Skip to content

Commit f7c9dac

Browse files
sunshinecogitster
authored andcommitted
worktree: detect branch-name/detached and error conditions locally
git-worktree currently conflates setting of HEAD in the new worktree with initial worktree population via a single git-checkout invocation, which requires git-checkout to have special knowledge that it is operating in a newly created worktree. The eventual goal is to separate these operations and rid git-checkout of that overly-intimate knowledge. Once these operations are separate, git-worktree will no longer be able to rely upon git-branch to determine the state of the worktree (branch name or detached), or to check for error conditions, such as the requested branch already checked out elsewhere, or an invalid reference. Therefore, imbue git-worktree with the intelligence to determine a branch name or detached state locally, and to perform error checking on its own. Signed-off-by: Eric Sunshine <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 80a0548 commit f7c9dac

File tree

1 file changed

+18
-0
lines changed

1 file changed

+18
-0
lines changed

builtin/worktree.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
#include "dir.h"
44
#include "parse-options.h"
55
#include "argv-array.h"
6+
#include "branch.h"
7+
#include "refs.h"
68
#include "run-command.h"
79
#include "sigchain.h"
810

@@ -188,11 +190,26 @@ static int add_worktree(const char *path, const char *refname,
188190
struct child_process cp;
189191
struct argv_array child_env = ARGV_ARRAY_INIT;
190192
int counter = 0, len, ret;
193+
struct strbuf symref = STRBUF_INIT;
194+
struct commit *commit = NULL;
191195
unsigned char rev[20];
192196

193197
if (file_exists(path) && !is_empty_dir(path))
194198
die(_("'%s' already exists"), path);
195199

200+
/* is 'refname' a branch or commit? */
201+
if (opts->force_new_branch) /* definitely a branch */
202+
;
203+
else if (!opts->detach && !strbuf_check_branch_ref(&symref, refname) &&
204+
ref_exists(symref.buf)) { /* it's a branch */
205+
if (!opts->force)
206+
die_if_checked_out(symref.buf);
207+
} else { /* must be a commit */
208+
commit = lookup_commit_reference_by_name(refname);
209+
if (!commit)
210+
die(_("invalid reference: %s"), refname);
211+
}
212+
196213
name = worktree_basename(path, &len);
197214
strbuf_addstr(&sb_repo,
198215
git_path("worktrees/%.*s", (int)(path + len - name), name));
@@ -281,6 +298,7 @@ static int add_worktree(const char *path, const char *refname,
281298
unlink_or_warn(sb.buf);
282299
argv_array_clear(&child_env);
283300
strbuf_release(&sb);
301+
strbuf_release(&symref);
284302
strbuf_release(&sb_repo);
285303
strbuf_release(&sb_git);
286304
return ret;

0 commit comments

Comments
 (0)