summaryrefslogtreecommitdiff
path: root/branch.c
diff options
context:
space:
mode:
authorLibravatar David Turner <dturner@twopensource.com>2015-08-10 13:52:44 -0400
committerLibravatar Junio C Hamano <gitster@pobox.com>2015-08-11 13:48:15 -0700
commit41af65651d4333cd19ab4af3509fa2d08f3816ed (patch)
tree19a55a6e2d48d20fc6bee7f6f2a99f3ae7ba8f0d /branch.c
parentDocumentation/git-worktree: fix duplicated 'from' (diff)
downloadtgif-41af65651d4333cd19ab4af3509fa2d08f3816ed.tar.xz
worktrees: add find_shared_symref
Add a new function, find_shared_symref, which contains the heart of die_if_checked_out, but works for any symref, not just HEAD. Refactor die_if_checked_out to use the same infrastructure as find_shared_symref. Soon, we will use find_shared_symref to protect notes merges in worktrees. Signed-off-by: David Turner <dturner@twopensource.com> Reviewed-by: Johan Herland <johan@herland.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'branch.c')
-rw-r--r--branch.c46
1 files changed, 34 insertions, 12 deletions
diff --git a/branch.c b/branch.c
index af9480f25a..483c52740f 100644
--- a/branch.c
+++ b/branch.c
@@ -310,21 +310,23 @@ void remove_branch_state(void)
unlink(git_path("SQUASH_MSG"));
}
-static void check_linked_checkout(const char *branch, const char *id)
+static char *find_linked_symref(const char *symref, const char *branch,
+ const char *id)
{
struct strbuf sb = STRBUF_INIT;
struct strbuf path = STRBUF_INIT;
struct strbuf gitdir = STRBUF_INIT;
+ char *existing = NULL;
/*
- * $GIT_COMMON_DIR/HEAD is practically outside
- * $GIT_DIR so resolve_ref_unsafe() won't work (it
- * uses git_path). Parse the ref ourselves.
+ * $GIT_COMMON_DIR/$symref (e.g. HEAD) is practically outside
+ * $GIT_DIR so resolve_ref_unsafe() won't work (it uses
+ * git_path). Parse the ref ourselves.
*/
if (id)
- strbuf_addf(&path, "%s/worktrees/%s/HEAD", get_git_common_dir(), id);
+ strbuf_addf(&path, "%s/worktrees/%s/%s", get_git_common_dir(), id, symref);
else
- strbuf_addf(&path, "%s/HEAD", get_git_common_dir());
+ strbuf_addf(&path, "%s/%s", get_git_common_dir(), symref);
if (!strbuf_readlink(&sb, path.buf, 0)) {
if (!starts_with(sb.buf, "refs/") ||
@@ -346,33 +348,53 @@ static void check_linked_checkout(const char *branch, const char *id)
strbuf_rtrim(&gitdir);
} else
strbuf_addstr(&gitdir, get_git_common_dir());
- skip_prefix(branch, "refs/heads/", &branch);
strbuf_strip_suffix(&gitdir, ".git");
- die(_("'%s' is already checked out at '%s'"), branch, gitdir.buf);
+
+ existing = strbuf_detach(&gitdir, NULL);
done:
strbuf_release(&path);
strbuf_release(&sb);
strbuf_release(&gitdir);
+
+ return existing;
}
-void die_if_checked_out(const char *branch)
+char *find_shared_symref(const char *symref, const char *target)
{
struct strbuf path = STRBUF_INIT;
DIR *dir;
struct dirent *d;
+ char *existing;
- check_linked_checkout(branch, NULL);
+ if ((existing = find_linked_symref(symref, target, NULL)))
+ return existing;
strbuf_addf(&path, "%s/worktrees", get_git_common_dir());
dir = opendir(path.buf);
strbuf_release(&path);
if (!dir)
- return;
+ return NULL;
while ((d = readdir(dir)) != NULL) {
if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
continue;
- check_linked_checkout(branch, d->d_name);
+ existing = find_linked_symref(symref, target, d->d_name);
+ if (existing)
+ goto done;
}
+done:
closedir(dir);
+
+ return existing;
+}
+
+void die_if_checked_out(const char *branch)
+{
+ char *existing;
+
+ existing = find_shared_symref("HEAD", branch);
+ if (existing) {
+ skip_prefix(branch, "refs/heads/", &branch);
+ die(_("'%s' is already checked out at '%s'"), branch, existing);
+ }
}