Merge branch 'bp/commit-p-editor'
authorJunio C Hamano <gitster@pobox.com>
Fri, 28 Mar 2014 20:51:11 +0000 (13:51 -0700)
committerJunio C Hamano <gitster@pobox.com>
Fri, 28 Mar 2014 20:51:11 +0000 (13:51 -0700)
When it is not necessary to edit a commit log message (e.g. "git
commit -m" is given a message without specifying "-e"), we used to
disable the spawning of the editor by overriding GIT_EDITOR, but
this means all the uses of the editor, other than to edit the
commit log message, are also affected.

* bp/commit-p-editor:
run-command: mark run_hook_with_custom_index as deprecated
merge hook tests: fix and update tests
merge: fix GIT_EDITOR override for commit hook
commit: fix patch hunk editing with "commit -p -m"
test patch hunk editing with "commit -p -m"
merge hook tests: use 'test_must_fail' instead of '!'
merge hook tests: fix missing '&&' in test

1  2 
builtin/checkout.c
builtin/commit.c
builtin/gc.c
builtin/merge.c
commit.h
diff --combined builtin/checkout.c
index ada51fa70ff59b10fd79168a4377d923638591e9,624bfbad7c76dea54ce90e62f0717157f622e2e5..1b86d9c868c35c7f0ad3f4b39f9d225c8365c77c
@@@ -53,10 -53,10 +53,10 @@@ struct checkout_opts 
  static int post_checkout_hook(struct commit *old, struct commit *new,
                              int changed)
  {
-       return run_hook(NULL, "post-checkout",
-                       sha1_to_hex(old ? old->object.sha1 : null_sha1),
-                       sha1_to_hex(new ? new->object.sha1 : null_sha1),
-                       changed ? "1" : "0", NULL);
+       return run_hook_le(NULL, "post-checkout",
+                          sha1_to_hex(old ? old->object.sha1 : null_sha1),
+                          sha1_to_hex(new ? new->object.sha1 : null_sha1),
+                          changed ? "1" : "0", NULL);
        /* "new" can be NULL when checking out from the index before
           a commit exists. */
  
@@@ -297,7 -297,8 +297,7 @@@ static int checkout_paths(const struct 
                 * match_pathspec() for _all_ entries when
                 * opts->source_tree != NULL.
                 */
 -              if (match_pathspec_depth(&opts->pathspec, ce->name, ce_namelen(ce),
 -                                 0, ps_matched))
 +              if (ce_path_match(ce, &opts->pathspec, ps_matched))
                        ce->ce_flags |= CE_MATCHED;
        }
  
diff --combined builtin/commit.c
index 38f34e7cd3c7ffd482eb13fcf810346e1da4d944,baf1fc0fff2b1d910eb470797f7605a6a904bd60..d9550c54d02bbd1ba4df87734433dea4a7097e2e
@@@ -113,7 -113,6 +113,7 @@@ static char *sign_commit
  static enum {
        CLEANUP_SPACE,
        CLEANUP_NONE,
 +      CLEANUP_SCISSORS,
        CLEANUP_ALL
  } cleanup_mode;
  static const char *cleanup_arg;
@@@ -235,7 -234,7 +235,7 @@@ static int list_paths(struct string_lis
  
                if (ce->ce_flags & CE_UPDATE)
                        continue;
 -              if (!match_pathspec_depth(pattern, ce->name, ce_namelen(ce), 0, m))
 +              if (!ce_path_match(ce, pattern, m))
                        continue;
                item = string_list_insert(list, ce->name);
                if (ce_skip_worktree(ce))
@@@ -308,6 -307,7 +308,6 @@@ static char *prepare_index(int argc, co
        int fd;
        struct string_list partial;
        struct pathspec pathspec;
 -      char *old_index_env = NULL;
        int refresh_flags = REFRESH_QUIET;
  
        if (is_status)
                die(_("index file corrupt"));
  
        if (interactive) {
 +              char *old_index_env = NULL;
                fd = hold_locked_index(&index_lock, 1);
  
                refresh_cache_or_die(refresh_flags);
@@@ -601,17 -600,19 +601,17 @@@ static int prepare_to_commit(const cha
  {
        struct stat statbuf;
        struct strbuf committer_ident = STRBUF_INIT;
 -      int commitable, saved_color_setting;
 +      int commitable;
        struct strbuf sb = STRBUF_INIT;
 -      char *buffer;
        const char *hook_arg1 = NULL;
        const char *hook_arg2 = NULL;
 -      int ident_shown = 0;
        int clean_message_contents = (cleanup_mode != CLEANUP_NONE);
        int old_display_comment_prefix;
  
        /* This checks and barfs if author is badly specified */
        determine_author_info(author_ident);
  
-       if (!no_verify && run_hook(index_file, "pre-commit", NULL))
+       if (!no_verify && run_commit_hook(use_editor, index_file, "pre-commit", NULL))
                return 0;
  
        if (squash_message) {
                                  logfile);
                hook_arg1 = "message";
        } else if (use_message) {
 +              char *buffer;
                buffer = strstr(use_message_buffer, "\n\n");
                if (!use_editor && (!buffer || buffer[2] == '\0'))
                        die(_("commit has empty message"));
        /* This checks if committer ident is explicitly given */
        strbuf_addstr(&committer_ident, git_committer_info(IDENT_STRICT));
        if (use_editor && include_status) {
 +              int ident_shown = 0;
 +              int saved_color_setting;
                char *ai_tmp, *ci_tmp;
 -              if (whence != FROM_COMMIT)
 +              if (whence != FROM_COMMIT) {
 +                      if (cleanup_mode == CLEANUP_SCISSORS)
 +                              wt_status_add_cut_line(s->fp);
                        status_printf_ln(s, GIT_COLOR_NORMAL,
                            whence == FROM_MERGE
                                ? _("\n"
                                git_path(whence == FROM_MERGE
                                         ? "MERGE_HEAD"
                                         : "CHERRY_PICK_HEAD"));
 +              }
  
                fprintf(s->fp, "\n");
                if (cleanup_mode == CLEANUP_ALL)
                                _("Please enter the commit message for your changes."
                                  " Lines starting\nwith '%c' will be ignored, and an empty"
                                  " message aborts the commit.\n"), comment_line_char);
 +              else if (cleanup_mode == CLEANUP_SCISSORS && whence == FROM_COMMIT)
 +                      wt_status_add_cut_line(s->fp);
                else /* CLEANUP_SPACE, that is. */
                        status_printf(s, GIT_COLOR_NORMAL,
                                _("Please enter the commit message for your changes."
                return 0;
        }
  
-       if (run_hook(index_file, "prepare-commit-msg",
-                    git_path(commit_editmsg), hook_arg1, hook_arg2, NULL))
+       if (run_commit_hook(use_editor, index_file, "prepare-commit-msg",
+                           git_path(commit_editmsg), hook_arg1, hook_arg2, NULL))
                return 0;
  
        if (use_editor) {
        }
  
        if (!no_verify &&
-           run_hook(index_file, "commit-msg", git_path(commit_editmsg), NULL)) {
+           run_commit_hook(use_editor, index_file, "commit-msg", git_path(commit_editmsg), NULL)) {
                return 0;
        }
  
@@@ -1074,8 -1067,6 +1074,6 @@@ static int parse_and_validate_options(i
                use_editor = 0;
        if (0 <= edit_flag)
                use_editor = edit_flag;
-       if (!use_editor)
-               setenv("GIT_EDITOR", ":", 1);
  
        /* Sanity check options */
        if (amend && !current_head)
                cleanup_mode = CLEANUP_SPACE;
        else if (!strcmp(cleanup_arg, "strip"))
                cleanup_mode = CLEANUP_ALL;
 +      else if (!strcmp(cleanup_arg, "scissors"))
 +              cleanup_mode = use_editor ? CLEANUP_SCISSORS : CLEANUP_SPACE;
        else
                die(_("Invalid cleanup mode %s"), cleanup_arg);
  
@@@ -1415,10 -1404,6 +1413,10 @@@ static int git_commit_config(const cha
        }
        if (!strcmp(k, "commit.cleanup"))
                return git_config_string(&cleanup_arg, k, v);
 +      if (!strcmp(k, "commit.gpgsign")) {
 +              sign_commit = git_config_bool(k, v) ? "" : NULL;
 +              return 0;
 +      }
  
        status = git_gpg_config(k, v, NULL);
        if (status)
@@@ -1458,6 -1443,29 +1456,29 @@@ static int run_rewrite_hook(const unsig
        return finish_command(&proc);
  }
  
+ int run_commit_hook(int editor_is_used, const char *index_file, const char *name, ...)
+ {
+       const char *hook_env[3] =  { NULL };
+       char index[PATH_MAX];
+       va_list args;
+       int ret;
+       snprintf(index, sizeof(index), "GIT_INDEX_FILE=%s", index_file);
+       hook_env[0] = index;
+       /*
+        * Let the hook know that no editor will be launched.
+        */
+       if (!editor_is_used)
+               hook_env[1] = "GIT_EDITOR=:";
+       va_start(args, name);
+       ret = run_hook_ve(hook_env, name, args);
+       va_end(args);
+       return ret;
+ }
  int cmd_commit(int argc, const char **argv, const char *prefix)
  {
        static struct wt_status s;
        struct ref_lock *ref_lock;
        struct commit_list *parents = NULL, **pptr = &parents;
        struct stat statbuf;
 -      int allow_fast_forward = 1;
        struct commit *current_head = NULL;
        struct commit_extra_header *extra = NULL;
  
        } else if (whence == FROM_MERGE) {
                struct strbuf m = STRBUF_INIT;
                FILE *fp;
 +              int allow_fast_forward = 1;
  
                if (!reflog_msg)
                        reflog_msg = "commit (merge)";
                die(_("could not read commit message: %s"), strerror(saved_errno));
        }
  
 -      /* Truncate the message just before the diff, if any. */
 -      if (verbose)
 +      if (verbose || /* Truncate the message just before the diff, if any. */
 +          cleanup_mode == CLEANUP_SCISSORS)
                wt_status_truncate_message_at_cut_line(&sb);
  
        if (cleanup_mode != CLEANUP_NONE)
                     "not exceeded, and then \"git reset HEAD\" to recover."));
  
        rerere(0);
-       run_hook(get_index_file(), "post-commit", NULL);
+       run_commit_hook(use_editor, get_index_file(), "post-commit", NULL);
        if (amend && !no_post_rewrite) {
                struct notes_rewrite_cfg *cfg;
                cfg = init_copy_notes_for_rewrite("amend");
diff --combined builtin/gc.c
index 63d400bcb2092b1751427994b35057f72b04de17,7fa717a3b6ab08bb5b4d5549eeb96f07460f95e6..11cf295515a25b1df19af7a14c2cd03911d957b5
@@@ -29,7 -29,6 +29,7 @@@ static int pack_refs = 1
  static int aggressive_window = 250;
  static int gc_auto_threshold = 6700;
  static int gc_auto_pack_limit = 50;
 +static int detach_auto = 1;
  static const char *prune_expire = "2.weeks.ago";
  
  static struct argv_array pack_refs_cmd = ARGV_ARRAY_INIT;
@@@ -74,10 -73,6 +74,10 @@@ static int gc_config(const char *var, c
                gc_auto_pack_limit = git_config_int(var, value);
                return 0;
        }
 +      if (!strcmp(var, "gc.autodetach")) {
 +              detach_auto = git_config_bool(var, value);
 +              return 0;
 +      }
        if (!strcmp(var, "gc.pruneexpire")) {
                if (value && strcmp(value, "now")) {
                        unsigned long now = approxidate("now");
@@@ -184,7 -179,7 +184,7 @@@ static int need_to_gc(void
        else if (!too_many_loose_objects())
                return 0;
  
-       if (run_hook(NULL, "pre-auto-gc", NULL))
+       if (run_hook_le(NULL, "pre-auto-gc", NULL))
                return 0;
        return 1;
  }
  static const char *lock_repo_for_gc(int force, pid_t* ret_pid)
  {
        static struct lock_file lock;
 -      static char locking_host[128];
        char my_host[128];
        struct strbuf sb = STRBUF_INIT;
        struct stat st;
        uintmax_t pid;
        FILE *fp;
 -      int fd, should_exit;
 +      int fd;
  
        if (pidfile)
                /* already locked */
        fd = hold_lock_file_for_update(&lock, git_path("gc.pid"),
                                       LOCK_DIE_ON_ERROR);
        if (!force) {
 +              static char locking_host[128];
 +              int should_exit;
                fp = fopen(git_path("gc.pid"), "r");
                memset(locking_host, 0, sizeof(locking_host));
                should_exit =
@@@ -307,19 -301,11 +307,19 @@@ int cmd_gc(int argc, const char **argv
                 */
                if (!need_to_gc())
                        return 0;
 -              if (!quiet)
 -                      fprintf(stderr,
 -                                      _("Auto packing the repository for optimum performance. You may also\n"
 -                                      "run \"git gc\" manually. See "
 -                                      "\"git help gc\" for more information.\n"));
 +              if (!quiet) {
 +                      if (detach_auto)
 +                              fprintf(stderr, _("Auto packing the repository in background for optimum performance.\n"));
 +                      else
 +                              fprintf(stderr, _("Auto packing the repository for optimum performance.\n"));
 +                      fprintf(stderr, _("See \"git help gc\" for manual housekeeping.\n"));
 +              }
 +              if (detach_auto)
 +                      /*
 +                       * failure to daemonize is ok, we'll continue
 +                       * in foreground
 +                       */
 +                      daemonize();
        } else
                add_repack_all_option();
  
diff --combined builtin/merge.c
index f0cf1205faa66c5ae8b4603f04239f1efbd999d6,b11a528ce5580d5e5b9b61f291e0d829a735ae6a..e15d0e145a51d52687619673aec3ee80c0485375
@@@ -421,7 -421,7 +421,7 @@@ static void finish(struct commit *head_
        }
  
        /* Run a post-merge hook */
-       run_hook(NULL, "post-merge", squash ? "1" : "0", NULL);
+       run_hook_le(NULL, "post-merge", squash ? "1" : "0", NULL);
  
        strbuf_release(&reflog_message);
  }
@@@ -597,9 -597,6 +597,9 @@@ static int git_merge_config(const char 
        } else if (!strcmp(k, "merge.defaulttoupstream")) {
                default_to_upstream = git_config_bool(k, v);
                return 0;
 +      } else if (!strcmp(k, "commit.gpgsign")) {
 +              sign_commit = git_config_bool(k, v) ? "" : NULL;
 +              return 0;
        }
  
        status = fmt_merge_msg_config(k, v, cb);
@@@ -824,8 -821,8 +824,8 @@@ static void prepare_to_commit(struct co
        if (0 < option_edit)
                strbuf_commented_addf(&msg, _(merge_editor_comment), comment_line_char);
        write_merge_msg(&msg);
-       if (run_hook(get_index_file(), "prepare-commit-msg",
-                    git_path("MERGE_MSG"), "merge", NULL, NULL))
+       if (run_commit_hook(0 < option_edit, get_index_file(), "prepare-commit-msg",
+                           git_path("MERGE_MSG"), "merge", NULL))
                abort_commit(remoteheads, NULL);
        if (0 < option_edit) {
                if (launch_editor(git_path("MERGE_MSG"), NULL, NULL))
diff --combined commit.h
index 55631f191f2a01276e8a16192117fb3cf25bc958,8d97a5caa3bd3ff5686f68998102527a3876bc4f..a9f177ba488a7002409eb2cdee1f7e9c3673529f
+++ b/commit.h
@@@ -209,7 -209,7 +209,7 @@@ extern int write_shallow_commits(struc
  extern void setup_alternate_shallow(struct lock_file *shallow_lock,
                                    const char **alternate_shallow_file,
                                    const struct sha1_array *extra);
 -extern char *setup_temporary_shallow(const struct sha1_array *extra);
 +extern const char *setup_temporary_shallow(const struct sha1_array *extra);
  extern void advertise_shallow_grafts(int);
  
  struct shallow_info {
@@@ -304,4 -304,7 +304,7 @@@ extern void check_commit_signature(cons
  
  int compare_commits_by_commit_date(const void *a_, const void *b_, void *unused);
  
+ LAST_ARG_MUST_BE_NULL
+ extern int run_commit_hook(int editor_is_used, const char *index_file, const char *name, ...);
  #endif /* COMMIT_H */