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

[PATCH 06/16] branch: publish die_if_checked_out()

From
Eric Sunshine <sunshine@sunshineco.com>
Date
Jul 11, 2015, 00:05 UTC
Message-ID
<1436573146-3893-7-git-send-email-sunshine@sunshineco.com>
In-Reply-To
<1436573146-3893-1-git-send-email-sunshine@sunshineco.com>

git-worktree will eventually be retrofitted to populate the new worktree via "git reset --hard" rather than "git checkout", at which time it will need to be able to detect if the branch is already checked out elsewhere, rather than relying upon git-branch to make this determination, so publish die_if_checked_out().

Signed-off-by: Eric Sunshine <sunshine@sunshineco.com>
---
 branch.c           | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 branch.h           |  7 ++++++
 builtin/checkout.c | 65 ------------------------------------------------------
 3 files changed, 72 insertions(+), 65 deletions(-)
diff --git a/branch.c b/branch.c
index 4bab55a..7b8b9a3 100644
--- a/branch.c
+++ b/branch.c
@@ -309,3 +309,68 @@ void remove_branch_state(void)
 	unlink(git_path("MERGE_MODE"));
 	unlink(git_path("SQUASH_MSG"));
 }
+
+static void check_linked_checkout(const char *branch, const char *id)
+{
+	struct strbuf sb = STRBUF_INIT;
+	struct strbuf path = STRBUF_INIT;
+	struct strbuf gitdir = STRBUF_INIT;
+	const char *start, *end;
+
+	if (id)
+		strbuf_addf(&path, "%s/worktrees/%s/HEAD", get_git_common_dir(), id);
+	else
+		strbuf_addf(&path, "%s/HEAD", get_git_common_dir());
+
+	if (strbuf_read_file(&sb, path.buf, 0) < 0 ||
+	    !skip_prefix(sb.buf, "ref:", &start))
+		goto done;
+	while (isspace(*start))
+		start++;
+	end = start;
+	while (*end && !isspace(*end))
+		end++;
+	if (strncmp(start, branch, end - start) || branch[end - start] != '\0')
+		goto done;
+	if (id) {
+		strbuf_reset(&path);
+		strbuf_addf(&path, "%s/worktrees/%s/gitdir", get_git_common_dir(), id);
+		if (strbuf_read_file(&gitdir, path.buf, 0) <= 0)
+			goto done;
+		strbuf_rtrim(&gitdir);
+	} else
+		strbuf_addstr(&gitdir, get_git_common_dir());
+	skip_prefix(branch, "refs/heads/", &branch);
+	die(_("'%s' is already checked out at '%s'"), branch, gitdir.buf);
+done:
+	strbuf_release(&path);
+	strbuf_release(&sb);
+	strbuf_release(&gitdir);
+}
+
+void die_if_checked_out(const char *branch)
+{
+	struct strbuf path = STRBUF_INIT;
+	DIR *dir;
+	struct dirent *d;
+
+	/*
+	 * $GIT_COMMON_DIR/HEAD is practically outside
+	 * $GIT_DIR so resolve_ref_unsafe() won't work (it
+	 * uses git_path). Parse the ref ourselves.
+	 */
+	check_linked_checkout(branch, NULL);
+
+	strbuf_addf(&path, "%s/worktrees", get_git_common_dir());
+	dir = opendir(path.buf);
+	strbuf_release(&path);
+	if (!dir)
+		return;
+
+	while ((d = readdir(dir)) != NULL) {
+		if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
+			continue;
+		check_linked_checkout(branch, d->d_name);
+	}
+	closedir(dir);
+}
diff --git a/branch.h b/branch.h
index 64173ab..58aa45f 100644
--- a/branch.h
+++ b/branch.h
@@ -52,4 +52,11 @@ extern void install_branch_config(int flag, const char *local, const char *origi
  */
 extern int read_branch_desc(struct strbuf *, const char *branch_name);
 
+/*
+ * Check if a branch is checked out in the main worktree or any linked
+ * worktree and die (with a message describing its checkout location) if
+ * it is.
+ */
+extern void die_if_checked_out(const char *branch);
+
 #endif
diff --git a/builtin/checkout.c b/builtin/checkout.c
index 673daa0..4ae895c 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -873,71 +873,6 @@ static const char *unique_tracking_name(const char *name, unsigned char *sha1)
 	return NULL;
 }
 
