summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Sunshine <sunshine@sunshineco.com>2017-12-07 16:20:17 -0500
committerJunio C Hamano <gitster@pobox.com>2017-12-07 14:02:28 -0800
commitade546be4786637ba039478d6f027becb1160803 (patch)
treefec3e4c4218543e1871e7739dc9f432e04eb16be
parent95ec6b1b3393eb6e26da40c565520a8db9796e9f (diff)
downloadgit-es/worktree-checkout-hook.tar.gz
worktree: invoke post-checkout hook (unless --no-checkout)es/worktree-checkout-hook
git-clone and git-checkout both invoke the post-checkout hook following a successful checkout, yet git-worktree neglects to do so even though it too "checks out" the worktree. Fix this oversight. Implementation note: The newly-created worktree may reference a branch or be detached. In the latter case, a commit lookup is performed, though the result is used only in a boolean sense to (a) determine if the commit actually exists, and (b) assign either the branch name or commit ID to HEAD. Since the post-commit hook needs to know the ID of the checked-out commit, the lookup now needs to be done in all cases, rather than only when detached. Consequently, a new boolean is needed to handle (b) since the lookup result itself can no longer perform that role. Reported-by: Matthew K Gumbel <matthew.k.gumbel@intel.com> Signed-off-by: Eric Sunshine <sunshine@sunshineco.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
-rw-r--r--Documentation/githooks.txt3
-rw-r--r--builtin/worktree.c22
-rwxr-xr-xt/t2025-worktree-add.sh29
3 files changed, 47 insertions, 7 deletions
diff --git a/Documentation/githooks.txt b/Documentation/githooks.txt
index 0bb0042d8c..91eb297f7b 100644
--- a/Documentation/githooks.txt
+++ b/Documentation/githooks.txt
@@ -170,7 +170,8 @@ This hook cannot affect the outcome of 'git checkout'.
It is also run after 'git clone', unless the --no-checkout (-n) option is
used. The first parameter given to the hook is the null-ref, the second the
-ref of the new HEAD and the flag is always 1.
+ref of the new HEAD and the flag is always 1. Likewise for 'git worktree add'
+unless --no-checkout is used.
This hook can be used to perform repository validity checks, auto-display
differences from the previous HEAD if different, or set working dir metadata
diff --git a/builtin/worktree.c b/builtin/worktree.c
index ed043d5f1c..9591f10442 100644
--- a/builtin/worktree.c
+++ b/builtin/worktree.c
@@ -218,20 +218,21 @@ static int add_worktree(const char *path, const char *refname,
int counter = 0, len, ret;
struct strbuf symref = STRBUF_INIT;
struct commit *commit = NULL;
+ int is_branch = 0;
if (file_exists(path) && !is_empty_dir(path))
die(_("'%s' already exists"), path);
/* is 'refname' a branch or commit? */
if (!opts->detach && !strbuf_check_branch_ref(&symref, refname) &&
- ref_exists(symref.buf)) { /* it's a branch */
+ ref_exists(symref.buf)) {
+ is_branch = 1;
if (!opts->force)
die_if_checked_out(symref.buf, 0);
- } else { /* must be a commit */
- commit = lookup_commit_reference_by_name(refname);
- if (!commit)
- die(_("invalid reference: %s"), refname);
}
+ commit = lookup_commit_reference_by_name(refname);
+ if (!commit)
+ die(_("invalid reference: %s"), refname);
name = worktree_basename(path, &len);
git_path_buf(&sb_repo, "worktrees/%.*s", (int)(path + len - name), name);
@@ -296,7 +297,7 @@ static int add_worktree(const char *path, const char *refname,
argv_array_pushf(&child_env, "%s=%s", GIT_WORK_TREE_ENVIRONMENT, path);
cp.git_cmd = 1;
- if (commit)
+ if (!is_branch)
argv_array_pushl(&cp.args, "update-ref", "HEAD",
oid_to_hex(&commit->object.oid), NULL);
else
@@ -327,6 +328,15 @@ done:
strbuf_addf(&sb, "%s/locked", sb_repo.buf);
unlink_or_warn(sb.buf);
}
+
+ /*
+ * Hook failure does not warrant worktree deletion, so run hook after
+ * is_junk is cleared, but do return appropriate code when hook fails.
+ */
+ if (!ret && opts->checkout)
+ ret = run_hook_le(NULL, "post-checkout", oid_to_hex(&null_oid),
+ oid_to_hex(&commit->object.oid), "1", NULL);
+
argv_array_clear(&child_env);
strbuf_release(&sb);
strbuf_release(&symref);
diff --git a/t/t2025-worktree-add.sh b/t/t2025-worktree-add.sh
index b5c47ac602..d6fb062f83 100755
--- a/t/t2025-worktree-add.sh
+++ b/t/t2025-worktree-add.sh
@@ -314,4 +314,33 @@ test_expect_success 'rename a branch under bisect not allowed' '
test_must_fail git branch -M under-bisect bisect-with-new-name
'
+post_checkout_hook () {
+ test_when_finished "rm -f .git/hooks/post-checkout" &&
+ mkdir -p .git/hooks &&
+ write_script .git/hooks/post-checkout <<-\EOF
+ echo $* >hook.actual
+ EOF
+}
+
+test_expect_success '"add" invokes post-checkout hook (branch)' '
+ post_checkout_hook &&
+ printf "%s %s 1\n" $_z40 $(git rev-parse HEAD) >hook.expect &&
+ git worktree add gumby &&
+ test_cmp hook.expect hook.actual
+'
+
+test_expect_success '"add" invokes post-checkout hook (detached)' '
+ post_checkout_hook &&
+ printf "%s %s 1\n" $_z40 $(git rev-parse HEAD) >hook.expect &&
+ git worktree add --detach grumpy &&
+ test_cmp hook.expect hook.actual
+'
+
+test_expect_success '"add --no-checkout" suppresses post-checkout hook' '
+ post_checkout_hook &&
+ rm -f hook.actual &&
+ git worktree add --no-checkout gloopy &&
+ test_path_is_missing hook.actual
+'
+
test_done