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

builtin/checkout.c
builtin/clone.c
builtin/commit.c
builtin/gc.c
builtin/merge.c
commit.h
run-command.c
run-command.h
t/t7505-prepare-commit-msg-hook.sh
t/t7514-commit-patch.sh [new file with mode: 0755]
index ada51fa70ff59b10fd79168a4377d923638591e9..1b86d9c868c35c7f0ad3f4b39f9d225c8365c77c 100644 (file)
@@ -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. */
 
index 43e772ccdbaba3172f7ee1a969f92b300cb9d5a1..9b3c04d914b3d318f723c2d3ded403fca9503c07 100644 (file)
@@ -660,8 +660,8 @@ static int checkout(void)
            commit_locked_index(lock_file))
                die(_("unable to write new index file"));
 
-       err |= run_hook(NULL, "post-checkout", sha1_to_hex(null_sha1),
-                       sha1_to_hex(sha1), "1", NULL);
+       err |= run_hook_le(NULL, "post-checkout", sha1_to_hex(null_sha1),
+                          sha1_to_hex(sha1), "1", NULL);
 
        if (!err && option_recursive)
                err = run_command_v_opt(argv_submodule, RUN_GIT_CMD);
index 38f34e7cd3c7ffd482eb13fcf810346e1da4d944..d9550c54d02bbd1ba4df87734433dea4a7097e2e 100644 (file)
@@ -611,7 +611,7 @@ static int prepare_to_commit(const char *index_file, const char *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) {
@@ -873,8 +873,8 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
                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) {
@@ -890,7 +890,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
        }
 
        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 +1074,6 @@ static int parse_and_validate_options(int argc, const char *argv[],
                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)
@@ -1458,6 +1456,29 @@ static int run_rewrite_hook(const unsigned char *oldsha1,
        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;
@@ -1682,7 +1703,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
                     "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");
index 63d400bcb2092b1751427994b35057f72b04de17..11cf295515a25b1df19af7a14c2cd03911d957b5 100644 (file)
@@ -184,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;
 }
index f0cf1205faa66c5ae8b4603f04239f1efbd999d6..e15d0e145a51d52687619673aec3ee80c0485375 100644 (file)
@@ -421,7 +421,7 @@ static void finish(struct commit *head_commit,
        }
 
        /* 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);
 }
@@ -824,8 +824,8 @@ static void prepare_to_commit(struct commit_list *remoteheads)
        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))
index 55631f191f2a01276e8a16192117fb3cf25bc958..a9f177ba488a7002409eb2cdee1f7e9c3673529f 100644 (file)
--- a/commit.h
+++ b/commit.h
@@ -304,4 +304,7 @@ extern void check_commit_signature(const struct commit* commit, struct signature
 
 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 */
index 3914d9c5117f29651b56772da143f0a226494a62..75abc478c6da75471e5fdbb55c74efdfcf3ad160 100644 (file)
@@ -760,13 +760,11 @@ char *find_hook(const char *name)
        return path;
 }
 
-int run_hook(const char *index_file, const char *name, ...)
+int run_hook_ve(const char *const *env, const char *name, va_list args)
 {
        struct child_process hook;
        struct argv_array argv = ARGV_ARRAY_INIT;
-       const char *p, *env[2];
-       char index[PATH_MAX];
-       va_list args;
+       const char *p;
        int ret;
 
        p = find_hook(name);
@@ -775,23 +773,45 @@ int run_hook(const char *index_file, const char *name, ...)
 
        argv_array_push(&argv, p);
 
-       va_start(args, name);
        while ((p = va_arg(args, const char *)))
                argv_array_push(&argv, p);
-       va_end(args);
 
        memset(&hook, 0, sizeof(hook));
        hook.argv = argv.argv;
+       hook.env = env;
        hook.no_stdin = 1;
        hook.stdout_to_stderr = 1;
-       if (index_file) {
-               snprintf(index, sizeof(index), "GIT_INDEX_FILE=%s", index_file);
-               env[0] = index;
-               env[1] = NULL;
-               hook.env = env;
-       }
 
        ret = run_command(&hook);
        argv_array_clear(&argv);
        return ret;
 }
+
+int run_hook_le(const char *const *env, const char *name, ...)
+{
+       va_list args;
+       int ret;
+
+       va_start(args, name);
+       ret = run_hook_ve(env, name, args);
+       va_end(args);
+
+       return ret;
+}
+
+int run_hook_with_custom_index(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;
+
+       va_start(args, name);
+       ret = run_hook_ve(hook_env, name, args);
+       va_end(args);
+
+       return ret;
+}
index 6b985afd07a5b58ecadad8859ae90b3430ccb4c2..3653bfa6e123ca8497571a2ca1c47200c1b544a2 100644 (file)
@@ -47,7 +47,12 @@ int run_command(struct child_process *);
 
 extern char *find_hook(const char *name);
 LAST_ARG_MUST_BE_NULL
