From ade546be4786637ba039478d6f027becb1160803 Mon Sep 17 00:00:00 2001 From: Eric Sunshine Date: Thu, 7 Dec 2017 16:20:17 -0500 Subject: worktree: invoke post-checkout hook (unless --no-checkout) 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 Signed-off-by: Eric Sunshine Signed-off-by: Junio C Hamano --- builtin/worktree.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) (limited to 'builtin') diff --git a/builtin/worktree.c b/builtin/worktree.c index ed043d5f1..9591f1044 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); -- cgit v1.2.1