4 * Copyright (c) 2007 Kristian Høgsberg <krh@redhat.com>
5 * Based on git-commit.sh by Junio C Hamano and Linus Torvalds
9 #include "cache-tree.h"
17 #include "wt-status.h"
18 #include "run-command.h"
23 #include "parse-options.h"
24 #include "string-list.h"
26 #include "unpack-trees.h"
29 static const char * const builtin_commit_usage[] = {
30 "git commit [options] [--] <filepattern>...",
34 static const char * const builtin_status_usage[] = {
35 "git status [options] [--] <filepattern>...",
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"
44 " git config --global user.name Your Name\n"
45 " git config --global user.email you@example.com\n"
47 "If the identity used for this commit is wrong, you can fix it with:\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 */
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 char *untracked_files_arg, *force_date;
71 * The default commit message cleanup mode will remove the lines
72 * beginning with # (shell comments) and leading and trailing
73 * whitespaces (empty lines or containing only whitespaces)
74 * if editor is used, and only the whitespaces if the message
75 * is specified explicitly.
82 static char *cleanup_arg;
84 static int use_editor = 1, initial_commit, in_merge, include_status = 1;
85 static const char *only_include_assumed;
86 static struct strbuf message;
88 static int null_termination;
92 STATUS_FORMAT_PORCELAIN,
93 } status_format = STATUS_FORMAT_LONG;
95 static int opt_parse_m(const struct option *opt, const char *arg, int unset)
97 struct strbuf *buf = opt->value;
99 strbuf_setlen(buf, 0);
101 strbuf_addstr(buf, arg);
102 strbuf_addstr(buf, "\n\n");
107 static struct option builtin_commit_options[] = {
109 OPT__VERBOSE(&verbose),
111 OPT_GROUP("Commit message options"),
112 OPT_FILENAME('F', "file", &logfile, "read log from file"),
113 OPT_STRING(0, "author", &force_author, "AUTHOR", "override author for commit"),
114 OPT_STRING(0, "date", &force_date, "DATE", "override date for commit"),
115 OPT_CALLBACK('m', "message", &message, "MESSAGE", "specify commit message", opt_parse_m),
116 OPT_STRING('c', "reedit-message", &edit_message, "COMMIT", "reuse and edit message from specified commit"),
117 OPT_STRING('C', "reuse-message", &use_message, "COMMIT", "reuse message from specified commit"),
118 OPT_BOOLEAN(0, "reset-author", &renew_authorship, "the commit is authored by me now (used with -C-c/--amend)"),
119 OPT_BOOLEAN('s', "signoff", &signoff, "add Signed-off-by:"),
120 OPT_FILENAME('t', "template", &template_file, "use specified template file"),
121 OPT_BOOLEAN('e', "edit", &edit_flag, "force edit of commit"),
122 OPT_STRING(0, "cleanup", &cleanup_arg, "default", "how to strip spaces and #comments from message"),
123 OPT_BOOLEAN(0, "status", &include_status, "include status in commit message template"),
124 /* end commit message options */
126 OPT_GROUP("Commit contents options"),
127 OPT_BOOLEAN('a', "all", &all, "commit all changed files"),
128 OPT_BOOLEAN('i', "include", &also, "add specified files to index for commit"),
129 OPT_BOOLEAN(0, "interactive", &interactive, "interactively add files"),
130 OPT_BOOLEAN('o', "only", &only, "commit only specified files"),
131 OPT_BOOLEAN('n', "no-verify", &no_verify, "bypass pre-commit hook"),
132 OPT_BOOLEAN(0, "dry-run", &dry_run, "show what would be committed"),
133 OPT_SET_INT(0, "short", &status_format, "show status concisely",
134 STATUS_FORMAT_SHORT),
135 OPT_SET_INT(0, "porcelain", &status_format,
136 "show porcelain output format", STATUS_FORMAT_PORCELAIN),
137 OPT_BOOLEAN('z', "null", &null_termination,
138 "terminate entries with NUL"),
139 OPT_BOOLEAN(0, "amend", &amend, "amend previous commit"),
140 { 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" },
141 OPT_BOOLEAN(0, "allow-empty", &allow_empty, "ok to record an empty change"),
142 /* end commit contents options */
147 static void rollback_index_files(void)
149 switch (commit_style) {
151 break; /* nothing to do */
153 rollback_lock_file(&index_lock);
156 rollback_lock_file(&index_lock);
157 rollback_lock_file(&false_lock);
162 static int commit_index_files(void)
166 switch (commit_style) {
168 break; /* nothing to do */
170 err = commit_lock_file(&index_lock);
173 err = commit_lock_file(&index_lock);
174 rollback_lock_file(&false_lock);
182 * Take a union of paths in the index and the named tree (typically, "HEAD"),
183 * and return the paths that match the given pattern in list.
185 static int list_paths(struct string_list *list, const char *with_tree,
186 const char *prefix, const char **pattern)
191 for (i = 0; pattern[i]; i++)
196 overlay_tree_on_cache(with_tree, prefix);
198 for (i = 0; i < active_nr; i++) {
199 struct cache_entry *ce = active_cache[i];
200 struct string_list_item *item;
202 if (ce->ce_flags & CE_UPDATE)
204 if (!match_pathspec(pattern, ce->name, ce_namelen(ce), 0, m))
206 item = string_list_insert(ce->name, list);
207 if (ce_skip_worktree(ce))
208 item->util = item; /* better a valid pointer than a fake one */
211 return report_path_error(m, pattern, prefix ? strlen(prefix) : 0);
214 static void add_remove_files(struct string_list *list)
217 for (i = 0; i < list->nr; i++) {
219 struct string_list_item *p = &(list->items[i]);
221 /* p->util is skip-worktree */
225 if (!lstat(p->string, &st)) {
226 if (add_to_cache(p->string, &st, 0))
227 die("updating files failed");
229 remove_file_from_cache(p->string);
233 static void create_base_index(void)
236 struct unpack_trees_options opts;
239 if (initial_commit) {
244 memset(&opts, 0, sizeof(opts));
248 opts.src_index = &the_index;
249 opts.dst_index = &the_index;
251 opts.fn = oneway_merge;
252 tree = parse_tree_indirect(head_sha1);
254 die("failed to unpack HEAD tree object");
256 init_tree_desc(&t, tree->buffer, tree->size);
257 if (unpack_trees(1, &t, &opts))
258 exit(128); /* We've already reported the error, finish dying */
261 static char *prepare_index(int argc, const char **argv, const char *prefix, int is_status)
264 struct string_list partial;
265 const char **pathspec = NULL;
266 int refresh_flags = REFRESH_QUIET;
269 refresh_flags |= REFRESH_UNMERGED;
271 if (interactive_add(argc, argv, prefix) != 0)
272 die("interactive add failed");
273 if (read_cache_preload(NULL) < 0)
274 die("index file corrupt");
275 commit_style = COMMIT_AS_IS;
276 return get_index_file();
280 pathspec = get_pathspec(prefix, argv);
282 if (read_cache_preload(pathspec) < 0)
283 die("index file corrupt");
286 * Non partial, non as-is commit.
288 * (1) get the real index;
289 * (2) update the_index as necessary;
290 * (3) write the_index out to the real index (still locked);
291 * (4) return the name of the locked index file.
293 * The caller should run hooks on the locked real index, and
294 * (A) if all goes well, commit the real index;
295 * (B) on failure, rollback the real index.
297 if (all || (also && pathspec && *pathspec)) {
298 int fd = hold_locked_index(&index_lock, 1);
299 add_files_to_cache(also ? prefix : NULL, pathspec, 0);
300 refresh_cache(refresh_flags);
301 if (write_cache(fd, active_cache, active_nr) ||
302 close_lock_file(&index_lock))
303 die("unable to write new_index file");
304 commit_style = COMMIT_NORMAL;
305 return index_lock.filename;
311 * (1) return the name of the real index file.
313 * The caller should run hooks on the real index, and run
314 * hooks on the real index, and create commit from the_index.
315 * We still need to refresh the index here.
317 if (!pathspec || !*pathspec) {
318 fd = hold_locked_index(&index_lock, 1);
319 refresh_cache(refresh_flags);
320 if (write_cache(fd, active_cache, active_nr) ||
321 commit_locked_index(&index_lock))
322 die("unable to write new_index file");
323 commit_style = COMMIT_AS_IS;
324 return get_index_file();
330 * (0) find the set of affected paths;
331 * (1) get lock on the real index file;
332 * (2) update the_index with the given paths;
333 * (3) write the_index out to the real index (still locked);
334 * (4) get lock on the false index file;
335 * (5) reset the_index from HEAD;
336 * (6) update the_index the same way as (2);
337 * (7) write the_index out to the false index file;
338 * (8) return the name of the false index file (still locked);
340 * The caller should run hooks on the locked false index, and
341 * create commit from it. Then
342 * (A) if all goes well, commit the real index;
343 * (B) on failure, rollback the real index;
344 * In either case, rollback the false index.
346 commit_style = COMMIT_PARTIAL;
349 die("cannot do a partial commit during a merge.");
351 memset(&partial, 0, sizeof(partial));
352 partial.strdup_strings = 1;
353 if (list_paths(&partial, initial_commit ? NULL : "HEAD", prefix, pathspec))
357 if (read_cache() < 0)
358 die("cannot read the index");
360 fd = hold_locked_index(&index_lock, 1);
361 add_remove_files(&partial);
362 refresh_cache(REFRESH_QUIET);
363 if (write_cache(fd, active_cache, active_nr) ||
364 close_lock_file(&index_lock))
365 die("unable to write new_index file");
367 fd = hold_lock_file_for_update(&false_lock,
368 git_path("next-index-%"PRIuMAX,
369 (uintmax_t) getpid()),
373 add_remove_files(&partial);
374 refresh_cache(REFRESH_QUIET);
376 if (write_cache(fd, active_cache, active_nr) ||
377 close_lock_file(&false_lock))
378 die("unable to write temporary index file");
381 read_cache_from(false_lock.filename);
383 return false_lock.filename;
386 static int run_status(FILE *fp, const char *index_file, const char *prefix, int nowarn,
389 unsigned char sha1[20];
391 if (s->relative_paths)
396 s->reference = "HEAD^1";
398 s->verbose = verbose;
399 s->index_file = index_file;
402 s->is_initial = get_sha1(s->reference, sha1) ? 1 : 0;
404 wt_status_collect(s);
406 switch (status_format) {
407 case STATUS_FORMAT_SHORT:
408 wt_shortstatus_print(s, null_termination);
410 case STATUS_FORMAT_PORCELAIN:
411 wt_porcelain_print(s, null_termination);
413 case STATUS_FORMAT_LONG:
418 return s->commitable;
421 static int is_a_merge(const unsigned char *sha1)
423 struct commit *commit = lookup_commit(sha1);
424 if (!commit || parse_commit(commit))
425 die("could not parse HEAD commit");
426 return !!(commit->parents && commit->parents->next);
429 static const char sign_off_header[] = "Signed-off-by: ";
431 static void determine_author_info(void)
433 char *name, *email, *date;
435 name = getenv("GIT_AUTHOR_NAME");
436 email = getenv("GIT_AUTHOR_EMAIL");
437 date = getenv("GIT_AUTHOR_DATE");
439 if (use_message && !renew_authorship) {
440 const char *a, *lb, *rb, *eol;
442 a = strstr(use_message_buffer, "\nauthor ");
444 die("invalid commit: %s", use_message);
446 lb = strstr(a + 8, " <");
447 rb = strstr(a + 8, "> ");
448 eol = strchr(a + 8, '\n');
449 if (!lb || !rb || !eol)
450 die("invalid commit: %s", use_message);
452 name = xstrndup(a + 8, lb - (a + 8));
453 email = xstrndup(lb + 2, rb - (lb + 2));
454 date = xstrndup(rb + 2, eol - (rb + 2));
458 const char *lb = strstr(force_author, " <");
459 const char *rb = strchr(force_author, '>');
462 die("malformed --author parameter");
463 name = xstrndup(force_author, lb - force_author);
464 email = xstrndup(lb + 2, rb - (lb + 2));
471 author_email = email;
475 static int ends_rfc2822_footer(struct strbuf *sb)
482 const char *buf = sb->buf;
484 for (i = len - 1; i > 0; i--) {
485 if (hit && buf[i] == '\n')
487 hit = (buf[i] == '\n');
490 while (i < len - 1 && buf[i] == '\n')
493 for (; i < len; i = k) {
494 for (k = i; k < len && buf[k] != '\n'; k++)
498 if ((buf[k] == ' ' || buf[k] == '\t') && !first)
503 for (j = 0; i + j < len; j++) {
516 static int prepare_to_commit(const char *index_file, const char *prefix,
520 int commitable, saved_color_setting;
521 struct strbuf sb = STRBUF_INIT;
524 const char *hook_arg1 = NULL;
525 const char *hook_arg2 = NULL;
528 if (!no_verify && run_hook(index_file, "pre-commit", NULL))
532 strbuf_addbuf(&sb, &message);
533 hook_arg1 = "message";
534 } else if (logfile && !strcmp(logfile, "-")) {
536 fprintf(stderr, "(reading log message from standard input)\n");
537 if (strbuf_read(&sb, 0, 0) < 0)
538 die_errno("could not read log from standard input");
539 hook_arg1 = "message";
540 } else if (logfile) {
541 if (strbuf_read_file(&sb, logfile, 0) < 0)
542 die_errno("could not read log file '%s'",
544 hook_arg1 = "message";
545 } else if (use_message) {
546 buffer = strstr(use_message_buffer, "\n\n");
547 if (!buffer || buffer[2] == '\0')
548 die("commit has empty message");
549 strbuf_add(&sb, buffer + 2, strlen(buffer + 2));
550 hook_arg1 = "commit";
551 hook_arg2 = use_message;
552 } else if (!stat(git_path("MERGE_MSG"), &statbuf)) {
553 if (strbuf_read_file(&sb, git_path("MERGE_MSG"), 0) < 0)
554 die_errno("could not read MERGE_MSG");
556 } else if (!stat(git_path("SQUASH_MSG"), &statbuf)) {
557 if (strbuf_read_file(&sb, git_path("SQUASH_MSG"), 0) < 0)
558 die_errno("could not read SQUASH_MSG");
559 hook_arg1 = "squash";
560 } else if (template_file && !stat(template_file, &statbuf)) {
561 if (strbuf_read_file(&sb, template_file, 0) < 0)
562 die_errno("could not read '%s'", template_file);
563 hook_arg1 = "template";
567 * This final case does not modify the template message,
568 * it just sets the argument to the prepare-commit-msg hook.
573 fp = fopen(git_path(commit_editmsg), "w");
575 die_errno("could not open '%s'", git_path(commit_editmsg));
577 if (cleanup_mode != CLEANUP_NONE)
581 struct strbuf sob = STRBUF_INIT;
584 strbuf_addstr(&sob, sign_off_header);
585 strbuf_addstr(&sob, fmt_name(getenv("GIT_COMMITTER_NAME"),
586 getenv("GIT_COMMITTER_EMAIL")));
587 strbuf_addch(&sob, '\n');
588 for (i = sb.len - 1; i > 0 && sb.buf[i - 1] != '\n'; i--)
590 if (prefixcmp(sb.buf + i, sob.buf)) {
591 if (!i || !ends_rfc2822_footer(&sb))
592 strbuf_addch(&sb, '\n');
593 strbuf_addbuf(&sb, &sob);
595 strbuf_release(&sob);
598 if (fwrite(sb.buf, 1, sb.len, fp) < sb.len)
599 die_errno("could not write commit template");
603 determine_author_info();
605 /* This checks if committer ident is explicitly given */
606 git_committer_info(0);
607 if (use_editor && include_status) {
609 const char *committer_ident;
614 "# It looks like you may be committing a MERGE.\n"
615 "# If this is not correct, please remove the file\n"
619 git_path("MERGE_HEAD"));
623 "# Please enter the commit message for your changes.");
624 if (cleanup_mode == CLEANUP_ALL)
627 "# with '#' will be ignored, and an empty"
628 " message aborts the commit.\n");
629 else /* CLEANUP_SPACE, that is. */
632 "# with '#' will be kept; you may remove them"
633 " yourself if you want to.\n"
634 "# An empty message aborts the commit.\n");
635 if (only_include_assumed)
636 fprintf(fp, "# %s\n", only_include_assumed);
638 author_ident = xstrdup(fmt_name(author_name, author_email));
639 committer_ident = fmt_name(getenv("GIT_COMMITTER_NAME"),
640 getenv("GIT_COMMITTER_EMAIL"));
641 if (strcmp(author_ident, committer_ident))
645 ident_shown++ ? "" : "#\n",
649 if (!user_ident_sufficiently_given())
653 ident_shown++ ? "" : "#\n",
659 saved_color_setting = s->use_color;
661 commitable = run_status(fp, index_file, prefix, 1, s);
662 s->use_color = saved_color_setting;
664 unsigned char sha1[20];
665 const char *parent = "HEAD";
667 if (!active_nr && read_cache() < 0)
668 die("Cannot read index");
673 if (get_sha1(parent, sha1))
674 commitable = !!active_nr;
676 commitable = index_differs_from(parent, 0);
681 if (!commitable && !in_merge && !allow_empty &&
682 !(amend && is_a_merge(head_sha1))) {
683 run_status(stdout, index_file, prefix, 0, s);
688 * Re-read the index as pre-commit hook could have updated it,
689 * and write it out as a tree. We must do this before we invoke
690 * the editor and after we invoke run_status above.
693 read_cache_from(index_file);
694 if (!active_cache_tree)
695 active_cache_tree = cache_tree();
696 if (cache_tree_update(active_cache_tree,
697 active_cache, active_nr, 0, 0) < 0) {
698 error("Error building trees");
702 if (run_hook(index_file, "prepare-commit-msg",
703 git_path(commit_editmsg), hook_arg1, hook_arg2, NULL))
707 char index[PATH_MAX];
708 const char *env[2] = { index, NULL };
709 snprintf(index, sizeof(index), "GIT_INDEX_FILE=%s", index_file);
710 if (launch_editor(git_path(commit_editmsg), NULL, env)) {
712 "Please supply the message using either -m or -F option.\n");
718 run_hook(index_file, "commit-msg", git_path(commit_editmsg), NULL)) {
726 * Find out if the message in the strbuf contains only whitespace and
727 * Signed-off-by lines.
729 static int message_is_empty(struct strbuf *sb)
731 struct strbuf tmpl = STRBUF_INIT;
733 int eol, i, start = 0;
735 if (cleanup_mode == CLEANUP_NONE && sb->len)
738 /* See if the template is just a prefix of the message. */
739 if (template_file && strbuf_read_file(&tmpl, template_file, 0) > 0) {
740 stripspace(&tmpl, cleanup_mode == CLEANUP_ALL);
741 if (start + tmpl.len <= sb->len &&
742 memcmp(tmpl.buf, sb->buf + start, tmpl.len) == 0)
745 strbuf_release(&tmpl);
747 /* Check if the rest is just whitespace and Signed-of-by's. */
748 for (i = start; i < sb->len; i++) {
749 nl = memchr(sb->buf + i, '\n', sb->len - i);
755 if (strlen(sign_off_header) <= eol - i &&
756 !prefixcmp(sb->buf + i, sign_off_header)) {
761 if (!isspace(sb->buf[i++]))
768 static const char *find_author_by_nickname(const char *name)
770 struct rev_info revs;
771 struct commit *commit;
772 struct strbuf buf = STRBUF_INIT;
776 init_revisions(&revs, NULL);
777 strbuf_addf(&buf, "--author=%s", name);
782 setup_revisions(ac, av, &revs, NULL);
783 prepare_revision_walk(&revs);
784 commit = get_revision(&revs);
786 struct pretty_print_context ctx = {0};
787 ctx.date_mode = DATE_NORMAL;
788 strbuf_release(&buf);
789 format_commit_message(commit, "%an <%ae>", &buf, &ctx);
790 return strbuf_detach(&buf, NULL);
792 die("No existing author found with '%s'", name);
796 static void handle_untracked_files_arg(struct wt_status *s)
798 if (!untracked_files_arg)
799 ; /* default already initialized */
800 else if (!strcmp(untracked_files_arg, "no"))
801 s->show_untracked_files = SHOW_NO_UNTRACKED_FILES;
802 else if (!strcmp(untracked_files_arg, "normal"))
803 s->show_untracked_files = SHOW_NORMAL_UNTRACKED_FILES;
804 else if (!strcmp(untracked_files_arg, "all"))
805 s->show_untracked_files = SHOW_ALL_UNTRACKED_FILES;
807 die("Invalid untracked files mode '%s'", untracked_files_arg);
810 static int parse_and_validate_options(int argc, const char *argv[],
811 const char * const usage[],
817 argc = parse_options(argc, argv, prefix, builtin_commit_options, usage,
820 if (force_author && !strchr(force_author, '>'))
821 force_author = find_author_by_nickname(force_author);
823 if (force_author && renew_authorship)
824 die("Using both --reset-author and --author does not make sense");
826 if (logfile || message.len || use_message)
831 setenv("GIT_EDITOR", ":", 1);
833 if (get_sha1("HEAD", head_sha1))
836 /* Sanity check options */
837 if (amend && initial_commit)
838 die("You have nothing to amend.");
839 if (amend && in_merge)
840 die("You are in the middle of a merge -- cannot amend.");
849 die("Only one of -c/-C/-F can be used.");
850 if (message.len && f > 0)
851 die("Option -m cannot be combined with -c/-C/-F.");
853 use_message = edit_message;
854 if (amend && !use_message)
855 use_message = "HEAD";
856 if (!use_message && renew_authorship)
857 die("--reset-author can be used only with -C, -c or --amend.");
859 unsigned char sha1[20];
860 static char utf8[] = "UTF-8";
863 struct commit *commit;
865 if (get_sha1(use_message, sha1))
866 die("could not lookup commit %s", use_message);
867 commit = lookup_commit_reference(sha1);
868 if (!commit || parse_commit(commit))
869 die("could not parse commit %s", use_message);
871 enc = strstr(commit->buffer, "\nencoding");
873 end = strchr(enc + 10, '\n');
874 enc = xstrndup(enc + 10, end - (enc + 10));
878 out_enc = git_commit_encoding ? git_commit_encoding : utf8;
880 if (strcmp(out_enc, enc))
882 reencode_string(commit->buffer, out_enc, enc);
885 * If we failed to reencode the buffer, just copy it
886 * byte for byte so the user can try to fix it up.
887 * This also handles the case where input and output
888 * encodings are identical.
890 if (use_message_buffer == NULL)
891 use_message_buffer = xstrdup(commit->buffer);
896 if (!!also + !!only + !!all + !!interactive > 1)
897 die("Only one of --include/--only/--all/--interactive can be used.");
898 if (argc == 0 && (also || (only && !amend)))
899 die("No paths with --include/--only does not make sense.");
900 if (argc == 0 && only && amend)
901 only_include_assumed = "Clever... amending the last one with dirty index.";
902 if (argc > 0 && !also && !only)
903 only_include_assumed = "Explicit paths specified without -i nor -o; assuming --only paths...";
904 if (!cleanup_arg || !strcmp(cleanup_arg, "default"))
905 cleanup_mode = use_editor ? CLEANUP_ALL : CLEANUP_SPACE;
906 else if (!strcmp(cleanup_arg, "verbatim"))
907 cleanup_mode = CLEANUP_NONE;
908 else if (!strcmp(cleanup_arg, "whitespace"))
909 cleanup_mode = CLEANUP_SPACE;
910 else if (!strcmp(cleanup_arg, "strip"))
911 cleanup_mode = CLEANUP_ALL;
913 die("Invalid cleanup mode %s", cleanup_arg);
915 handle_untracked_files_arg(s);
918 die("Paths with -a does not make sense.");
919 else if (interactive && argc > 0)
920 die("Paths with --interactive does not make sense.");
922 if (null_termination && status_format == STATUS_FORMAT_LONG)
923 status_format = STATUS_FORMAT_PORCELAIN;
924 if (status_format != STATUS_FORMAT_LONG)
930 static int dry_run_commit(int argc, const char **argv, const char *prefix,
934 const char *index_file;
936 index_file = prepare_index(argc, argv, prefix, 1);
937 commitable = run_status(stdout, index_file, prefix, 0, s);
938 rollback_index_files();
940 return commitable ? 0 : 1;
943 static int parse_status_slot(const char *var, int offset)
945 if (!strcasecmp(var+offset, "header"))
946 return WT_STATUS_HEADER;
947 if (!strcasecmp(var+offset, "updated")
948 || !strcasecmp(var+offset, "added"))
949 return WT_STATUS_UPDATED;
950 if (!strcasecmp(var+offset, "changed"))
951 return WT_STATUS_CHANGED;
952 if (!strcasecmp(var+offset, "untracked"))
953 return WT_STATUS_UNTRACKED;
954 if (!strcasecmp(var+offset, "nobranch"))
955 return WT_STATUS_NOBRANCH;
956 if (!strcasecmp(var+offset, "unmerged"))
957 return WT_STATUS_UNMERGED;
961 static int git_status_config(const char *k, const char *v, void *cb)
963 struct wt_status *s = cb;
965 if (!strcmp(k, "status.submodulesummary")) {
967 s->submodule_summary = git_config_bool_or_int(k, v, &is_bool);
968 if (is_bool && s->submodule_summary)
969 s->submodule_summary = -1;
972 if (!strcmp(k, "status.color") || !strcmp(k, "color.status")) {
973 s->use_color = git_config_colorbool(k, v, -1);
976 if (!prefixcmp(k, "status.color.") || !prefixcmp(k, "color.status.")) {
977 int slot = parse_status_slot(k, 13);
981 return config_error_nonbool(k);
982 color_parse(v, k, s->color_palette[slot]);
985 if (!strcmp(k, "status.relativepaths")) {
986 s->relative_paths = git_config_bool(k, v);
989 if (!strcmp(k, "status.showuntrackedfiles")) {
991 return config_error_nonbool(k);
992 else if (!strcmp(v, "no"))
993 s->show_untracked_files = SHOW_NO_UNTRACKED_FILES;
994 else if (!strcmp(v, "normal"))
995 s->show_untracked_files = SHOW_NORMAL_UNTRACKED_FILES;
996 else if (!strcmp(v, "all"))
997 s->show_untracked_files = SHOW_ALL_UNTRACKED_FILES;
999 return error("Invalid untracked files mode '%s'", v);
1002 return git_diff_ui_config(k, v, NULL);
1005 int cmd_status(int argc, const char **argv, const char *prefix)
1008 unsigned char sha1[20];
1009 static struct option builtin_status_options[] = {
1010 OPT__VERBOSE(&verbose),
1011 OPT_SET_INT('s', "short", &status_format,
1012 "show status concisely", STATUS_FORMAT_SHORT),
1013 OPT_SET_INT(0, "porcelain", &status_format,
1014 "show porcelain output format",
1015 STATUS_FORMAT_PORCELAIN),
1016 OPT_BOOLEAN('z', "null", &null_termination,
1017 "terminate entries with NUL"),
1018 { OPTION_STRING, 'u', "untracked-files", &untracked_files_arg,
1020 "show untracked files, optional modes: all, normal, no. (Default: all)",
1021 PARSE_OPT_OPTARG, NULL, (intptr_t)"all" },
1025 if (null_termination && status_format == STATUS_FORMAT_LONG)
1026 status_format = STATUS_FORMAT_PORCELAIN;
1028 wt_status_prepare(&s);
1029 git_config(git_status_config, &s);
1030 in_merge = file_exists(git_path("MERGE_HEAD"));
1031 argc = parse_options(argc, argv, prefix,
1032 builtin_status_options,
1033 builtin_status_usage, 0);
1034 handle_untracked_files_arg(&s);
1037 s.pathspec = get_pathspec(prefix, argv);
1040 refresh_cache(REFRESH_QUIET|REFRESH_UNMERGED);
1041 s.is_initial = get_sha1(s.reference, sha1) ? 1 : 0;
1042 s.in_merge = in_merge;
1043 wt_status_collect(&s);
1045 if (s.relative_paths)
1047 if (s.use_color == -1)
1048 s.use_color = git_use_color_default;
1049 if (diff_use_color_default == -1)
1050 diff_use_color_default = git_use_color_default;
1052 switch (status_format) {
1053 case STATUS_FORMAT_SHORT:
1054 wt_shortstatus_print(&s, null_termination);
1056 case STATUS_FORMAT_PORCELAIN:
1057 wt_porcelain_print(&s, null_termination);
1059 case STATUS_FORMAT_LONG:
1060 s.verbose = verbose;
1061 wt_status_print(&s);
1067 static void print_summary(const char *prefix, const unsigned char *sha1)
1069 struct rev_info rev;
1070 struct commit *commit;
1071 struct strbuf format = STRBUF_INIT;
1072 unsigned char junk_sha1[20];
1073 const char *head = resolve_ref("HEAD", junk_sha1, 0, NULL);
1074 struct pretty_print_context pctx = {0};
1075 struct strbuf author_ident = STRBUF_INIT;
1076 struct strbuf committer_ident = STRBUF_INIT;
1078 commit = lookup_commit(sha1);
1080 die("couldn't look up newly created commit");
1081 if (!commit || parse_commit(commit))
1082 die("could not parse newly created commit");
1084 strbuf_addstr(&format, "format:%h] %s");
1086 format_commit_message(commit, "%an <%ae>", &author_ident, &pctx);
1087 format_commit_message(commit, "%cn <%ce>", &committer_ident, &pctx);
1088 if (strbuf_cmp(&author_ident, &committer_ident)) {
1089 strbuf_addstr(&format, "\n Author: ");
1090 strbuf_addbuf_percentquote(&format, &author_ident);
1092 if (!user_ident_sufficiently_given()) {
1093 strbuf_addstr(&format, "\n Committer: ");
1094 strbuf_addbuf_percentquote(&format, &committer_ident);
1095 if (advice_implicit_identity) {
1096 strbuf_addch(&format, '\n');
1097 strbuf_addstr(&format, implicit_ident_advice);
1100 strbuf_release(&author_ident);
1101 strbuf_release(&committer_ident);
1103 init_revisions(&rev, prefix);
1104 setup_revisions(0, NULL, &rev, NULL);
1108 rev.diffopt.output_format =
1109 DIFF_FORMAT_SHORTSTAT | DIFF_FORMAT_SUMMARY;
1111 rev.verbose_header = 1;
1112 rev.show_root_diff = 1;
1113 get_commit_format(format.buf, &rev);
1114 rev.always_show_header = 0;
1115 rev.diffopt.detect_rename = 1;
1116 rev.diffopt.rename_limit = 100;
1117 rev.diffopt.break_opt = 0;
1118 diff_setup_done(&rev.diffopt);
1121 !prefixcmp(head, "refs/heads/") ?
1123 !strcmp(head, "HEAD") ?
1126 initial_commit ? " (root-commit)" : "");
1128 if (!log_tree_commit(&rev, commit)) {
1129 struct pretty_print_context ctx = {0};
1130 struct strbuf buf = STRBUF_INIT;
1131 ctx.date_mode = DATE_NORMAL;
1132 format_commit_message(commit, format.buf + 7, &buf, &ctx);
1133 printf("%s\n", buf.buf);
1134 strbuf_release(&buf);
1136 strbuf_release(&format);
1139 static int git_commit_config(const char *k, const char *v, void *cb)
1141 struct wt_status *s = cb;
1143 if (!strcmp(k, "commit.template"))
1144 return git_config_pathname(&template_file, k, v);
1145 if (!strcmp(k, "commit.status")) {
1146 include_status = git_config_bool(k, v);
1150 return git_status_config(k, v, s);
1153 int cmd_commit(int argc, const char **argv, const char *prefix)
1155 struct strbuf sb = STRBUF_INIT;
1156 const char *index_file, *reflog_msg;
1158 unsigned char commit_sha1[20];
1159 struct ref_lock *ref_lock;
1160 struct commit_list *parents = NULL, **pptr = &parents;
1161 struct stat statbuf;
1162 int allow_fast_forward = 1;
1165 wt_status_prepare(&s);
1166 git_config(git_commit_config, &s);
1167 in_merge = file_exists(git_path("MERGE_HEAD"));
1168 s.in_merge = in_merge;
1170 if (s.use_color == -1)
1171 s.use_color = git_use_color_default;
1172 argc = parse_and_validate_options(argc, argv, builtin_commit_usage,
1175 if (diff_use_color_default == -1)
1176 diff_use_color_default = git_use_color_default;
1177 return dry_run_commit(argc, argv, prefix, &s);
1179 index_file = prepare_index(argc, argv, prefix, 0);
1181 /* Set up everything for writing the commit object. This includes
1182 running hooks, writing the trees, and interacting with the user. */
1183 if (!prepare_to_commit(index_file, prefix, &s)) {
1184 rollback_index_files();
1188 /* Determine parents */
1189 if (initial_commit) {
1190 reflog_msg = "commit (initial)";
1192 struct commit_list *c;
1193 struct commit *commit;
1195 reflog_msg = "commit (amend)";
1196 commit = lookup_commit(head_sha1);
1197 if (!commit || parse_commit(commit))
1198 die("could not parse HEAD commit");
1200 for (c = commit->parents; c; c = c->next)
1201 pptr = &commit_list_insert(c->item, pptr)->next;
1202 } else if (in_merge) {
1203 struct strbuf m = STRBUF_INIT;
1206 reflog_msg = "commit (merge)";
1207 pptr = &commit_list_insert(lookup_commit(head_sha1), pptr)->next;
1208 fp = fopen(git_path("MERGE_HEAD"), "r");
1210 die_errno("could not open '%s' for reading",
1211 git_path("MERGE_HEAD"));
1212 while (strbuf_getline(&m, fp, '\n') != EOF) {
1213 unsigned char sha1[20];
1214 if (get_sha1_hex(m.buf, sha1) < 0)
1215 die("Corrupt MERGE_HEAD file (%s)", m.buf);
1216 pptr = &commit_list_insert(lookup_commit(sha1), pptr)->next;
1220 if (!stat(git_path("MERGE_MODE"), &statbuf)) {
1221 if (strbuf_read_file(&sb, git_path("MERGE_MODE"), 0) < 0)
1222 die_errno("could not read MERGE_MODE");
1223 if (!strcmp(sb.buf, "no-ff"))
1224 allow_fast_forward = 0;
1226 if (allow_fast_forward)
1227 parents = reduce_heads(parents);
1229 reflog_msg = "commit";
1230 pptr = &commit_list_insert(lookup_commit(head_sha1), pptr)->next;
1233 /* Finally, get the commit message */
1235 if (strbuf_read_file(&sb, git_path(commit_editmsg), 0) < 0) {
1236 int saved_errno = errno;
1237 rollback_index_files();
1238 die("could not read commit message: %s", strerror(saved_errno));
1241 /* Truncate the message just before the diff, if any. */
1243 p = strstr(sb.buf, "\ndiff --git ");
1245 strbuf_setlen(&sb, p - sb.buf + 1);
1248 if (cleanup_mode != CLEANUP_NONE)
1249 stripspace(&sb, cleanup_mode == CLEANUP_ALL);
1250 if (message_is_empty(&sb)) {
1251 rollback_index_files();
1252 fprintf(stderr, "Aborting commit due to empty commit message.\n");
1256 if (commit_tree(sb.buf, active_cache_tree->sha1, parents, commit_sha1,
1257 fmt_ident(author_name, author_email, author_date,
1258 IDENT_ERROR_ON_NO_NAME))) {
1259 rollback_index_files();
1260 die("failed to write commit object");
1263 ref_lock = lock_any_ref_for_update("HEAD",
1264 initial_commit ? NULL : head_sha1,
1267 nl = strchr(sb.buf, '\n');
1269 strbuf_setlen(&sb, nl + 1 - sb.buf);
1271 strbuf_addch(&sb, '\n');
1272 strbuf_insert(&sb, 0, reflog_msg, strlen(reflog_msg));
1273 strbuf_insert(&sb, strlen(reflog_msg), ": ", 2);
1276 rollback_index_files();
1277 die("cannot lock HEAD ref");
1279 if (write_ref_sha1(ref_lock, commit_sha1, sb.buf) < 0) {
1280 rollback_index_files();
1281 die("cannot update HEAD ref");
1284 unlink(git_path("MERGE_HEAD"));
1285 unlink(git_path("MERGE_MSG"));
1286 unlink(git_path("MERGE_MODE"));
1287 unlink(git_path("SQUASH_MSG"));
1289 if (commit_index_files())
1290 die ("Repository has been updated, but unable to write\n"
1291 "new_index file. Check that disk is not full or quota is\n"
1292 "not exceeded, and then \"git reset HEAD\" to recover.");
1295 run_hook(get_index_file(), "post-commit", NULL);
1297 print_summary(prefix, commit_sha1);