Merge branch 'kw/commit-keep-index-when-pre-commit-is-not-run' into next
authorJunio C Hamano <gitster@pobox.com>
Sun, 20 Aug 2017 06:07:19 +0000 (23:07 -0700)
committerJunio C Hamano <gitster@pobox.com>
Sun, 20 Aug 2017 06:07:19 +0000 (23:07 -0700)
"git commit" used to discard the index and re-read from the filesystem
just in case the pre-commit hook has updated it in the middle; this
has been optimized out when we know we do not run the pre-commit hook.

* kw/commit-keep-index-when-pre-commit-is-not-run:
commit: skip discarding the index if there is no pre-commit hook

1  2 
builtin/commit.c
diff --combined builtin/commit.c
index e7a2cb628554c7db3370521521291a28b060f574,6448ef48b034cfcb3cd3f899e86bb35468c638e7..b79bcfd5b9331f79b660940bb4029aa96041d80e
@@@ -6,7 -6,6 +6,7 @@@
   */
  
  #include "cache.h"
 +#include "config.h"
  #include "lockfile.h"
  #include "cache-tree.h"
  #include "color.h"
@@@ -140,6 -139,7 +140,6 @@@ static enum commit_whence whence
  static int sequencer_in_use;
  static int use_editor = 1, include_status = 1;
  static int show_ignored_in_status, have_option_m;
 -static const char *only_include_assumed;
  static struct strbuf message = STRBUF_INIT;
  
  static enum wt_status_format status_format = STATUS_FORMAT_UNSPECIFIED;
