diff --git a/builtin/worktree.c b/builtin/worktree.c index da76eb7d348..cf35b2aa7e2 100644 --- a/builtin/worktree.c +++ b/builtin/worktree.c @@ -3,6 +3,8 @@ #include "dir.h" #include "parse-options.h" #include "argv-array.h" +#include "branch.h" +#include "refs.h" #include "run-command.h" #include "sigchain.h" @@ -188,11 +190,26 @@ static int add_worktree(const char *path, const char *refname, struct child_process cp; struct argv_array child_env = ARGV_ARRAY_INIT; int counter = 0, len, ret; + struct strbuf symref = STRBUF_INIT; + struct commit *commit = NULL; unsigned char rev[20]; if (file_exists(path) && !is_empty_dir(path)) die(_("'%s' already exists"), path); + /* is 'refname' a branch or commit? */ + if (opts->force_new_branch) /* definitely a branch */ + ; + else if (!opts->detach && !strbuf_check_branch_ref(&symref, refname) && + ref_exists(symref.buf)) { /* it's a branch */ + if (!opts->force) + die_if_checked_out(symref.buf); + } else { /* must be a commit */ + commit = lookup_commit_reference_by_name(refname); + if (!commit) + die(_("invalid reference: %s"), refname); + } + name = worktree_basename(path, &len); strbuf_addstr(&sb_repo, git_path("worktrees/%.*s", (int)(path + len - name), name)); @@ -281,6 +298,7 @@ static int add_worktree(const char *path, const char *refname, unlink_or_warn(sb.buf); argv_array_clear(&child_env); strbuf_release(&sb); + strbuf_release(&symref); strbuf_release(&sb_repo); strbuf_release(&sb_git); return ret;