diff options
Diffstat (limited to 'builtin/commit.c')
| -rw-r--r-- | builtin/commit.c | 361 |
1 files changed, 202 insertions, 159 deletions
diff --git a/builtin/commit.c b/builtin/commit.c index b9ed0374e3..6e1484446b 100644 --- a/builtin/commit.c +++ b/builtin/commit.c @@ -5,46 +5,54 @@ * Based on git-commit.sh by Junio C Hamano and Linus Torvalds */ -#define USE_THE_INDEX_COMPATIBILITY_MACROS -#include "cache.h" +#define USE_THE_INDEX_VARIABLE +#include "builtin.h" +#include "advice.h" #include "config.h" #include "lockfile.h" #include "cache-tree.h" #include "color.h" #include "dir.h" -#include "builtin.h" +#include "editor.h" +#include "environment.h" #include "diff.h" -#include "diffcore.h" #include "commit.h" +#include "gettext.h" #include "revision.h" #include "wt-status.h" #include "run-command.h" -#include "hook.h" -#include "refs.h" -#include "log-tree.h" #include "strbuf.h" -#include "utf8.h" +#include "object-name.h" #include "parse-options.h" +#include "path.h" +#include "preload-index.h" +#include "read-cache.h" #include "string-list.h" #include "rerere.h" #include "unpack-trees.h" -#include "quote.h" -#include "submodule.h" -#include "gpg-interface.h" #include "column.h" #include "sequencer.h" +#include "sparse-index.h" #include "mailmap.h" #include "help.h" #include "commit-reach.h" #include "commit-graph.h" +#include "pretty.h" static const char * const builtin_commit_usage[] = { - N_("git commit [<options>] [--] <pathspec>..."), + N_("git commit [-a | --interactive | --patch] [-s] [-v] [-u<mode>] [--amend]\n" + " [--dry-run] [(-c | -C | --squash) <commit> | --fixup [(amend|reword):]<commit>)]\n" + " [-F <file> | -m <msg>] [--reset-author] [--allow-empty]\n" + " [--allow-empty-message] [--no-verify] [-e] [--author=<author>]\n" + " [--date=<date>] [--cleanup=<mode>] [--[no-]status]\n" + " [-i | -o] [--pathspec-from-file=<file> [--pathspec-file-nul]]\n" + " [(--trailer <token>[(=|:)<value>])...] [-S[<keyid>]]\n" + " [--] [<pathspec>...]"), NULL }; static const char * const builtin_status_usage[] = { - N_("git status [<options>] [--] <pathspec>..."), + N_("git status [<options>] [--] [<pathspec>...]"), NULL }; @@ -138,7 +146,7 @@ static int opt_pass_trailer(const struct option *opt, const char *arg, int unset { BUG_ON_OPT_NEG(unset); - strvec_pushl(&trailer_args, "--trailer", arg, NULL); + strvec_pushl(opt->value, "--trailer", arg, NULL); return 0; } @@ -264,8 +272,8 @@ static int list_paths(struct string_list *list, const char *with_tree, /* TODO: audit for interaction with sparse-index. */ ensure_full_index(&the_index); - for (i = 0; i < active_nr; i++) { - const struct cache_entry *ce = active_cache[i]; + for (i = 0; i < the_index.cache_nr; i++) { + const struct cache_entry *ce = the_index.cache[i]; struct string_list_item *item; if (ce->ce_flags & CE_UPDATE) @@ -294,10 +302,10 @@ static void add_remove_files(struct string_list *list) continue; if (!lstat(p->string, &st)) { - if (add_to_cache(p->string, &st, 0)) + if (add_to_index(&the_index, p->string, &st, 0)) die(_("updating files failed")); } else - remove_file_from_cache(p->string); + remove_file_from_index(&the_index, p->string); } } @@ -308,7 +316,7 @@ static void create_base_index(const struct commit *current_head) struct tree_desc t; if (!current_head) { - discard_cache(); + discard_index(&the_index); return; } @@ -323,8 +331,9 @@ static void create_base_index(const struct commit *current_head) tree = parse_tree_indirect(¤t_head->object.oid); if (!tree) die(_("failed to unpack HEAD tree object")); - parse_tree(tree); - init_tree_desc(&t, tree->buffer, tree->size); + if (parse_tree(tree) < 0) + exit(128); + init_tree_desc(&t, &tree->object.oid, tree->buffer, tree->size); if (unpack_trees(1, &t, &opts)) exit(128); /* We've already reported the error, finish dying */ } @@ -335,7 +344,7 @@ static void refresh_cache_or_die(int refresh_flags) * refresh_flags contains REFRESH_QUIET, so the only errors * are for unmerged entries. */ - if (refresh_cache(refresh_flags | REFRESH_IN_PORCELAIN)) + if (refresh_index(&the_index, refresh_flags | REFRESH_IN_PORCELAIN, NULL, NULL, NULL)) die_resolve_conflict("commit"); } @@ -374,12 +383,13 @@ static const char *prepare_index(const char **argv, const char *prefix, (!amend || (fixup_message && strcmp(fixup_prefix, "amend")))))) die(_("No paths with --include/--only does not make sense.")); - if (read_cache_preload(&pathspec) < 0) + if (repo_read_index_preload(the_repository, &pathspec, 0) < 0) die(_("index file corrupt")); if (interactive) { char *old_index_env = NULL, *old_repo_index_file; - hold_locked_index(&index_lock, LOCK_DIE_ON_ERROR); + repo_hold_locked_index(the_repository, &index_lock, + LOCK_DIE_ON_ERROR); refresh_cache_or_die(refresh_flags); @@ -402,9 +412,10 @@ static const char *prepare_index(const char **argv, const char *prefix, unsetenv(INDEX_ENVIRONMENT); FREE_AND_NULL(old_index_env); - discard_cache(); - read_cache_from(get_lock_file_path(&index_lock)); - if (update_main_cache_tree(WRITE_TREE_SILENT) == 0) { + discard_index(&the_index); + read_index_from(&the_index, get_lock_file_path(&index_lock), + get_git_dir()); + if (cache_tree_update(&the_index, WRITE_TREE_SILENT) == 0) { if (reopen_lock_file(&index_lock) < 0) die(_("unable to write index file")); if (write_locked_index(&the_index, &index_lock, 0)) @@ -430,14 +441,21 @@ static const char *prepare_index(const char **argv, const char *prefix, * (B) on failure, rollback the real index. */ if (all || (also && pathspec.nr)) { - hold_locked_index(&index_lock, LOCK_DIE_ON_ERROR); - add_files_to_cache(also ? prefix : NULL, &pathspec, 0); + char *ps_matched = xcalloc(pathspec.nr, 1); + repo_hold_locked_index(the_repository, &index_lock, + LOCK_DIE_ON_ERROR); + add_files_to_cache(the_repository, also ? prefix : NULL, + &pathspec, ps_matched, 0, 0); + if (!all && report_path_error(ps_matched, &pathspec)) + exit(128); + refresh_cache_or_die(refresh_flags); - update_main_cache_tree(WRITE_TREE_SILENT); + cache_tree_update(&the_index, WRITE_TREE_SILENT); if (write_locked_index(&the_index, &index_lock, 0)) - die(_("unable to write new_index file")); + die(_("unable to write new index file")); commit_style = COMMIT_NORMAL; ret = get_lock_file_path(&index_lock); + free(ps_matched); goto out; } @@ -451,14 +469,15 @@ static const char *prepare_index(const char **argv, const char *prefix, * We still need to refresh the index here. */ if (!only && !pathspec.nr) { - hold_locked_index(&index_lock, LOCK_DIE_ON_ERROR); + repo_hold_locked_index(the_repository, &index_lock, + LOCK_DIE_ON_ERROR); refresh_cache_or_die(refresh_flags); - if (active_cache_changed - || !cache_tree_fully_valid(active_cache_tree)) - update_main_cache_tree(WRITE_TREE_SILENT); + if (the_index.cache_changed + || !cache_tree_fully_valid(the_index.cache_tree)) + cache_tree_update(&the_index, WRITE_TREE_SILENT); if (write_locked_index(&the_index, &index_lock, COMMIT_LOCK | SKIP_IF_UNCHANGED)) - die(_("unable to write new_index file")); + die(_("unable to write new index file")); commit_style = COMMIT_AS_IS; ret = get_index_file(); goto out; @@ -497,16 +516,16 @@ static const char *prepare_index(const char **argv, const char *prefix, if (list_paths(&partial, !current_head ? NULL : "HEAD", &pathspec)) exit(1); - discard_cache(); - if (read_cache() < 0) + discard_index(&the_index); + if (repo_read_index(the_repository) < 0) die(_("cannot read the index")); - hold_locked_index(&index_lock, LOCK_DIE_ON_ERROR); + repo_hold_locked_index(the_repository, &index_lock, LOCK_DIE_ON_ERROR); add_remove_files(&partial); - refresh_cache(REFRESH_QUIET); - update_main_cache_tree(WRITE_TREE_SILENT); + refresh_index(&the_index, REFRESH_QUIET, NULL, NULL, NULL); + cache_tree_update(&the_index, WRITE_TREE_SILENT); if (write_locked_index(&the_index, &index_lock, 0)) - die(_("unable to write new_index file")); + die(_("unable to write new index file")); hold_lock_file_for_update(&false_lock, git_path("next-index-%"PRIuMAX, @@ -515,14 +534,14 @@ static const char *prepare_index(const char **argv, const char *prefix, create_base_index(current_head); add_remove_files(&partial); - refresh_cache(REFRESH_QUIET); + refresh_index(&the_index, REFRESH_QUIET, NULL, NULL, NULL); if (write_locked_index(&the_index, &false_lock, 0)) die(_("unable to write temporary index file")); - discard_cache(); + discard_index(&the_index); ret = get_lock_file_path(&false_lock); - read_cache_from(ret); + read_index_from(&the_index, ret, get_git_dir()); out: string_list_clear(&partial, 0); clear_pathspec(&pathspec); @@ -545,7 +564,7 @@ static int run_status(FILE *fp, const char *index_file, const char *prefix, int s->index_file = index_file; s->fp = fp; s->nowarn = nowarn; - s->is_initial = get_oid(s->reference, &oid) ? 1 : 0; + s->is_initial = repo_get_oid(the_repository, s->reference, &oid) ? 1 : 0; if (!s->is_initial) oidcpy(&s->oid_commit, &oid); s->status_format = status_format; @@ -671,9 +690,10 @@ static void adjust_comment_line_char(const struct strbuf *sb) char *candidate; const char *p; - comment_line_char = candidates[0]; - if (!memchr(sb->buf, comment_line_char, sb->len)) + if (!memchr(sb->buf, candidates[0], sb->len)) { + comment_line_str = xstrfmt("%c", candidates[0]); return; + } p = sb->buf; candidate = strchr(candidates, *p); @@ -692,7 +712,7 @@ static void adjust_comment_line_char(const struct strbuf *sb) if (!*p) die(_("unable to select a comment character that is not used\n" "in the current commit message")); - comment_line_char = *p; + comment_line_str = xstrfmt("%c", *p); } static void prepare_amend_commit(struct commit *commit, struct strbuf *sb, @@ -700,15 +720,15 @@ static void prepare_amend_commit(struct commit *commit, struct strbuf *sb, { const char *buffer, *subject, *fmt; - buffer = get_commit_buffer(commit, NULL); + buffer = repo_get_commit_buffer(the_repository, commit, NULL); find_commit_subject(buffer, &subject); /* * If we amend the 'amend!' commit then we don't want to * duplicate the subject line. */ fmt = starts_with(subject, "amend!") ? "%b" : "%B"; - format_commit_message(commit, fmt, sb, ctx); - unuse_commit_buffer(commit, buffer); + repo_format_commit_message(the_repository, commit, fmt, sb, ctx); + repo_unuse_commit_buffer(the_repository, commit, buffer); } static int prepare_to_commit(const char *index_file, const char *prefix, @@ -724,12 +744,13 @@ static int prepare_to_commit(const char *index_file, const char *prefix, const char *hook_arg2 = NULL; int clean_message_contents = (cleanup_mode != COMMIT_MSG_CLEANUP_NONE); int old_display_comment_prefix; - int merge_contains_scissors = 0; + int invoked_hook; /* This checks and barfs if author is badly specified */ determine_author_info(author_ident); - if (!no_verify && run_commit_hook(use_editor, index_file, "pre-commit", NULL)) + if (!no_verify && run_commit_hook(use_editor, index_file, &invoked_hook, + "pre-commit", NULL)) return 0; if (squash_message) { @@ -744,10 +765,11 @@ static int prepare_to_commit(const char *index_file, const char *prefix, struct commit *c; c = lookup_commit_reference_by_name(squash_message); if (!c) - die(_("could not lookup commit %s"), squash_message); + die(_("could not lookup commit '%s'"), squash_message); ctx.output_encoding = get_commit_output_encoding(); - format_commit_message(c, "squash! %s\n\n", &sb, - &ctx); + repo_format_commit_message(the_repository, c, + "squash! %s\n\n", &sb, + &ctx); } } @@ -778,10 +800,11 @@ static int prepare_to_commit(const char *index_file, const char *prefix, char *fmt; commit = lookup_commit_reference_by_name(fixup_commit); if (!commit) - die(_("could not lookup commit %s"), fixup_commit); + die(_("could not lookup commit '%s'"), fixup_commit); ctx.output_encoding = get_commit_output_encoding(); fmt = xstrfmt("%s! %%s\n\n", fixup_prefix); - format_commit_message(commit, fmt, &sb, &ctx); + repo_format_commit_message(the_repository, commit, fmt, &sb, + &ctx); free(fmt); hook_arg1 = "message"; @@ -824,7 +847,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix, wt_status_locate_end(sb.buf + merge_msg_start, sb.len - merge_msg_start) < sb.len - merge_msg_start) - merge_contains_scissors = 1; + s->added_cut_line = 1; } else if (!stat(git_path_squash_msg(the_repository), &statbuf)) { if (strbuf_read_file(&sb, git_path_squash_msg(the_repository), 0) < 0) die_errno(_("could not read SQUASH_MSG")); @@ -858,7 +881,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix, } s->fp = fopen_for_writing(git_path_commit_editmsg()); - if (s->fp == NULL) + if (!s->fp) die_errno(_("could not open '%s'"), git_path_commit_editmsg()); /* Ignore status.displayCommentPrefix: we do need comments in COMMIT_EDITMSG. */ @@ -872,10 +895,10 @@ static int prepare_to_commit(const char *index_file, const char *prefix, s->hints = 0; if (clean_message_contents) - strbuf_stripspace(&sb, 0); + strbuf_stripspace(&sb, NULL); if (signoff) - append_signoff(&sb, ignore_non_trailer(sb.buf, sb.len), 0); + append_signoff(&sb, ignored_log_message_bytes(sb.buf, sb.len), 0); if (fwrite(sb.buf, 1, sb.len, s->fp) < sb.len) die_errno(_("could not write commit template")); @@ -892,24 +915,23 @@ static int prepare_to_commit(const char *index_file, const char *prefix, struct ident_split ci, ai; const char *hint_cleanup_all = allow_empty_message ? _("Please enter the commit message for your changes." - " Lines starting\nwith '%c' will be ignored.\n") : + " Lines starting\nwith '%s' will be ignored.\n") : _("Please enter the commit message for your changes." - " Lines starting\nwith '%c' will be ignored, and an empty" + " Lines starting\nwith '%s' will be ignored, and an empty" " message aborts the commit.\n"); const char *hint_cleanup_space = allow_empty_message ? _("Please enter the commit message for your changes." " Lines starting\n" - "with '%c' will be kept; you may remove them" + "with '%s' will be kept; you may remove them" " yourself if you want to.\n") : _("Please enter the commit message for your changes." " Lines starting\n" - "with '%c' will be kept; you may remove them" + "with '%s' will be kept; you may remove them" " yourself if you want to.\n" "An empty message aborts the commit.\n"); if (whence != FROM_COMMIT) { - if (cleanup_mode == COMMIT_MSG_CLEANUP_SCISSORS && - !merge_contains_scissors) - wt_status_add_cut_line(s->fp); + if (cleanup_mode == COMMIT_MSG_CLEANUP_SCISSORS) + wt_status_add_cut_line(s); status_printf_ln( s, GIT_COLOR_NORMAL, whence == FROM_MERGE ? @@ -927,12 +949,12 @@ static int prepare_to_commit(const char *index_file, const char *prefix, fprintf(s->fp, "\n"); if (cleanup_mode == COMMIT_MSG_CLEANUP_ALL) - status_printf(s, GIT_COLOR_NORMAL, hint_cleanup_all, comment_line_char); + status_printf(s, GIT_COLOR_NORMAL, hint_cleanup_all, comment_line_str); else if (cleanup_mode == COMMIT_MSG_CLEANUP_SCISSORS) { - if (whence == FROM_COMMIT && !merge_contains_scissors) - wt_status_add_cut_line(s->fp); + if (whence == FROM_COMMIT) + wt_status_add_cut_line(s); } else /* COMMIT_MSG_CLEANUP_SPACE, that is. */ - status_printf(s, GIT_COLOR_NORMAL, hint_cleanup_space, comment_line_char); + status_printf(s, GIT_COLOR_NORMAL, hint_cleanup_space, comment_line_str); /* * These should never fail because they come from our own @@ -977,21 +999,21 @@ static int prepare_to_commit(const char *index_file, const char *prefix, struct object_id oid; const char *parent = "HEAD"; - if (!active_nr && read_cache() < 0) + if (!the_index.initialized && repo_read_index(the_repository) < 0) die(_("Cannot read index")); if (amend) parent = "HEAD^1"; - if (get_oid(parent, &oid)) { + if (repo_get_oid(the_repository, parent, &oid)) { int i, ita_nr = 0; /* TODO: audit for interaction with sparse-index. */ ensure_full_index(&the_index); - for (i = 0; i < active_nr; i++) - if (ce_intent_to_add(active_cache[i])) + for (i = 0; i < the_index.cache_nr; i++) + if (ce_intent_to_add(the_index.cache[i])) ita_nr++; - committable = active_nr - ita_nr > 0; + committable = the_index.cache_nr - ita_nr > 0; } else { /* * Unless the user did explicitly request a submodule @@ -1019,7 +1041,8 @@ static int prepare_to_commit(const char *index_file, const char *prefix, struct child_process run_trailer = CHILD_PROCESS_INIT; strvec_pushl(&run_trailer.args, "interpret-trailers", - "--in-place", git_path_commit_editmsg(), NULL); + "--in-place", "--no-divider", + git_path_commit_editmsg(), NULL); strvec_pushv(&run_trailer.args, trailer_args.v); run_trailer.git_cmd = 1; if (run_command(&run_trailer)) @@ -1052,22 +1075,22 @@ static int prepare_to_commit(const char *index_file, const char *prefix, return 0; } - if (!no_verify && hook_exists("pre-commit")) { + if (!no_verify && invoked_hook) { /* - * Re-read the index as pre-commit hook could have updated it, - * and write it out as a tree. We must do this before we invoke + * Re-read the index as the pre-commit-commit hook was invoked + * and could have updated it. We must do this before we invoke * the editor and after we invoke run_status above. */ - discard_cache(); + discard_index(&the_index); } - read_cache_from(index_file); + read_index_from(&the_index, index_file, get_git_dir()); - if (update_main_cache_tree(0)) { + if (cache_tree_update(&the_index, 0)) { error(_("Error building trees")); return 0; } - if (run_commit_hook(use_editor, index_file, "prepare-commit-msg", + if (run_commit_hook(use_editor, index_file, NULL, "prepare-commit-msg", git_path_commit_editmsg(), hook_arg1, hook_arg2, NULL)) return 0; @@ -1084,7 +1107,8 @@ static int prepare_to_commit(const char *index_file, const char *prefix, } if (!no_verify && - run_commit_hook(use_editor, index_file, "commit-msg", git_path_commit_editmsg(), NULL)) { + run_commit_hook(use_editor, index_file, NULL, "commit-msg", + git_path_commit_editmsg(), NULL)) { return 0; } @@ -1096,7 +1120,6 @@ static const char *find_author_by_nickname(const char *name) struct rev_info revs; struct commit *commit; struct strbuf buf = STRBUF_INIT; - struct string_list mailmap = STRING_LIST_INIT_NODUP; const char *av[20]; int ac = 0; @@ -1107,7 +1130,8 @@ static const char *find_author_by_nickname(const char *name) av[++ac] = buf.buf; av[++ac] = NULL; setup_revisions(ac, av, &revs, NULL); - revs.mailmap = &mailmap; + revs.mailmap = xmalloc(sizeof(struct string_list)); + string_list_init_nodup(revs.mailmap); read_mailmap(revs.mailmap); if (prepare_revision_walk(&revs)) @@ -1117,8 +1141,9 @@ static const char *find_author_by_nickname(const char *name) struct pretty_print_context ctx = {0}; ctx.date_mode.type = DATE_NORMAL; strbuf_release(&buf); - format_commit_message(commit, "%aN <%aE>", &buf, &ctx); - clear_mailmap(&mailmap); + repo_format_commit_message(the_repository, commit, + "%aN <%aE>", &buf, &ctx); + release_revisions(&revs); return strbuf_detach(&buf, NULL); } die(_("--author '%s' is not 'Name <email>' and matches no existing author"), name); @@ -1138,22 +1163,45 @@ static void handle_ignored_arg(struct wt_status *s) die(_("Invalid ignored mode '%s'"), ignored_arg); } -static void handle_untracked_files_arg(struct wt_status *s) +static enum untracked_status_type parse_untracked_setting_name(const char *u) { - if (!untracked_files_arg) - ; /* default already initialized */ - else if (!strcmp(untracked_files_arg, "no")) - s->show_untracked_files = SHOW_NO_UNTRACKED_FILES; - else if (!strcmp(untracked_files_arg, "normal")) - s->show_untracked_files = SHOW_NORMAL_UNTRACKED_FILES; - else if (!strcmp(untracked_files_arg, "all")) - s->show_untracked_files = SHOW_ALL_UNTRACKED_FILES; /* * Please update $__git_untracked_file_modes in * git-completion.bash when you add new options */ + switch (git_parse_maybe_bool(u)) { + case 0: + u = "no"; + break; + case 1: + u = "normal"; + break; + default: + break; + } + + if (!strcmp(u, "no")) + return SHOW_NO_UNTRACKED_FILES; + else if (!strcmp(u, "normal")) + return SHOW_NORMAL_UNTRACKED_FILES; + else if (!strcmp(u, "all")) + return SHOW_ALL_UNTRACKED_FILES; else - die(_("Invalid untracked files mode '%s'"), untracked_files_arg); + return SHOW_UNTRACKED_FILES_ERROR; +} + +static void handle_untracked_files_arg(struct wt_status *s) +{ + enum untracked_status_type u; + + if (!untracked_files_arg) + return; /* default already initialized */ + + u = parse_untracked_setting_name(untracked_files_arg); + if (u == SHOW_UNTRACKED_FILES_ERROR) + die(_("Invalid untracked files mode '%s'"), + untracked_files_arg); + s->show_untracked_files = u; } static const char *read_commit_message(const char *name) @@ -1163,9 +1211,9 @@ static const char *read_commit_message(const char *name) commit = lookup_commit_reference_by_name(name); if (!commit) - die(_("could not lookup commit %s"), name); + die(_("could not lookup commit '%s'"), name); out_enc = get_commit_output_encoding(); - return logmsg_reencode(commit, NULL, out_enc); + return repo_logmsg_reencode(the_repository, commit, NULL, out_enc); } /* @@ -1242,8 +1290,6 @@ static int parse_and_validate_options(int argc, const char *argv[], struct commit *current_head, struct wt_status *s) { - int f = 0; - argc = parse_options(argc, argv, prefix, options, usage, 0); finalize_deferred_config(s); @@ -1251,7 +1297,7 @@ static int parse_and_validate_options(int argc, const char *argv[], force_author = find_author_by_nickname(force_author); if (force_author && renew_authorship) - die(_("Using both --reset-author and --author does not make sense")); + die(_("options '%s' and '%s' cannot be used together"), "--reset-author", "--author"); if (logfile || have_option_m || use_message) use_editor = 0; @@ -1268,20 +1314,16 @@ static int parse_and_validate_options(int argc, const char *argv[], die(_("You are in the middle of a rebase -- cannot amend.")); } if (fixup_message && squash_message) - die(_("Options --squash and --fixup cannot be used together")); - if (use_message) - f++; - if (edit_message) - f++; - if (fixup_message) - f++; - if (logfile) - f++; - if (f > 1) - die(_("Only one of -c/-C/-F/--fixup can be used.")); - if (have_option_m && (edit_message || use_message || logfile)) - die((_("Option -m cannot be combined with -c/-C/-F."))); - if (f || have_option_m) + die(_("options '%s' and '%s' cannot be used together"), "--squash", "--fixup"); + die_for_incompatible_opt4(!!use_message, "-C", + !!edit_message, "-c", + !!logfile, "-F", + !!fixup_message, "--fixup"); + die_for_incompatible_opt4(have_option_m, "-m", + !!edit_message, "-c", + !!use_message, "-C", + !!logfile, "-F"); + if (use_message || edit_message || logfile ||fixup_message || have_option_m) template_file = NULL; if (edit_message) use_message = edit_message; @@ -1306,9 +1348,10 @@ static int parse_and_validate_options(int argc, const char *argv[], if (patch_interactive) interactive = 1; - if (also + only + all + interactive > 1) - die(_("Only one of --include/--only/--all/--interactive/--patch can be used.")); - + die_for_incompatible_opt4(also, "-i/--include", + only, "-o/--only", + all, "-a/--all", + interactive, "--interactive/-p/--patch"); if (fixup_message) { /* * We limit --fixup's suboptions to only alpha characters. @@ -1384,7 +1427,8 @@ static int parse_status_slot(const char *slot) return LOOKUP_CONFIG(color_status_slots, slot); } -static int git_status_config(const char *k, const char *v, void *cb) +static int git_status_config(const char *k, const char *v, + const struct config_context *ctx, void *cb) { struct wt_status *s = cb; const char *slot_name; @@ -1393,7 +1437,8 @@ static int git_status_config(const char *k, const char *v, void *cb) return git_column_config(k, v, "status", &s->colopts); if (!strcmp(k, "status.submodulesummary")) { int is_bool; - s->submodule_summary = git_config_bool_or_int(k, v, &is_bool); + s->submodule_summary = git_config_bool_or_int(k, v, ctx->kvi, + &is_bool); if (is_bool && s->submodule_summary) s->submodule_summary = -1; return 0; @@ -1439,25 +1484,21 @@ static int git_status_config(const char *k, const char *v, void *cb) return 0; } if (!strcmp(k, "status.showuntrackedfiles")) { - if (!v) - return config_error_nonbool(k); - else if (!strcmp(v, "no")) - s->show_untracked_files = SHOW_NO_UNTRACKED_FILES; - else if (!strcmp(v, "normal")) - s->show_untracked_files = SHOW_NORMAL_UNTRACKED_FILES; - else if (!strcmp(v, "all")) - s->show_untracked_files = SHOW_ALL_UNTRACKED_FILES; - else + enum untracked_status_type u; + + u = parse_untracked_setting_name(v); + if (u == SHOW_UNTRACKED_FILES_ERROR) return error(_("Invalid untracked files mode '%s'"), v); + s->show_untracked_files = u; return 0; } if (!strcmp(k, "diff.renamelimit")) { if (s->rename_limit == -1) - s->rename_limit = git_config_int(k, v); + s->rename_limit = git_config_int(k, v, ctx->kvi); return 0; } if (!strcmp(k, "status.renamelimit")) { - s->rename_limit = git_config_int(k, v); + s->rename_limit = git_config_int(k, v, ctx->kvi); return 0; } if (!strcmp(k, "diff.renames")) { @@ -1469,7 +1510,7 @@ static int git_status_config(const char *k, const char *v, void *cb) s->detect_rename = git_config_rename(k, v); return 0; } - return git_diff_ui_config(k, v, NULL); + return git_diff_ui_config(k, v, ctx, NULL); } int cmd_status(int argc, const char **argv, const char *prefix) @@ -1550,11 +1591,11 @@ int cmd_status(int argc, const char **argv, const char *prefix) &s.pathspec, NULL, NULL); if (use_optional_locks()) - fd = hold_locked_index(&index_lock, 0); + fd = repo_hold_locked_index(the_repository, &index_lock, 0); else fd = -1; - s.is_initial = get_oid(s.reference, &oid) ? 1 : 0; + s.is_initial = repo_get_oid(the_repository, s.reference, &oid) ? 1 : 0; if (!s.is_initial) oidcpy(&s.oid_commit, &oid); @@ -1584,10 +1625,10 @@ int cmd_status(int argc, const char **argv, const char *prefix) return 0; } -static int git_commit_config(const char *k, const char *v, void *cb) +static int git_commit_config(const char *k, const char *v, + const struct config_context *ctx, void *cb) { struct wt_status *s = cb; - int status; if (!strcmp(k, "commit.template")) return git_config_pathname(&template_file, k, v); @@ -1603,14 +1644,12 @@ static int git_commit_config(const char *k, const char *v, void *cb) } if (!strcmp(k, "commit.verbose")) { int is_bool; - config_commit_verbose = git_config_bool_or_int(k, v, &is_bool); + config_commit_verbose = git_config_bool_or_int(k, v, ctx->kvi, + &is_bool); return 0; } - status = git_gpg_config(k, v, NULL); - if (status) - return status; - return git_status_config(k, v, s); + return git_status_config(k, v, ctx, s); } int cmd_commit(int argc, const char **argv, const char *prefix) @@ -1634,7 +1673,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix) OPT_STRING(0, "fixup", &fixup_message, N_("[(amend|reword):]commit"), N_("use autosquash formatted message to fixup or amend/reword specified commit")), OPT_STRING(0, "squash", &squash_message, N_("commit"), N_("use autosquash formatted message to squash specified commit")), OPT_BOOL(0, "reset-author", &renew_authorship, N_("the commit is authored by me now (used with -C/-c/--amend)")), - OPT_CALLBACK_F(0, "trailer", NULL, N_("trailer"), N_("add custom trailer(s)"), PARSE_OPT_NONEG, opt_pass_trailer), + OPT_CALLBACK_F(0, "trailer", &trailer_args, N_("trailer"), N_("add custom trailer(s)"), PARSE_OPT_NONEG, opt_pass_trailer), OPT_BOOL('s', "signoff", &signoff, N_("add a Signed-off-by trailer")), OPT_FILENAME('t', "template", &template_file, N_("use specified template file")), OPT_BOOL('e', "edit", &edit_flag, N_("force edit of commit")), @@ -1688,6 +1727,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix) struct commit *current_head = NULL; struct commit_extra_header *extra = NULL; struct strbuf err = STRBUF_INIT; + int ret = 0; if (argc == 2 && !strcmp(argv[1], "-h")) usage_with_options(builtin_commit_usage, builtin_commit_options); @@ -1700,11 +1740,11 @@ int cmd_commit(int argc, const char **argv, const char *prefix) status_format = STATUS_FORMAT_NONE; /* Ignore status.short */ s.colopts = 0; - if (get_oid("HEAD", &oid)) + if (repo_get_oid(the_repository, "HEAD", &oid)) current_head = NULL; else { current_head = lookup_commit_or_die(&oid, "HEAD"); - if (parse_commit(current_head)) + if (repo_parse_commit(the_repository, current_head)) die(_("could not parse HEAD commit")); } verbose = -1; /* unspecified */ @@ -1722,8 +1762,9 @@ int cmd_commit(int argc, const char **argv, const char *prefix) running hooks, writing the trees, and interacting with the user. */ if (!prepare_to_commit(index_file, prefix, current_head, &s, &author_ident)) { + ret = 1; rollback_index_files(); - return 1; + goto cleanup; } /* Determine parents */ @@ -1815,13 +1856,12 @@ int cmd_commit(int argc, const char **argv, const char *prefix) append_merge_tag_headers(parents, &tail); } - if (commit_tree_extended(sb.buf, sb.len, &active_cache_tree->oid, + if (commit_tree_extended(sb.buf, sb.len, &the_index.cache_tree->oid, parents, &oid, author_ident.buf, NULL, sign_commit, extra)) { rollback_index_files(); die(_("failed to write commit object")); } - strbuf_release(&author_ident); free_commit_extra_headers(extra); if (update_head_with_reflog(current_head, &oid, reflog_msg, &sb, @@ -1838,14 +1878,15 @@ int cmd_commit(int argc, const char **argv, const char *prefix) if (commit_index_files()) die(_("repository has been updated, but unable to write\n" - "new_index file. Check that disk is not full and quota is\n" + "new index file. Check that disk is not full and quota is\n" "not exceeded, and then \"git restore --staged :/\" to recover.")); git_test_write_commit_graph_or_die(); repo_rerere(the_repository, 0); run_auto_maintenance(quiet); - run_commit_hook(use_editor, get_index_file(), "post-commit", NULL); + run_commit_hook(use_editor, get_index_file(), NULL, "post-commit", + NULL); if (amend && !no_post_rewrite) { commit_post_rewrite(the_repository, current_head, &oid); } @@ -1860,9 +1901,11 @@ int cmd_commit(int argc, const char **argv, const char *prefix) &oid, flags); } - apply_autostash(git_path_merge_autostash(the_repository)); + apply_autostash_ref(the_repository, "MERGE_AUTOSTASH"); - UNLEAK(err); - UNLEAK(sb); - return 0; +cleanup: + strbuf_release(&author_ident); + strbuf_release(&err); + strbuf_release(&sb); + return ret; } |
