Merge branch 'sb/submodule-update-reset-fix' into maint
[gitweb.git] / builtin / worktree.c
index 15cb1600eebc3fd209fc88561f811e132b493131..7cef5b120b7786d107282d03052c5e06d3a2c85a 100644 (file)
@@ -33,8 +33,19 @@ struct add_opts {
 
 static int show_only;
 static int verbose;
+static int guess_remote;
 static timestamp_t expire;
 
+static int git_worktree_config(const char *var, const char *value, void *cb)
+{
+       if (!strcmp(var, "worktree.guessremote")) {
+               guess_remote = git_config_bool(var, value);
+               return 0;
+       }
+
+       return git_default_config(var, value, cb);
+}
+
 static int prune_worktree(const char *id, struct strbuf *reason)
 {
        struct stat st;
@@ -219,20 +230,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);
@@ -297,7 +309,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
@@ -328,6 +340,15 @@ static int add_worktree(const char *path, const char *refname,
                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);
@@ -343,7 +364,6 @@ static int add(int ac, const char **av, const char *prefix)
        char *path;
        const char *branch;
        const char *opt_track = NULL;
-       int guess_remote = 0;
        struct option options[] = {
                OPT__FORCE(&opts.force, N_("checkout <branch> even if already checked out in other worktree")),
                OPT_STRING('b', NULL, &opts.new_branch, N_("branch"),
@@ -591,7 +611,7 @@ int cmd_worktree(int ac, const char **av, const char *prefix)
                OPT_END()
        };
 
-       git_config(git_default_config, NULL);
+       git_config(git_worktree_config, NULL);
 
        if (ac < 2)
                usage_with_options(worktree_usage, options);