summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLibravatar Eric Sunshine <sunshine@sunshineco.com>2015-07-17 19:00:13 -0400
committerLibravatar Junio C Hamano <gitster@pobox.com>2015-07-20 11:29:52 -0700
commitf7c9dac1b037e453e934c272d77cc648d56d5477 (patch)
tree9eb5bec4ee344a68f62d19039879486f8f2d01d6
parentworktree: add_worktree: construct worktree-population command locally (diff)
downloadtgif-f7c9dac1b037e453e934c272d77cc648d56d5477.tar.xz
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 <sunshine@sunshineco.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
-rw-r--r--builtin/worktree.c18
1 files changed, 18 insertions, 0 deletions
diff --git a/builtin/worktree.c b/builtin/worktree.c
index da76eb7d34..cf35b2aa7e 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;