summaryrefslogtreecommitdiff
path: root/branch.c
diff options
context:
space:
mode:
Diffstat (limited to 'branch.c')
-rw-r--r--branch.c65
1 files changed, 44 insertions, 21 deletions
diff --git a/branch.c b/branch.c
index af9480f..d013374 100644
--- a/branch.c
+++ b/branch.c
@@ -284,8 +284,9 @@ void create_branch(const char *head,
transaction = ref_transaction_begin(&err);
if (!transaction ||
- ref_transaction_update(transaction, ref.buf, sha1,
- null_sha1, 0, !forcing, msg, &err) ||
+ ref_transaction_update(transaction, ref.buf,
+ sha1, forcing ? NULL : null_sha1,
+ 0, msg, &err) ||
ref_transaction_commit(transaction, &err))
die("%s", err.buf);
ref_transaction_free(transaction);
@@ -301,30 +302,32 @@ void create_branch(const char *head,
void remove_branch_state(void)
{
- unlink(git_path("CHERRY_PICK_HEAD"));
- unlink(git_path("REVERT_HEAD"));
- unlink(git_path("MERGE_HEAD"));
- unlink(git_path("MERGE_RR"));
- unlink(git_path("MERGE_MSG"));
- unlink(git_path("MERGE_MODE"));
- unlink(git_path("SQUASH_MSG"));
+ unlink(git_path_cherry_pick_head());
+ unlink(git_path_revert_head());
+ unlink(git_path_merge_head());
+ unlink(git_path_merge_rr());
+ unlink(git_path_merge_msg());
+ unlink(git_path_merge_mode());
+ 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 +349,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);
+ }
}