-static void check_linked_checkout(const char *branch, const char *id)
-{
-	struct strbuf sb = STRBUF_INIT;
-	struct strbuf path = STRBUF_INIT;
-	struct strbuf gitdir = STRBUF_INIT;
-	const char *start, *end;
-
-	if (id)
-		strbuf_addf(&path, "%s/worktrees/%s/HEAD", get_git_common_dir(), id);
-	else
-		strbuf_addf(&path, "%s/HEAD", get_git_common_dir());
-
-	if (strbuf_read_file(&sb, path.buf, 0) < 0 ||
-	    !skip_prefix(sb.buf, "ref:", &start))
-		goto done;
-	while (isspace(*start))
-		start++;
-	end = start;
-	while (*end && !isspace(*end))
-		end++;
-	if (strncmp(start, branch, end - start) || branch[end - start] != '\0')
-		goto done;
-	if (id) {
-		strbuf_reset(&path);
-		strbuf_addf(&path, "%s/worktrees/%s/gitdir", get_git_common_dir(), id);
-		if (strbuf_read_file(&gitdir, path.buf, 0) <= 0)
-			goto done;
-		strbuf_rtrim(&gitdir);
-	} else
-		strbuf_addstr(&gitdir, get_git_common_dir());
-	skip_prefix(branch, "refs/heads/", &branch);
-	die(_("'%s' is already checked out at '%s'"), branch, gitdir.buf);
-done:
-	strbuf_release(&path);
-	strbuf_release(&sb);
-	strbuf_release(&gitdir);
-}
-
-static void die_if_checked_out(const char *branch)
-{
-	struct strbuf path = STRBUF_INIT;
-	DIR *dir;
-	struct dirent *d;
-
-	/*
-	 * $GIT_COMMON_DIR/HEAD is practically outside
-	 * $GIT_DIR so resolve_ref_unsafe() won't work (it
-	 * uses git_path). Parse the ref ourselves.
-	 */
-	check_linked_checkout(branch, NULL);
-
-	strbuf_addf(&path, "%s/worktrees", get_git_common_dir());
-	dir = opendir(path.buf);
-	strbuf_release(&path);
-	if (!dir)
-		return;
-
-	while ((d = readdir(dir)) != NULL) {
-		if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
-			continue;
-		check_linked_checkout(branch, d->d_name);
-	}
-	closedir(dir);
-}
-
 static int parse_branchname_arg(int argc, const char **argv,
 				int dwim_new_local_branch_ok,
 				struct branch_info *new,
-- 
2.5.0.rc1.201.ga12d9f8
Previous: Eric SunshineNext: Eric Sunshine
Message 7 of 31 in “worktree: use "git reset --hard" to populate worktree”
  1. 00/16 worktree: use "git reset --hard" to populate worktreeEric Sunshine, Jul 11, 2015
  2. 01/16 checkout: avoid resolving HEAD unnecessarilyEric Sunshine, Jul 11, 2015
  3. 02/16 checkout: name check_linked_checkouts() more meaningfullyEric Sunshine, Jul 11, 2015
  4. 03/16 checkout: improve die_if_checked_out() robustnessEric Sunshine, Jul 11, 2015
  5. 04/16 checkout: die_if_checked_out: simplify strbuf managementEric Sunshine, Jul 11, 2015
  6. 05/16 checkout: generalize die_if_checked_out() branch name argumentEric Sunshine, Jul 11, 2015
  7. 06/16 branch: publish die_if_checked_out()Eric Sunshine, Jul 11, 2015
  8. 07/16 worktree: simplify new branch (-b/-B) option checkingEric Sunshine, Jul 11, 2015
  9. 08/16 worktree: introduce options containerEric Sunshine, Jul 11, 2015
  10. 09/16 worktree: make --detach mutually exclusive with -b/-BEric Sunshine, Jul 11, 2015
  11. 10/16 worktree: make branch creation distinct from worktree populationEric Sunshine, Jul 11, 2015
  12. Duy NguyenJul 12, 2015
  13. Eric SunshineJul 12, 2015
  14. Duy NguyenJul 12, 2015
  15. Eric SunshineJul 12, 2015
  16. Eric SunshineJul 12, 2015
  17. Eric SunshineJul 12, 2015
  18. Duy NguyenJul 12, 2015
  19. 11/16 worktree: add_worktree: construct worktree-population command locallyEric Sunshine, Jul 11, 2015
  20. 12/16 worktree: detect branch symref/detach and error conditions locallyEric Sunshine, Jul 11, 2015
  21. 13/16 worktree: make setup of new HEAD distinct from worktree populationEric Sunshine, Jul 11, 2015
  22. 14/16 worktree: avoid resolving HEAD unnecessarilyEric Sunshine, Jul 11, 2015
  23. 15/16 worktree: populate via "git reset --hard" rather than "git checkout"Eric Sunshine, Jul 11, 2015
  24. 16/16 checkout: drop intimate knowledge of new worktree initial populationEric Sunshine, Jul 11, 2015
  25. Junio C HamanoJul 13, 2015
  26. Michael J GruberJul 14, 2015
  27. Duy NguyenJul 14, 2015
  28. Eric SunshineJul 14, 2015
  29. Eric SunshineJul 15, 2015
  30. Duy NguyenJul 15, 2015
  31. Eric SunshineJul 12, 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.