-extern int run_hook(const char *index_file, const char *name, ...);
+extern int run_hook_le(const char *const *env, const char *name, ...);
+extern int run_hook_ve(const char *const *env, const char *name, va_list args);
+
+LAST_ARG_MUST_BE_NULL
+__attribute__((deprecated))
+extern int run_hook_with_custom_index(const char *index_file, const char *name, ...);
 
 #define RUN_COMMAND_NO_STDIN 1
 #define RUN_GIT_CMD         2  /*If this is to be git sub-command */
index 357375151d79d03d11275875dd10ceea42a3ba47..03dce09cfea5f1b5c19e7e8c4537a657cdf55dfc 100755 (executable)
@@ -134,14 +134,26 @@ test_expect_success 'with hook (-c)' '
 
 test_expect_success 'with hook (merge)' '
 
-       head=`git rev-parse HEAD` &&
-       git checkout -b other HEAD@{1} &&
-       echo "more" >> file &&
+       test_when_finished "git checkout -f master" &&
+       git checkout -B other HEAD@{1} &&
+       echo "more" >>file &&
+       git add file &&
+       git commit -m other &&
+       git checkout - &&
+       git merge --no-ff other &&
+       test "`git log -1 --pretty=format:%s`" = "merge (no editor)"
+'
+
+test_expect_success 'with hook and editor (merge)' '
+
+       test_when_finished "git checkout -f master" &&
+       git checkout -B other HEAD@{1} &&
+       echo "more" >>file &&
        git add file &&
        git commit -m other &&
        git checkout - &&
-       git merge other &&
-       test "`git log -1 --pretty=format:%s`" = merge
+       env GIT_EDITOR="\"\$FAKE_EDITOR\"" git merge --no-ff -e other &&
+       test "`git log -1 --pretty=format:%s`" = "merge"
 '
 
 cat > "$HOOK" <<'EOF'
@@ -151,34 +163,37 @@ EOF
 
 test_expect_success 'with failing hook' '
 
+       test_when_finished "git checkout -f master" &&
        head=`git rev-parse HEAD` &&
        echo "more" >> file &&
        git add file &&
-       ! GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit -c $head
+       test_must_fail env GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit -c $head
 
 '
 
 test_expect_success 'with failing hook (--no-verify)' '
 
+       test_when_finished "git checkout -f master" &&
        head=`git rev-parse HEAD` &&
        echo "more" >> file &&
        git add file &&
-       ! GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit --no-verify -c $head
+       test_must_fail env GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit --no-verify -c $head
 
 '
 
 test_expect_success 'with failing hook (merge)' '
 
+       test_when_finished "git checkout -f master" &&
        git checkout -B other HEAD@{1} &&
        echo "more" >> file &&
        git add file &&
        rm -f "$HOOK" &&
        git commit -m other &&
-       write_script "$HOOK" <<-EOF
+       write_script "$HOOK" <<-EOF &&
        exit 1
        EOF
        git checkout - &&
-       test_must_fail git merge other
+       test_must_fail git merge --no-ff other
 
 '
 
diff --git a/t/t7514-commit-patch.sh b/t/t7514-commit-patch.sh
new file mode 100755 (executable)
index 0000000..998a210
--- /dev/null
@@ -0,0 +1,34 @@
+#!/bin/sh
+
+test_description='hunk edit with "commit -p -m"'
+. ./test-lib.sh
+
+if ! test_have_prereq PERL
+then
+       skip_all="skipping '$test_description' tests, perl not available"
+       test_done
+fi
+
+test_expect_success 'setup (initial)' '
+       echo line1 >file &&
+       git add file &&
+       git commit -m commit1
+'
+
+test_expect_success 'edit hunk "commit -p -m message"' '
+       test_when_finished "rm -f editor_was_started" &&
+       rm -f editor_was_started &&
+       echo more >>file &&
+       echo e | env GIT_EDITOR=": >editor_was_started" git commit -p -m commit2 file &&
+       test -r editor_was_started
+'
+
+test_expect_success 'edit hunk "commit --dry-run -p -m message"' '
+       test_when_finished "rm -f editor_was_started" &&
+       rm -f editor_was_started &&
+       echo more >>file &&
+       echo e | env GIT_EDITOR=": >editor_was_started" git commit -p -m commit3 file &&
+       test -r editor_was_started
+'
+
+test_done