git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v4 1/2] worktrees: add find_shared_symref

From
David Turner <dturner@twopensource.com>
Date
Jul 31, 2015, 22:11 UTC
Message-ID
<1438380669-11012-1-git-send-email-dturner@twopensource.com>

Add a new function, find_shared_symref, which contains the heart of die_if_checked_out, but works for all symrefs. 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>
---

This version includes Junio's suggested comment fix, and Eric's suggestions for error message improvements.

---
 branch.c | 39 ++++++++++++++++++++++++++++-----------
 branch.h |  8 ++++++++
 2 files changed, 36 insertions(+), 11 deletions(-)
diff --git a/branch.c b/branch.c
index c85be07..9b5e3b3 100644
--- a/branch.c
+++ b/branch.c
@@ -311,21 +311,22 @@ 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;
 
 	/*
-	 * $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/") ||
@@ -349,31 +350,47 @@ static void check_linked_checkout(const char *branch, const char *id)
 		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);
+	return strbuf_detach(&gitdir, NULL);
 done:
 	strbuf_release(&path);
 	strbuf_release(&sb);
 	strbuf_release(&gitdir);
+
+	return NULL;
 }
 
-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);
+		if ((existing = find_linked_symref(symref, target, d->d_name)))
+			return existing;
 	}
 	closedir(dir);
+
+	return NULL;
+}
+
+void die_if_checked_out(const char *branch)
+{
+	char *existing;
+
+	existing = find_shared_symref("HEAD", branch);
+	if (existing)
+		die(_("'%s' is already checked out at '%s'"), branch, existing);
 }
diff --git a/branch.h b/branch.h
index 58aa45f..0f466c7 100644
--- a/branch.h
+++ b/branch.h
@@ -59,4 +59,12 @@ extern int read_branch_desc(struct strbuf *, const char *branch_name);
  */
 extern void die_if_checked_out(const char *branch);
 
+/*
+ * Check if a per-worktree symref points to a ref in the main worktree
+ * or any linked worktree, and return the path to the exising worktree
+ * if it is.  Returns NULL if there is no existing ref.  The caller is
+ * responsible for freeing the returned path.
+ */
+extern char *find_shared_symref(const char *symref, const char *branch);
+
 #endif
-- 
2.0.4.315.gad8727a-twtrsrc
Next: David Turner
Message 1 of 5 in “worktrees: add find_shared_symref”
  1. 1/2 worktrees: add find_shared_symrefDavid Turner, Jul 31, 2015
  2. 2/2 notes: handle multiple worktreesDavid Turner, Jul 31, 2015
  3. Johan HerlandAug 1, 2015
  4. David TurnerAug 3, 2015
  5. Eric SunshineJul 31, 2015

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.