status: fix bug with missing --ignore files
[git/jnareb-git.git] / builtin / commit.c
blob761ca0704749980bb4110e8e297b083bcdc6691d
1 /*
2 * Builtin "git commit"
4 * Copyright (c) 2007 Kristian Høgsberg <krh@redhat.com>
5 * Based on git-commit.sh by Junio C Hamano and Linus Torvalds
6 */
8 #include "cache.h"
9 #include "cache-tree.h"
10 #include "color.h"
11 #include "dir.h"
12 #include "builtin.h"
13 #include "diff.h"
14 #include "diffcore.h"
15 #include "commit.h"
16 #include "revision.h"
17 #include "wt-status.h"
18 #include "run-command.h"
19 #include "refs.h"
20 #include "log-tree.h"
21 #include "strbuf.h"
22 #include "utf8.h"
23 #include "parse-options.h"
24 #include "string-list.h"
25 #include "rerere.h"
26 #include "unpack-trees.h"
27 #include "quote.h"
29 static const char * const builtin_commit_usage[] = {
30 "git commit [options] [--] <filepattern>...",
31 NULL
34 static const char * const builtin_status_usage[] = {
35 "git status [options] [--] <filepattern>...",
36 NULL
39 static const char implicit_ident_advice[] =
40 "Your name and email address were configured automatically based\n"
41 "on your username and hostname. Please check that they are accurate.\n"
42 "You can suppress this message by setting them explicitly:\n"
43 "\n"
44 " git config --global user.name \"Your Name\"\n"
45 " git config --global user.email you@example.com\n"
46 "\n"
47 "If the identity used for this commit is wrong, you can fix it with:\n"
48 "\n"
49 " git commit --amend --author='Your Name <you@example.com>'\n";
51 static unsigned char head_sha1[20];
53 static char *use_message_buffer;
54 static const char commit_editmsg[] = "COMMIT_EDITMSG";
55 static struct lock_file index_lock; /* real index */
56 static struct lock_file false_lock; /* used only for partial commits */
57 static enum {
58 COMMIT_AS_IS = 1,
59 COMMIT_NORMAL,
60 COMMIT_PARTIAL,
61 } commit_style;
63 static const char *logfile, *force_author;
64 static const char *template_file;
65 static char *edit_message, *use_message;
66 static char *author_name, *author_email, *author_date;
67 static int all, edit_flag, also, interactive, only, amend, signoff;
68 static int quiet, verbose, no_verify, allow_empty, dry_run, renew_authorship;
69 static int no_post_rewrite;
70 static char *untracked_files_arg, *force_date;
72 * The default commit message cleanup mode will remove the lines
73 * beginning with # (shell comments) and leading and trailing
74 * whitespaces (empty lines or containing only whitespaces)
75 * if editor is used, and only the whitespaces if the message
76 * is specified explicitly.
78 static enum {
79 CLEANUP_SPACE,
80 CLEANUP_NONE,
81 CLEANUP_ALL,
82 } cleanup_mode;
83 static char *cleanup_arg;
85 static int use_editor = 1, initial_commit, in_merge, include_status = 1;
86 static int show_ignored_in_status;
87 static const char *only_include_assumed;
88 static struct strbuf message;
90 static int null_termination;
91 static enum {
92 STATUS_FORMAT_LONG,
93 STATUS_FORMAT_SHORT,
94 STATUS_FORMAT_PORCELAIN,
95 } status_format = STATUS_FORMAT_LONG;
97 static int opt_parse_m(const struct option *opt, const char *arg, int unset)
99 struct strbuf *buf = opt->value;
100 if (unset)
101 strbuf_setlen(buf, 0);
102 else {
103 strbuf_addstr(buf, arg);
104 strbuf_addstr(buf, "\n\n");
106 return 0;
109 static struct option builtin_commit_options[] = {
110 OPT__QUIET(&quiet),
111 OPT__VERBOSE(&verbose),
113 OPT_GROUP("Commit message options"),
114 OPT_FILENAME('F', "file", &logfile, "read log from file"),
115 OPT_STRING(0, "author", &force_author, "AUTHOR", "override author for commit"),
116 OPT_STRING(0, "date", &force_date, "DATE", "override date for commit"),
117 OPT_CALLBACK('m', "message", &message, "MESSAGE", "specify commit message", opt_parse_m),
118 OPT_STRING('c', "reedit-message", &edit_message, "COMMIT", "reuse and edit message from specified commit"),
119 OPT_STRING('C', "reuse-message", &use_message, "COMMIT", "reuse message from specified commit"),
120 OPT_BOOLEAN(0, "reset-author", &renew_authorship, "the commit is authored by me now (used with -C-c/--amend)"),
121 OPT_BOOLEAN('s', "signoff", &signoff, "add Signed-off-by:"),
122 OPT_FILENAME('t', "template", &template_file, "use specified template file"),
123 OPT_BOOLEAN('e', "edit", &edit_flag, "force edit of commit"),
124 OPT_STRING(0, "cleanup", &cleanup_arg, "default", "how to strip spaces and #comments from message"),
125 OPT_BOOLEAN(0, "status", &include_status, "include status in commit message template"),
126 /* end commit message options */
128 OPT_GROUP("Commit contents options"),
129 OPT_BOOLEAN('a', "all", &all, "commit all changed files"),
130 OPT_BOOLEAN('i', "include", &also, "add specified files to index for commit"),
131 OPT_BOOLEAN(0, "interactive", &interactive, "interactively add files"),
132 OPT_BOOLEAN('o', "only", &only, "commit only specified files"),
133 OPT_BOOLEAN('n', "no-verify", &no_verify, "bypass pre-commit hook"),
134 OPT_BOOLEAN(0, "dry-run", &dry_run, "show what would be committed"),
135 OPT_SET_INT(0, "short", &status_format, "show status concisely",
136 STATUS_FORMAT_SHORT),
137 OPT_SET_INT(0, "porcelain", &status_format,
138 "show porcelain output format", STATUS_FORMAT_PORCELAIN),
139 OPT_BOOLEAN('z', "null", &null_termination,
140 "terminate entries with NUL"),
141 OPT_BOOLEAN(0, "amend", &amend, "amend previous commit"),
142 OPT_BOOLEAN(0, "no-post-rewrite", &no_post_rewrite, "bypass post-rewrite hook"),
143 { OPTION_STRING, 'u', "untracked-files", &untracked_files_arg, "mode", "show untracked files, optional modes: all, normal, no. (Default: all)", PARSE_OPT_OPTARG, NULL, (intptr_t)"all" },
144 OPT_BOOLEAN(0, "allow-empty", &allow_empty, "ok to record an empty change"),
145 /* end commit contents options */
147 OPT_END()
150 static void rollback_index_files(void)
152 switch (commit_style) {
153 case COMMIT_AS_IS:
154 break; /* nothing to do */
155 case COMMIT_NORMAL:
156 rollback_lock_file(&index_lock);
157 break;
158 case COMMIT_PARTIAL:
159 rollback_lock_file(&index_lock);
160 rollback_lock_file(&false_lock);
161 break;
165 static int commit_index_files(void)
167 int err = 0;
169 switch (commit_style) {
170 case COMMIT_AS_IS:
171 break; /* nothing to do */
172 case COMMIT_NORMAL:
173 err = commit_lock_file(&index_lock);
174 break;
175 case COMMIT_PARTIAL:
176 err = commit_lock_file(&index_lock);
177 rollback_lock_file(&false_lock);
178 break;
181 return err;
185 * Take a union of paths in the index and the named tree (typically, "HEAD"),
186 * and return the paths that match the given pattern in list.
188 static int list_paths(struct string_list *list, const char *with_tree,
189 const char *prefix, const char **pattern)
191 int i;
192 char *m;
194 for (i = 0; pattern[i]; i++)
196 m = xcalloc(1, i);
198 if (with_tree)
199 overlay_tree_on_cache(with_tree, prefix);
201 for (i = 0; i < active_nr; i++) {
202 struct cache_entry *ce = active_cache[i];
203 struct string_list_item *item;
205 if (ce->ce_flags & CE_UPDATE)
206 continue;
207 if (!match_pathspec(pattern, ce->name, ce_namelen(ce), 0, m))
208 continue;
209 item = string_list_insert(ce->name, list);
210 if (ce_skip_worktree(ce))
211 item->util = item; /* better a valid pointer than a fake one */
214 return report_path_error(m, pattern, prefix ? strlen(prefix) : 0);
217 static void add_remove_files(struct string_list *list)
219 int i;
220 for (i = 0; i < list->nr; i++) {
221 struct stat st;
222 struct string_list_item *p = &(list->items[i]);
224 /* p->util is skip-worktree */
225 if (p->util)
226 continue;
228 if (!lstat(p->string, &st)) {
229 if (add_to_cache(p->string, &st, 0))
230 die("updating files failed");
231 } else
232 remove_file_from_cache(p->string);
236 static void create_base_index(void)
238 struct tree *tree;
239 struct unpack_trees_options opts;
240 struct tree_desc t;
242 if (initial_commit) {
243 discard_cache();
244 return;
247 memset(&opts, 0, sizeof(opts));
248 opts.head_idx = 1;
249 opts.index_only = 1;
250 opts.merge = 1;
251 opts.src_index = &the_index;
252 opts.dst_index = &the_index;
254 opts.fn = oneway_merge;
255 tree = parse_tree_indirect(head_sha1);
256 if (!tree)
257 die("failed to unpack HEAD tree object");
258 parse_tree(tree);
259 init_tree_desc(&t, tree->buffer, tree->size);
260 if (unpack_trees(1, &t, &opts))
261 exit(128); /* We've already reported the error, finish dying */
264 static void refresh_cache_or_die(int refresh_flags)
267 * refresh_flags contains REFRESH_QUIET, so the only errors
268 * are for unmerged entries.
270 if (refresh_cache(refresh_flags | REFRESH_IN_PORCELAIN))
271 die_resolve_conflict("commit");
274 static char *prepare_index(int argc, const char **argv, const char *prefix, int is_status)
276 int fd;
277 struct string_list partial;
278 const char **pathspec = NULL;
279 int refresh_flags = REFRESH_QUIET;
281 if (is_status)
282 refresh_flags |= REFRESH_UNMERGED;
283 if (interactive) {
284 if (interactive_add(argc, argv, prefix) != 0)
285 die("interactive add failed");
286 if (read_cache_preload(NULL) < 0)
287 die("index file corrupt");
288 commit_style = COMMIT_AS_IS;
289 return get_index_file();
292 if (*argv)
293 pathspec = get_pathspec(prefix, argv);
295 if (read_cache_preload(pathspec) < 0)
296 die("index file corrupt");
299 * Non partial, non as-is commit.
301 * (1) get the real index;
302 * (2) update the_index as necessary;
303 * (3) write the_index out to the real index (still locked);
304 * (4) return the name of the locked index file.
306 * The caller should run hooks on the locked real index, and
307 * (A) if all goes well, commit the real index;
308 * (B) on failure, rollback the real index.
310 if (all || (also && pathspec && *pathspec)) {
311 fd = hold_locked_index(&index_lock, 1);
312 add_files_to_cache(also ? prefix : NULL, pathspec, 0);
313 refresh_cache_or_die(refresh_flags);
314 if (write_cache(fd, active_cache, active_nr) ||
315 close_lock_file(&index_lock))
316 die("unable to write new_index file");
317 commit_style = COMMIT_NORMAL;
318 return index_lock.filename;
322 * As-is commit.
324 * (1) return the name of the real index file.
326 * The caller should run hooks on the real index,
327 * and create commit from the_index.
328 * We still need to refresh the index here.
330 if (!pathspec || !*pathspec) {
331 fd = hold_locked_index(&index_lock, 1);
332 refresh_cache_or_die(refresh_flags);
333 if (write_cache(fd, active_cache, active_nr) ||
334 commit_locked_index(&index_lock))
335 die("unable to write new_index file");
336 commit_style = COMMIT_AS_IS;
337 return get_index_file();
341 * A partial commit.
343 * (0) find the set of affected paths;
344 * (1) get lock on the real index file;
345 * (2) update the_index with the given paths;
346 * (3) write the_index out to the real index (still locked);
347 * (4) get lock on the false index file;
348 * (5) reset the_index from HEAD;
349 * (6) update the_index the same way as (2);
350 * (7) write the_index out to the false index file;
351 * (8) return the name of the false index file (still locked);
353 * The caller should run hooks on the locked false index, and
354 * create commit from it. Then
355 * (A) if all goes well, commit the real index;
356 * (B) on failure, rollback the real index;
357 * In either case, rollback the false index.
359 commit_style = COMMIT_PARTIAL;
361 if (in_merge)
362 die("cannot do a partial commit during a merge.");
364 memset(&partial, 0, sizeof(partial));
365 partial.strdup_strings = 1;
366 if (list_paths(&partial, initial_commit ? NULL : "HEAD", prefix, pathspec))
367 exit(1);
369 discard_cache();
370 if (read_cache() < 0)
371 die("cannot read the index");
373 fd = hold_locked_index(&index_lock, 1);
374 add_remove_files(&partial);
375 refresh_cache(REFRESH_QUIET);
376 if (write_cache(fd, active_cache, active_nr) ||
377 close_lock_file(&index_lock))
378 die("unable to write new_index file");
380 fd = hold_lock_file_for_update(&false_lock,
381 git_path("next-index-%"PRIuMAX,
382 (uintmax_t) getpid()),
383 LOCK_DIE_ON_ERROR);
385 create_base_index();
386 add_remove_files(&partial);
387 refresh_cache(REFRESH_QUIET);
389 if (write_cache(fd, active_cache, active_nr) ||
390 close_lock_file(&false_lock))
391 die("unable to write temporary index file");
393 discard_cache();
394 read_cache_from(false_lock.filename);
396 return false_lock.filename;
399 static int run_status(FILE *fp, const char *index_file, const char *prefix, int nowarn,
400 struct wt_status *s)
402 unsigned char sha1[20];
404 if (s->relative_paths)
405 s->prefix = prefix;
407 if (amend) {
408 s->amend = 1;
409 s->reference = "HEAD^1";
411 s->verbose = verbose;
412 s->index_file = index_file;
413 s->fp = fp;
414 s->nowarn = nowarn;
415 s->is_initial = get_sha1(s->reference, sha1) ? 1 : 0;
417 wt_status_collect(s);
419 switch (status_format) {
420 case STATUS_FORMAT_SHORT:
421 wt_shortstatus_print(s, null_termination);
422 break;
423 case STATUS_FORMAT_PORCELAIN:
424 wt_porcelain_print(s, null_termination);
425 break;
426 case STATUS_FORMAT_LONG:
427 wt_status_print(s);
428 break;
431 return s->commitable;
434 static int is_a_merge(const unsigned char *sha1)
436 struct commit *commit = lookup_commit(sha1);
437 if (!commit || parse_commit(commit))
438 die("could not parse HEAD commit");
439 return !!(commit->parents && commit->parents->next);
442 static const char sign_off_header[] = "Signed-off-by: ";
444 static void determine_author_info(void)
446 char *name, *email, *date;
448 name = getenv("GIT_AUTHOR_NAME");
449 email = getenv("GIT_AUTHOR_EMAIL");
450 date = getenv("GIT_AUTHOR_DATE");
452 if (use_message && !renew_authorship) {
453 const char *a, *lb, *rb, *eol;
455 a = strstr(use_message_buffer, "\nauthor ");
456 if (!a)
457 die("invalid commit: %s", use_message);
459 lb = strstr(a + 8, " <");
460 rb = strstr(a + 8, "> ");
461 eol = strchr(a + 8, '\n');
462 if (!lb || !rb || !eol)
463 die("invalid commit: %s", use_message);
465 name = xstrndup(a + 8, lb - (a + 8));
466 email = xstrndup(lb + 2, rb - (lb + 2));
467 date = xstrndup(rb + 2, eol - (rb + 2));
470 if (force_author) {
471 const char *lb = strstr(force_author, " <");
472 const char *rb = strchr(force_author, '>');
474 if (!lb || !rb)
475 die("malformed --author parameter");
476 name = xstrndup(force_author, lb - force_author);
477 email = xstrndup(lb + 2, rb - (lb + 2));
480 if (force_date)
481 date = force_date;
483 author_name = name;
484 author_email = email;
485 author_date = date;
488 static int ends_rfc2822_footer(struct strbuf *sb)
490 int ch;
491 int hit = 0;
492 int i, j, k;
493 int len = sb->len;
494 int first = 1;
495 const char *buf = sb->buf;
497 for (i = len - 1; i > 0; i--) {
498 if (hit && buf[i] == '\n')
499 break;
500 hit = (buf[i] == '\n');
503 while (i < len - 1 && buf[i] == '\n')
504 i++;
506 for (; i < len; i = k) {
507 for (k = i; k < len && buf[k] != '\n'; k++)
508 ; /* do nothing */
509 k++;
511 if ((buf[k] == ' ' || buf[k] == '\t') && !first)
512 continue;
514 first = 0;
516 for (j = 0; i + j < len; j++) {
517 ch = buf[i + j];
518 if (ch == ':')
519 break;
520 if (isalnum(ch) ||
521 (ch == '-'))
522 continue;
523 return 0;
526 return 1;
529 static int prepare_to_commit(const char *index_file, const char *prefix,
530 struct wt_status *s)
532 struct stat statbuf;
533 int commitable, saved_color_setting;
534 struct strbuf sb = STRBUF_INIT;
535 char *buffer;
536 FILE *fp;
537 const char *hook_arg1 = NULL;
538 const char *hook_arg2 = NULL;
539 int ident_shown = 0;
541 if (!no_verify && run_hook(index_file, "pre-commit", NULL))
542 return 0;
544 if (message.len) {
545 strbuf_addbuf(&sb, &message);
546 hook_arg1 = "message";
547 } else if (logfile && !strcmp(logfile, "-")) {
548 if (isatty(0))
549 fprintf(stderr, "(reading log message from standard input)\n");
550 if (strbuf_read(&sb, 0, 0) < 0)
551 die_errno("could not read log from standard input");
552 hook_arg1 = "message";
553 } else if (logfile) {
554 if (strbuf_read_file(&sb, logfile, 0) < 0)
555 die_errno("could not read log file '%s'",
556 logfile);
557 hook_arg1 = "message";
558 } else if (use_message) {
559 buffer = strstr(use_message_buffer, "\n\n");
560 if (!buffer || buffer[2] == '\0')
561 die("commit has empty message");
562 strbuf_add(&sb, buffer + 2, strlen(buffer + 2));
563 hook_arg1 = "commit";
564 hook_arg2 = use_message;
565 } else if (!stat(git_path("MERGE_MSG"), &statbuf)) {
566 if (strbuf_read_file(&sb, git_path("MERGE_MSG"), 0) < 0)
567 die_errno("could not read MERGE_MSG");
568 hook_arg1 = "merge";
569 } else if (!stat(git_path("SQUASH_MSG"), &statbuf)) {
570 if (strbuf_read_file(&sb, git_path("SQUASH_MSG"), 0) < 0)
571 die_errno("could not read SQUASH_MSG");
572 hook_arg1 = "squash";
573 } else if (template_file && !stat(template_file, &statbuf)) {
574 if (strbuf_read_file(&sb, template_file, 0) < 0)
575 die_errno("could not read '%s'", template_file);
576 hook_arg1 = "template";
580 * This final case does not modify the template message,
581 * it just sets the argument to the prepare-commit-msg hook.
583 else if (in_merge)
584 hook_arg1 = "merge";
586 fp = fopen(git_path(commit_editmsg), "w");
587 if (fp == NULL)
588 die_errno("could not open '%s'", git_path(commit_editmsg));
590 if (cleanup_mode != CLEANUP_NONE)
591 stripspace(&sb, 0);
593 if (signoff) {
594 struct strbuf sob = STRBUF_INIT;
595 int i;
597 strbuf_addstr(&sob, sign_off_header);
598 strbuf_addstr(&sob, fmt_name(getenv("GIT_COMMITTER_NAME"),
599 getenv("GIT_COMMITTER_EMAIL")));
600 strbuf_addch(&sob, '\n');
601 for (i = sb.len - 1; i > 0 && sb.buf[i - 1] != '\n'; i--)
602 ; /* do nothing */
603 if (prefixcmp(sb.buf + i, sob.buf)) {
604 if (!i || !ends_rfc2822_footer(&sb))
605 strbuf_addch(&sb, '\n');
606 strbuf_addbuf(&sb, &sob);
608 strbuf_release(&sob);
611 if (fwrite(sb.buf, 1, sb.len, fp) < sb.len)
612 die_errno("could not write commit template");
614 strbuf_release(&sb);
616 determine_author_info();
618 /* This checks if committer ident is explicitly given */
619 git_committer_info(0);
620 if (use_editor && include_status) {
621 char *author_ident;
622 const char *committer_ident;
624 if (in_merge)
625 fprintf(fp,
626 "#\n"
627 "# It looks like you may be committing a MERGE.\n"
628 "# If this is not correct, please remove the file\n"
629 "# %s\n"
630 "# and try again.\n"
631 "#\n",
632 git_path("MERGE_HEAD"));
634 fprintf(fp,
635 "\n"
636 "# Please enter the commit message for your changes.");
637 if (cleanup_mode == CLEANUP_ALL)
638 fprintf(fp,
639 " Lines starting\n"
640 "# with '#' will be ignored, and an empty"
641 " message aborts the commit.\n");
642 else /* CLEANUP_SPACE, that is. */
643 fprintf(fp,
644 " Lines starting\n"
645 "# with '#' will be kept; you may remove them"
646 " yourself if you want to.\n"
647 "# An empty message aborts the commit.\n");
648 if (only_include_assumed)
649 fprintf(fp, "# %s\n", only_include_assumed);
651 author_ident = xstrdup(fmt_name(author_name, author_email));
652 committer_ident = fmt_name(getenv("GIT_COMMITTER_NAME"),
653 getenv("GIT_COMMITTER_EMAIL"));
654 if (strcmp(author_ident, committer_ident))
655 fprintf(fp,
656 "%s"
657 "# Author: %s\n",
658 ident_shown++ ? "" : "#\n",
659 author_ident);
660 free(author_ident);
662 if (!user_ident_sufficiently_given())
663 fprintf(fp,
664 "%s"
665 "# Committer: %s\n",
666 ident_shown++ ? "" : "#\n",
667 committer_ident);
669 if (ident_shown)
670 fprintf(fp, "#\n");
672 saved_color_setting = s->use_color;
673 s->use_color = 0;
674 commitable = run_status(fp, index_file, prefix, 1, s);
675 s->use_color = saved_color_setting;
676 } else {
677 unsigned char sha1[20];
678 const char *parent = "HEAD";
680 if (!active_nr && read_cache() < 0)
681 die("Cannot read index");
683 if (amend)
684 parent = "HEAD^1";
686 if (get_sha1(parent, sha1))
687 commitable = !!active_nr;
688 else
689 commitable = index_differs_from(parent, 0);
692 fclose(fp);
694 if (!commitable && !in_merge && !allow_empty &&
695 !(amend && is_a_merge(head_sha1))) {
696 run_status(stdout, index_file, prefix, 0, s);
697 return 0;
701 * Re-read the index as pre-commit hook could have updated it,
702 * and write it out as a tree. We must do this before we invoke
703 * the editor and after we invoke run_status above.
705 discard_cache();
706 read_cache_from(index_file);
707 if (!active_cache_tree)
708 active_cache_tree = cache_tree();
709 if (cache_tree_update(active_cache_tree,
710 active_cache, active_nr, 0, 0) < 0) {
711 error("Error building trees");
712 return 0;
715 if (run_hook(index_file, "prepare-commit-msg",
716 git_path(commit_editmsg), hook_arg1, hook_arg2, NULL))
717 return 0;
719 if (use_editor) {
720 char index[PATH_MAX];
721 const char *env[2] = { index, NULL };
722 snprintf(index, sizeof(index), "GIT_INDEX_FILE=%s", index_file);
723 if (launch_editor(git_path(commit_editmsg), NULL, env)) {
724 fprintf(stderr,
725 "Please supply the message using either -m or -F option.\n");
726 exit(1);
730 if (!no_verify &&
731 run_hook(index_file, "commit-msg", git_path(commit_editmsg), NULL)) {
732 return 0;
735 return 1;
739 * Find out if the message in the strbuf contains only whitespace and
740 * Signed-off-by lines.
742 static int message_is_empty(struct strbuf *sb)
744 struct strbuf tmpl = STRBUF_INIT;
745 const char *nl;
746 int eol, i, start = 0;
748 if (cleanup_mode == CLEANUP_NONE && sb->len)
749 return 0;
751 /* See if the template is just a prefix of the message. */
752 if (template_file && strbuf_read_file(&tmpl, template_file, 0) > 0) {
753 stripspace(&tmpl, cleanup_mode == CLEANUP_ALL);
754 if (start + tmpl.len <= sb->len &&
755 memcmp(tmpl.buf, sb->buf + start, tmpl.len) == 0)
756 start += tmpl.len;
758 strbuf_release(&tmpl);
760 /* Check if the rest is just whitespace and Signed-of-by's. */
761 for (i = start; i < sb->len; i++) {
762 nl = memchr(sb->buf + i, '\n', sb->len - i);
763 if (nl)
764 eol = nl - sb->buf;
765 else
766 eol = sb->len;
768 if (strlen(sign_off_header) <= eol - i &&
769 !prefixcmp(sb->buf + i, sign_off_header)) {
770 i = eol;
771 continue;
773 while (i < eol)
774 if (!isspace(sb->buf[i++]))
775 return 0;
778 return 1;
781 static const char *find_author_by_nickname(const char *name)
783 struct rev_info revs;
784 struct commit *commit;
785 struct strbuf buf = STRBUF_INIT;
786 const char *av[20];
787 int ac = 0;
789 init_revisions(&revs, NULL);
790 strbuf_addf(&buf, "--author=%s", name);
791 av[++ac] = "--all";
792 av[++ac] = "-i";
793 av[++ac] = buf.buf;
794 av[++ac] = NULL;
795 setup_revisions(ac, av, &revs, NULL);
796 prepare_revision_walk(&revs);
797 commit = get_revision(&revs);
798 if (commit) {
799 struct pretty_print_context ctx = {0};
800 ctx.date_mode = DATE_NORMAL;
801 strbuf_release(&buf);
802 format_commit_message(commit, "%an <%ae>", &buf, &ctx);
803 return strbuf_detach(&buf, NULL);
805 die("No existing author found with '%s'", name);
809 static void handle_untracked_files_arg(struct wt_status *s)
811 if (!untracked_files_arg)
812 ; /* default already initialized */
813 else if (!strcmp(untracked_files_arg, "no"))
814 s->show_untracked_files = SHOW_NO_UNTRACKED_FILES;
815 else if (!strcmp(untracked_files_arg, "normal"))
816 s->show_untracked_files = SHOW_NORMAL_UNTRACKED_FILES;
817 else if (!strcmp(untracked_files_arg, "all"))
818 s->show_untracked_files = SHOW_ALL_UNTRACKED_FILES;
819 else
820 die("Invalid untracked files mode '%s'", untracked_files_arg);
823 static int parse_and_validate_options(int argc, const char *argv[],
824 const char * const usage[],
825 const char *prefix,
826 struct wt_status *s)
828 int f = 0;
830 argc = parse_options(argc, argv, prefix, builtin_commit_options, usage,
833 if (force_author && !strchr(force_author, '>'))
834 force_author = find_author_by_nickname(force_author);
836 if (force_author && renew_authorship)
837 die("Using both --reset-author and --author does not make sense");
839 if (logfile || message.len || use_message)
840 use_editor = 0;
841 if (edit_flag)
842 use_editor = 1;
843 if (!use_editor)
844 setenv("GIT_EDITOR", ":", 1);
846 if (get_sha1("HEAD", head_sha1))
847 initial_commit = 1;
849 /* Sanity check options */
850 if (amend && initial_commit)
851 die("You have nothing to amend.");
852 if (amend && in_merge)
853 die("You are in the middle of a merge -- cannot amend.");
855 if (use_message)
856 f++;
857 if (edit_message)
858 f++;
859 if (logfile)
860 f++;
861 if (f > 1)
862 die("Only one of -c/-C/-F can be used.");
863 if (message.len && f > 0)
864 die("Option -m cannot be combined with -c/-C/-F.");
865 if (edit_message)
866 use_message = edit_message;
867 if (amend && !use_message)
868 use_message = "HEAD";
869 if (!use_message && renew_authorship)
870 die("--reset-author can be used only with -C, -c or --amend.");
871 if (use_message) {
872 unsigned char sha1[20];
873 static char utf8[] = "UTF-8";
874 const char *out_enc;
875 char *enc, *end;
876 struct commit *commit;
878 if (get_sha1(use_message, sha1))
879 die("could not lookup commit %s", use_message);
880 commit = lookup_commit_reference(sha1);
881 if (!commit || parse_commit(commit))
882 die("could not parse commit %s", use_message);
884 enc = strstr(commit->buffer, "\nencoding");
885 if (enc) {
886 end = strchr(enc + 10, '\n');
887 enc = xstrndup(enc + 10, end - (enc + 10));
888 } else {
889 enc = utf8;
891 out_enc = git_commit_encoding ? git_commit_encoding : utf8;
893 if (strcmp(out_enc, enc))
894 use_message_buffer =
895 reencode_string(commit->buffer, out_enc, enc);
898 * If we failed to reencode the buffer, just copy it
899 * byte for byte so the user can try to fix it up.
900 * This also handles the case where input and output
901 * encodings are identical.
903 if (use_message_buffer == NULL)
904 use_message_buffer = xstrdup(commit->buffer);
905 if (enc != utf8)
906 free(enc);
909 if (!!also + !!only + !!all + !!interactive > 1)
910 die("Only one of --include/--only/--all/--interactive can be used.");
911 if (argc == 0 && (also || (only && !amend)))
912 die("No paths with --include/--only does not make sense.");
913 if (argc == 0 && only && amend)
914 only_include_assumed = "Clever... amending the last one with dirty index.";
915 if (argc > 0 && !also && !only)
916 only_include_assumed = "Explicit paths specified without -i nor -o; assuming --only paths...";
917 if (!cleanup_arg || !strcmp(cleanup_arg, "default"))
918 cleanup_mode = use_editor ? CLEANUP_ALL : CLEANUP_SPACE;
919 else if (!strcmp(cleanup_arg, "verbatim"))
920 cleanup_mode = CLEANUP_NONE;
921 else if (!strcmp(cleanup_arg, "whitespace"))
922 cleanup_mode = CLEANUP_SPACE;
923 else if (!strcmp(cleanup_arg, "strip"))
924 cleanup_mode = CLEANUP_ALL;
925 else
926 die("Invalid cleanup mode %s", cleanup_arg);
928 handle_untracked_files_arg(s);
930 if (all && argc > 0)
931 die("Paths with -a does not make sense.");
932 else if (interactive && argc > 0)
933 die("Paths with --interactive does not make sense.");
935 if (null_termination && status_format == STATUS_FORMAT_LONG)
936 status_format = STATUS_FORMAT_PORCELAIN;
937 if (status_format != STATUS_FORMAT_LONG)
938 dry_run = 1;
940 return argc;
943 static int dry_run_commit(int argc, const char **argv, const char *prefix,
944 struct wt_status *s)
946 int commitable;
947 const char *index_file;
949 index_file = prepare_index(argc, argv, prefix, 1);
950 commitable = run_status(stdout, index_file, prefix, 0, s);
951 rollback_index_files();
953 return commitable ? 0 : 1;
956 static int parse_status_slot(const char *var, int offset)
958 if (!strcasecmp(var+offset, "header"))
959 return WT_STATUS_HEADER;
960 if (!strcasecmp(var+offset, "updated")
961 || !strcasecmp(var+offset, "added"))
962 return WT_STATUS_UPDATED;
963 if (!strcasecmp(var+offset, "changed"))
964 return WT_STATUS_CHANGED;
965 if (!strcasecmp(var+offset, "untracked"))
966 return WT_STATUS_UNTRACKED;
967 if (!strcasecmp(var+offset, "nobranch"))
968 return WT_STATUS_NOBRANCH;
969 if (!strcasecmp(var+offset, "unmerged"))
970 return WT_STATUS_UNMERGED;
971 return -1;
974 static int git_status_config(const char *k, const char *v, void *cb)
976 struct wt_status *s = cb;
978 if (!strcmp(k, "status.submodulesummary")) {
979 int is_bool;
980 s->submodule_summary = git_config_bool_or_int(k, v, &is_bool);
981 if (is_bool && s->submodule_summary)
982 s->submodule_summary = -1;
983 return 0;
985 if (!strcmp(k, "status.color") || !strcmp(k, "color.status")) {
986 s->use_color = git_config_colorbool(k, v, -1);
987 return 0;
989 if (!prefixcmp(k, "status.color.") || !prefixcmp(k, "color.status.")) {
990 int slot = parse_status_slot(k, 13);
991 if (slot < 0)
992 return 0;
993 if (!v)
994 return config_error_nonbool(k);
995 color_parse(v, k, s->color_palette[slot]);
996 return 0;
998 if (!strcmp(k, "status.relativepaths")) {
999 s->relative_paths = git_config_bool(k, v);
1000 return 0;
1002 if (!strcmp(k, "status.showuntrackedfiles")) {
1003 if (!v)
1004 return config_error_nonbool(k);
1005 else if (!strcmp(v, "no"))
1006 s->show_untracked_files = SHOW_NO_UNTRACKED_FILES;
1007 else if (!strcmp(v, "normal"))
1008 s->show_untracked_files = SHOW_NORMAL_UNTRACKED_FILES;
1009 else if (!strcmp(v, "all"))
1010 s->show_untracked_files = SHOW_ALL_UNTRACKED_FILES;
1011 else
1012 return error("Invalid untracked files mode '%s'", v);
1013 return 0;
1015 return git_diff_ui_config(k, v, NULL);
1018 int cmd_status(int argc, const char **argv, const char *prefix)
1020 struct wt_status s;
1021 unsigned char sha1[20];
1022 static struct option builtin_status_options[] = {
1023 OPT__VERBOSE(&verbose),
1024 OPT_SET_INT('s', "short", &status_format,
1025 "show status concisely", STATUS_FORMAT_SHORT),
1026 OPT_SET_INT(0, "porcelain", &status_format,
1027 "show porcelain output format",
1028 STATUS_FORMAT_PORCELAIN),
1029 OPT_BOOLEAN('z', "null", &null_termination,
1030 "terminate entries with NUL"),
1031 { OPTION_STRING, 'u', "untracked-files", &untracked_files_arg,
1032 "mode",
1033 "show untracked files, optional modes: all, normal, no. (Default: all)",
1034 PARSE_OPT_OPTARG, NULL, (intptr_t)"all" },
1035 OPT_BOOLEAN(0, "ignored", &show_ignored_in_status,
1036 "show ignored files"),
1037 OPT_END(),
1040 if (null_termination && status_format == STATUS_FORMAT_LONG)
1041 status_format = STATUS_FORMAT_PORCELAIN;
1043 wt_status_prepare(&s);
1044 git_config(git_status_config, &s);
1045 in_merge = file_exists(git_path("MERGE_HEAD"));
1046 argc = parse_options(argc, argv, prefix,
1047 builtin_status_options,
1048 builtin_status_usage, 0);
1049 handle_untracked_files_arg(&s);
1050 if (show_ignored_in_status)
1051 s.show_ignored_files = 1;
1052 if (*argv)
1053 s.pathspec = get_pathspec(prefix, argv);
1055 read_cache_preload(s.pathspec);
1056 refresh_index(&the_index, REFRESH_QUIET|REFRESH_UNMERGED, s.pathspec, NULL, NULL);
1057 s.is_initial = get_sha1(s.reference, sha1) ? 1 : 0;
1058 s.in_merge = in_merge;
1059 wt_status_collect(&s);
1061 if (s.relative_paths)
1062 s.prefix = prefix;
1063 if (s.use_color == -1)
1064 s.use_color = git_use_color_default;
1065 if (diff_use_color_default == -1)
1066 diff_use_color_default = git_use_color_default;
1068 switch (status_format) {
1069 case STATUS_FORMAT_SHORT:
1070 wt_shortstatus_print(&s, null_termination);
1071 break;
1072 case STATUS_FORMAT_PORCELAIN:
1073 wt_porcelain_print(&s, null_termination);
1074 break;
1075 case STATUS_FORMAT_LONG:
1076 s.verbose = verbose;
1077 wt_status_print(&s);
1078 break;
1080 return 0;
1083 static void print_summary(const char *prefix, const unsigned char *sha1)
1085 struct rev_info rev;
1086 struct commit *commit;
1087 struct strbuf format = STRBUF_INIT;
1088 unsigned char junk_sha1[20];
1089 const char *head = resolve_ref("HEAD", junk_sha1, 0, NULL);
1090 struct pretty_print_context pctx = {0};
1091 struct strbuf author_ident = STRBUF_INIT;
1092 struct strbuf committer_ident = STRBUF_INIT;
1094 commit = lookup_commit(sha1);
1095 if (!commit)
1096 die("couldn't look up newly created commit");
1097 if (!commit || parse_commit(commit))
1098 die("could not parse newly created commit");
1100 strbuf_addstr(&format, "format:%h] %s");
1102 format_commit_message(commit, "%an <%ae>", &author_ident, &pctx);
1103 format_commit_message(commit, "%cn <%ce>", &committer_ident, &pctx);
1104 if (strbuf_cmp(&author_ident, &committer_ident)) {
1105 strbuf_addstr(&format, "\n Author: ");
1106 strbuf_addbuf_percentquote(&format, &author_ident);
1108 if (!user_ident_sufficiently_given()) {
1109 strbuf_addstr(&format, "\n Committer: ");
1110 strbuf_addbuf_percentquote(&format, &committer_ident);
1111 if (advice_implicit_identity) {
1112 strbuf_addch(&format, '\n');
1113 strbuf_addstr(&format, implicit_ident_advice);
1116 strbuf_release(&author_ident);
1117 strbuf_release(&committer_ident);
1119 init_revisions(&rev, prefix);
1120 setup_revisions(0, NULL, &rev, NULL);
1122 rev.abbrev = 0;
1123 rev.diff = 1;
1124 rev.diffopt.output_format =
1125 DIFF_FORMAT_SHORTSTAT | DIFF_FORMAT_SUMMARY;
1127 rev.verbose_header = 1;
1128 rev.show_root_diff = 1;
1129 get_commit_format(format.buf, &rev);
1130 rev.always_show_header = 0;
1131 rev.diffopt.detect_rename = 1;
1132 rev.diffopt.rename_limit = 100;
1133 rev.diffopt.break_opt = 0;
1134 diff_setup_done(&rev.diffopt);
1136 printf("[%s%s ",
1137 !prefixcmp(head, "refs/heads/") ?
1138 head + 11 :
1139 !strcmp(head, "HEAD") ?
1140 "detached HEAD" :
1141 head,
1142 initial_commit ? " (root-commit)" : "");
1144 if (!log_tree_commit(&rev, commit)) {
1145 struct pretty_print_context ctx = {0};
1146 struct strbuf buf = STRBUF_INIT;
1147 ctx.date_mode = DATE_NORMAL;
1148 format_commit_message(commit, format.buf + 7, &buf, &ctx);
1149 printf("%s\n", buf.buf);
1150 strbuf_release(&buf);
1152 strbuf_release(&format);
1155 static int git_commit_config(const char *k, const char *v, void *cb)
1157 struct wt_status *s = cb;
1159 if (!strcmp(k, "commit.template"))
1160 return git_config_pathname(&template_file, k, v);
1161 if (!strcmp(k, "commit.status")) {
1162 include_status = git_config_bool(k, v);
1163 return 0;
1166 return git_status_config(k, v, s);
1169 static const char post_rewrite_hook[] = "hooks/post-rewrite";
1171 static int run_rewrite_hook(const unsigned char *oldsha1,
1172 const unsigned char *newsha1)
1174 /* oldsha1 SP newsha1 LF NUL */
1175 static char buf[2*40 + 3];
1176 struct child_process proc;
1177 const char *argv[3];
1178 int code;
1179 size_t n;
1181 if (access(git_path(post_rewrite_hook), X_OK) < 0)
1182 return 0;
1184 argv[0] = git_path(post_rewrite_hook);
1185 argv[1] = "amend";
1186 argv[2] = NULL;
1188 memset(&proc, 0, sizeof(proc));
1189 proc.argv = argv;
1190 proc.in = -1;
1191 proc.stdout_to_stderr = 1;
1193 code = start_command(&proc);
1194 if (code)
1195 return code;
1196 n = snprintf(buf, sizeof(buf), "%s %s\n",
1197 sha1_to_hex(oldsha1), sha1_to_hex(newsha1));
1198 write_in_full(proc.in, buf, n);
1199 close(proc.in);
1200 return finish_command(&proc);
1203 int cmd_commit(int argc, const char **argv, const char *prefix)
1205 struct strbuf sb = STRBUF_INIT;
1206 const char *index_file, *reflog_msg;
1207 char *nl, *p;
1208 unsigned char commit_sha1[20];
1209 struct ref_lock *ref_lock;
1210 struct commit_list *parents = NULL, **pptr = &parents;
1211 struct stat statbuf;
1212 int allow_fast_forward = 1;
1213 struct wt_status s;
1215 wt_status_prepare(&s);
1216 git_config(git_commit_config, &s);
1217 in_merge = file_exists(git_path("MERGE_HEAD"));
1218 s.in_merge = in_merge;
1220 if (s.use_color == -1)
1221 s.use_color = git_use_color_default;
1222 argc = parse_and_validate_options(argc, argv, builtin_commit_usage,
1223 prefix, &s);
1224 if (dry_run) {
1225 if (diff_use_color_default == -1)
1226 diff_use_color_default = git_use_color_default;
1227 return dry_run_commit(argc, argv, prefix, &s);
1229 index_file = prepare_index(argc, argv, prefix, 0);
1231 /* Set up everything for writing the commit object. This includes
1232 running hooks, writing the trees, and interacting with the user. */
1233 if (!prepare_to_commit(index_file, prefix, &s)) {
1234 rollback_index_files();
1235 return 1;
1238 /* Determine parents */
1239 if (initial_commit) {
1240 reflog_msg = "commit (initial)";
1241 } else if (amend) {
1242 struct commit_list *c;
1243 struct commit *commit;
1245 reflog_msg = "commit (amend)";
1246 commit = lookup_commit(head_sha1);
1247 if (!commit || parse_commit(commit))
1248 die("could not parse HEAD commit");
1250 for (c = commit->parents; c; c = c->next)
1251 pptr = &commit_list_insert(c->item, pptr)->next;
1252 } else if (in_merge) {
1253 struct strbuf m = STRBUF_INIT;
1254 FILE *fp;
1256 reflog_msg = "commit (merge)";
1257 pptr = &commit_list_insert(lookup_commit(head_sha1), pptr)->next;
1258 fp = fopen(git_path("MERGE_HEAD"), "r");
1259 if (fp == NULL)
1260 die_errno("could not open '%s' for reading",
1261 git_path("MERGE_HEAD"));
1262 while (strbuf_getline(&m, fp, '\n') != EOF) {
1263 unsigned char sha1[20];
1264 if (get_sha1_hex(m.buf, sha1) < 0)
1265 die("Corrupt MERGE_HEAD file (%s)", m.buf);
1266 pptr = &commit_list_insert(lookup_commit(sha1), pptr)->next;
1268 fclose(fp);
1269 strbuf_release(&m);
1270 if (!stat(git_path("MERGE_MODE"), &statbuf)) {
1271 if (strbuf_read_file(&sb, git_path("MERGE_MODE"), 0) < 0)
1272 die_errno("could not read MERGE_MODE");
1273 if (!strcmp(sb.buf, "no-ff"))
1274 allow_fast_forward = 0;
1276 if (allow_fast_forward)
1277 parents = reduce_heads(parents);
1278 } else {
1279 reflog_msg = "commit";
1280 pptr = &commit_list_insert(lookup_commit(head_sha1), pptr)->next;
1283 /* Finally, get the commit message */
1284 strbuf_reset(&sb);
1285 if (strbuf_read_file(&sb, git_path(commit_editmsg), 0) < 0) {
1286 int saved_errno = errno;
1287 rollback_index_files();
1288 die("could not read commit message: %s", strerror(saved_errno));
1291 /* Truncate the message just before the diff, if any. */
1292 if (verbose) {
1293 p = strstr(sb.buf, "\ndiff --git ");
1294 if (p != NULL)
1295 strbuf_setlen(&sb, p - sb.buf + 1);
1298 if (cleanup_mode != CLEANUP_NONE)
1299 stripspace(&sb, cleanup_mode == CLEANUP_ALL);
1300 if (message_is_empty(&sb)) {
1301 rollback_index_files();
1302 fprintf(stderr, "Aborting commit due to empty commit message.\n");
1303 exit(1);
1306 if (commit_tree(sb.buf, active_cache_tree->sha1, parents, commit_sha1,
1307 fmt_ident(author_name, author_email, author_date,
1308 IDENT_ERROR_ON_NO_NAME))) {
1309 rollback_index_files();
1310 die("failed to write commit object");
1313 ref_lock = lock_any_ref_for_update("HEAD",
1314 initial_commit ? NULL : head_sha1,
1317 nl = strchr(sb.buf, '\n');
1318 if (nl)
1319 strbuf_setlen(&sb, nl + 1 - sb.buf);
1320 else
1321 strbuf_addch(&sb, '\n');
1322 strbuf_insert(&sb, 0, reflog_msg, strlen(reflog_msg));
1323 strbuf_insert(&sb, strlen(reflog_msg), ": ", 2);
1325 if (!ref_lock) {
1326 rollback_index_files();
1327 die("cannot lock HEAD ref");
1329 if (write_ref_sha1(ref_lock, commit_sha1, sb.buf) < 0) {
1330 rollback_index_files();
1331 die("cannot update HEAD ref");
1334 unlink(git_path("MERGE_HEAD"));
1335 unlink(git_path("MERGE_MSG"));
1336 unlink(git_path("MERGE_MODE"));
1337 unlink(git_path("SQUASH_MSG"));
1339 if (commit_index_files())
1340 die ("Repository has been updated, but unable to write\n"
1341 "new_index file. Check that disk is not full or quota is\n"
1342 "not exceeded, and then \"git reset HEAD\" to recover.");
1344 rerere(0);
1345 run_hook(get_index_file(), "post-commit", NULL);
1346 if (amend && !no_post_rewrite) {
1347 struct notes_rewrite_cfg *cfg;
1348 cfg = init_copy_notes_for_rewrite("amend");
1349 if (cfg) {
1350 copy_note_for_rewrite(cfg, head_sha1, commit_sha1);
1351 finish_copy_notes_for_rewrite(cfg);
1353 run_rewrite_hook(head_sha1, commit_sha1);
1355 if (!quiet)
1356 print_summary(prefix, commit_sha1);
1358 return 0;