@@@ -253,8 -253,7 +253,8 @@@ static int list_paths(struct string_lis
  
        if (with_tree) {
                char *max_prefix = common_prefix(pattern);
 -              overlay_tree_on_cache(with_tree, max_prefix ? max_prefix : prefix);
 +              overlay_tree_on_index(&the_index, with_tree,
 +                                    max_prefix ? max_prefix : prefix);
                free(max_prefix);
        }
  
@@@ -314,7 -313,7 +314,7 @@@ static void create_base_index(const str
        opts.dst_index = &the_index;
  
        opts.fn = oneway_merge;
 -      tree = parse_tree_indirect(current_head->object.oid.hash);
 +      tree = parse_tree_indirect(&current_head->object.oid);
        if (!tree)
                die(_("failed to unpack HEAD tree object"));
        parse_tree(tree);
@@@ -497,7 -496,7 +497,7 @@@ static const char *prepare_index(int ar
  static int run_status(FILE *fp, const char *index_file, const char *prefix, int nowarn,
                      struct wt_status *s)
  {
 -      unsigned char sha1[20];
 +      struct object_id oid;
  
        if (s->relative_paths)
                s->prefix = prefix;
        s->index_file = index_file;
        s->fp = fp;
        s->nowarn = nowarn;
 -      s->is_initial = get_sha1(s->reference, sha1) ? 1 : 0;
 +      s->is_initial = get_oid(s->reference, &oid) ? 1 : 0;
        if (!s->is_initial)
 -              hashcpy(s->sha1_commit, sha1);
 +              hashcpy(s->sha1_commit, oid.hash);
        s->status_format = status_format;
        s->ignore_submodule_arg = ignore_submodule_arg;
  
@@@ -822,9 -821,9 +822,9 @@@ static int prepare_to_commit(const cha
                                        "If this is not correct, please remove the file\n"
                                        "       %s\n"
                                        "and try again.\n"),
 -                              git_path(whence == FROM_MERGE
 -                                       ? "MERGE_HEAD"
 -                                       : "CHERRY_PICK_HEAD"));
 +                              whence == FROM_MERGE ?
 +                                      git_path_merge_head() :
 +                                      git_path_cherry_pick_head());
                }
  
                fprintf(s->fp, "\n");
                                  "with '%c' will be kept; you may remove them"
                                  " yourself if you want to.\n"
                                  "An empty message aborts the commit.\n"), comment_line_char);
 -              if (only_include_assumed)
 -                      status_printf_ln(s, GIT_COLOR_NORMAL,
 -                                      "%s", only_include_assumed);
  
                /*
                 * These should never fail because they come from our own
                                (int)(ci.name_end - ci.name_begin), ci.name_begin,
                                (int)(ci.mail_end - ci.mail_begin), ci.mail_begin);
  
 -              if (ident_shown)
 -                      status_printf_ln(s, GIT_COLOR_NORMAL, "%s", "");
 +              status_printf_ln(s, GIT_COLOR_NORMAL, "%s", ""); /* Add new line for clarity */
  
                saved_color_setting = s->use_color;
                s->use_color = 0;
                commitable = run_status(s->fp, index_file, prefix, 1, s);
                s->use_color = saved_color_setting;
        } else {
 -              unsigned char sha1[20];
 +              struct object_id oid;
                const char *parent = "HEAD";
  
                if (!active_nr && read_cache() < 0)
                if (amend)
                        parent = "HEAD^1";
  
 -              if (get_sha1(parent, sha1)) {
 +              if (get_oid(parent, &oid)) {
                        int i, ita_nr = 0;
  
                        for (i = 0; i < active_nr; i++)
                return 0;
        }
  
-       /*
-        * 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
-        * the editor and after we invoke run_status above.
-        */
-       discard_cache();
+       if (!no_verify && find_hook("pre-commit")) {
+               /*
+                * 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
+                * the editor and after we invoke run_status above.
+                */
+               discard_cache();
+       }
        read_cache_from(index_file);
        if (update_main_cache_tree(0)) {
                error(_("Error building trees"));
                return 0;
@@@ -981,7 -987,7 +984,7 @@@ static int rest_is_empty(struct strbuf 
        int i, eol;
        const char *nl;
  
 -      /* Check if the rest is just whitespace and Signed-of-by's. */
 +      /* Check if the rest is just whitespace and Signed-off-by's. */
        for (i = start; i < sb->len; i++) {
                nl = memchr(sb->buf + i, '\n', sb->len - i);
                if (nl)
@@@ -1205,6 -1211,8 +1208,6 @@@ static int parse_and_validate_options(i
                die(_("Only one of --include/--only/--all/--interactive/--patch can be used."));
        if (argc == 0 && (also || (only && !amend && !allow_empty)))
                die(_("No paths with --include/--only does not make sense."));
 -      if (argc > 0 && !also && !only)
 -              only_include_assumed = _("Explicit paths specified without -i or -o; assuming --only paths...");
        if (!cleanup_arg || !strcmp(cleanup_arg, "default"))
                cleanup_mode = use_editor ? CLEANUP_ALL : CLEANUP_SPACE;
        else if (!strcmp(cleanup_arg, "verbatim"))
@@@ -1258,10 -1266,6 +1261,10 @@@ static int parse_status_slot(const cha
                return WT_STATUS_NOBRANCH;
        if (!strcasecmp(slot, "unmerged"))
                return WT_STATUS_UNMERGED;
 +      if (!strcasecmp(slot, "localBranch"))
 +              return WT_STATUS_LOCAL_BRANCH;
 +      if (!strcasecmp(slot, "remoteBranch"))
 +              return WT_STATUS_REMOTE_BRANCH;
        return -1;
  }
  
@@@ -1290,10 -1294,6 +1293,10 @@@ static int git_status_config(const cha
                status_deferred_config.show_branch = git_config_bool(k, v);
                return 0;
        }
 +      if (!strcmp(k, "status.showstash")) {
 +              s->show_stash = git_config_bool(k, v);
 +              return 0;
 +      }
        if (!strcmp(k, "status.color") || !strcmp(k, "color.status")) {
                s->use_color = git_config_colorbool(k, v);
                return 0;
@@@ -1335,15 -1335,13 +1338,15 @@@ int cmd_status(int argc, const char **a
  {
        static struct wt_status s;
        int fd;
 -      unsigned char sha1[20];
 +      struct object_id oid;
        static struct option builtin_status_options[] = {
                OPT__VERBOSE(&verbose, N_("be verbose")),
                OPT_SET_INT('s', "short", &status_format,
                            N_("show status concisely"), STATUS_FORMAT_SHORT),
                OPT_BOOL('b', "branch", &s.show_branch,
                         N_("show branch information")),
 +              OPT_BOOL(0, "show-stash", &s.show_stash,
 +                       N_("show stash information")),
                { OPTION_CALLBACK, 0, "porcelain", &status_format,
                  N_("version"), N_("machine-readable output"),
                  PARSE_OPT_OPTARG, opt_parse_porcelain },
  
        fd = hold_locked_index(&index_lock, 0);
  
 -      s.is_initial = get_sha1(s.reference, sha1) ? 1 : 0;
 +      s.is_initial = get_oid(s.reference, &oid) ? 1 : 0;
        if (!s.is_initial)
 -              hashcpy(s.sha1_commit, sha1);
 +              hashcpy(s.sha1_commit, oid.hash);
  
        s.ignore_submodule_arg = ignore_submodule_arg;
        s.status_format = status_format;
  
  static const char *implicit_ident_advice(void)
  {
 -      char *user_config = expand_user_path("~/.gitconfig");
 +      char *user_config = expand_user_path("~/.gitconfig", 0);
        char *xdg_config = xdg_config_home("config");
        int config_exists = file_exists(user_config) || file_exists(xdg_config);
  
  
  }
  
 -static void print_summary(const char *prefix, const unsigned char *sha1,
 +static void print_summary(const char *prefix, const struct object_id *oid,
                          int initial_commit)
  {
        struct rev_info rev;
        struct commit *commit;
        struct strbuf format = STRBUF_INIT;
 -      unsigned char junk_sha1[20];
 +      struct object_id junk_oid;
        const char *head;
        struct pretty_print_context pctx = {0};
        struct strbuf author_ident = STRBUF_INIT;
        struct strbuf committer_ident = STRBUF_INIT;
  
 -      commit = lookup_commit(sha1);
 +      commit = lookup_commit(oid);
        if (!commit)
                die(_("couldn't look up newly created commit"));
        if (parse_commit(commit))
        rev.diffopt.break_opt = 0;
        diff_setup_done(&rev.diffopt);
  
 -      head = resolve_ref_unsafe("HEAD", 0, junk_sha1, NULL);
 +      head = resolve_ref_unsafe("HEAD", 0, junk_oid.hash, NULL);
        if (!strcmp(head, "HEAD"))
                head = _("detached HEAD");
        else
@@@ -1527,8 -1525,8 +1530,8 @@@ static int git_commit_config(const cha
        return git_status_config(k, v, s);
  }
  
 -static int run_rewrite_hook(const unsigned char *oldsha1,
 -                          const unsigned char *newsha1)
 +static int run_rewrite_hook(const struct object_id *oldoid,
 +                          const struct object_id *newoid)
  {
        struct child_process proc = CHILD_PROCESS_INIT;
        const char *argv[3];
        code = start_command(&proc);
        if (code)
                return code;
 -      strbuf_addf(&sb, "%s %s\n", sha1_to_hex(oldsha1), sha1_to_hex(newsha1));
 +      strbuf_addf(&sb, "%s %s\n", oid_to_hex(oldoid), oid_to_hex(newoid));
        sigchain_push(SIGPIPE, SIG_IGN);
        write_in_full(proc.in, sb.buf, sb.len);
        close(proc.in);
@@@ -1641,7 -1639,7 +1644,7 @@@ int cmd_commit(int argc, const char **a
        struct strbuf author_ident = STRBUF_INIT;
        const char *index_file, *reflog_msg;
        char *nl;
 -      unsigned char sha1[20];
 +      struct object_id oid;
        struct commit_list *parents = NULL;
        struct stat statbuf;
        struct commit *current_head = NULL;
                usage_with_options(builtin_commit_usage, builtin_commit_options);
  
        status_init_config(&s, git_commit_config);
 +      s.commit_template = 1;
        status_format = STATUS_FORMAT_NONE; /* Ignore status.short */
        s.colopts = 0;
  
 -      if (get_sha1("HEAD", sha1))
 +      if (get_oid("HEAD", &oid))
                current_head = NULL;
        else {
 -              current_head = lookup_commit_or_die(sha1, "HEAD");
 +              current_head = lookup_commit_or_die(&oid, "HEAD");
                if (parse_commit(current_head))
                        die(_("could not parse HEAD commit"));
        }
                if (!reflog_msg)
                        reflog_msg = "commit (merge)";
                pptr = commit_list_append(current_head, pptr);
 -              fp = fopen(git_path_merge_head(), "r");
 -              if (fp == NULL)
 -                      die_errno(_("could not open '%s' for reading"),
 -                                git_path_merge_head());
 +              fp = xfopen(git_path_merge_head(), "r");
                while (strbuf_getline_lf(&m, fp) != EOF) {
                        struct commit *parent;
  
  
        if (verbose || /* Truncate the message just before the diff, if any. */
            cleanup_mode == CLEANUP_SCISSORS)
 -              wt_status_truncate_message_at_cut_line(&sb);
 -
 +              strbuf_setlen(&sb, wt_status_locate_end(sb.buf, sb.len));
        if (cleanup_mode != CLEANUP_NONE)
                strbuf_stripspace(&sb, cleanup_mode == CLEANUP_ALL);
 -      if (template_untouched(&sb) && !allow_empty_message) {
 +
 +      if (message_is_empty(&sb) && !allow_empty_message) {
                rollback_index_files();
 -              fprintf(stderr, _("Aborting commit; you did not edit the message.\n"));
 +              fprintf(stderr, _("Aborting commit due to empty commit message.\n"));
                exit(1);
        }
 -      if (message_is_empty(&sb) && !allow_empty_message) {
 +      if (template_untouched(&sb) && !allow_empty_message) {
                rollback_index_files();
 -              fprintf(stderr, _("Aborting commit due to empty commit message.\n"));
 +              fprintf(stderr, _("Aborting commit; you did not edit the message.\n"));
                exit(1);
        }
  
                append_merge_tag_headers(parents, &tail);
        }
  
 -      if (commit_tree_extended(sb.buf, sb.len, active_cache_tree->sha1,
 -                       parents, sha1, author_ident.buf, sign_commit, extra)) {
 +      if (commit_tree_extended(sb.buf, sb.len, active_cache_tree->oid.hash,
 +                       parents, oid.hash, author_ident.buf, sign_commit, extra)) {
                rollback_index_files();
                die(_("failed to write commit object"));
        }
  
        transaction = ref_transaction_begin(&err);
        if (!transaction ||
 -          ref_transaction_update(transaction, "HEAD", sha1,
 +          ref_transaction_update(transaction, "HEAD", oid.hash,
                                   current_head
                                   ? current_head->object.oid.hash : null_sha1,
                                   0, sb.buf, &err) ||
                cfg = init_copy_notes_for_rewrite("amend");
                if (cfg) {
                        /* we are amending, so current_head is not NULL */
 -                      copy_note_for_rewrite(cfg, current_head->object.oid.hash, sha1);
 +                      copy_note_for_rewrite(cfg, &current_head->object.oid, &oid);
                        finish_copy_notes_for_rewrite(cfg, "Notes added by 'git commit --amend'");
                }
 -              run_rewrite_hook(current_head->object.oid.hash, sha1);
 +              run_rewrite_hook(&current_head->object.oid, &oid);
        }
        if (!quiet)
 -              print_summary(prefix, sha1, !current_head);
 +              print_summary(prefix, &oid, !current_head);
  
        strbuf_release(&err);
        return 0;