Web lists-archives.com

Re: [RFC PATCH 3/4] Add alias option to git branch




From 9f9b9010cb0b8c2874428d2f4bd21f06f747bfee Mon Sep 17 00:00:00 2001
From: Kenneth Cochran <kenneth.cochran101@xxxxxxxxx>
Date: Sun, 3 Mar 2019 15:34:20 -0600
Subject: [RFC PATCH 3/4] worktree: symref should be found anywhere in chain
Cc: Sahil Dua <sahildua2305@xxxxxxxxx>,
    Duy Nguyen <pclouds@xxxxxxxxx>,
    Jeff King <peff@xxxxxxxx>

Currently, when searching for a shared symref, a symref chain is
fully dereferenced before checking the name. This poses problems for
`git branch -d` which will happily delete a checked out symref.

The existing behaviour (recognizing a non-symbolic ref by the same name)
still exists, but it will now also find any symref that is in between the
starting symref and the first non-symbolic ref.

Concretely, for the following chain
HEAD -> symref1 -> symref2 -> master
previously the function was only able to find master.
With these changes applied, it will be able to find any of the above references.

Signed-off-by: Kenneth Cochran <kenneth.cochran101@xxxxxxxxx>
---
 t/t3207-branch-alias.sh | 13 +++++++++++++
 worktree.c              | 18 ++++++++++++------
 2 files changed, 25 insertions(+), 6 deletions(-)

diff --git a/t/t3207-branch-alias.sh b/t/t3207-branch-alias.sh
index 9d4c8c2914..c1edeed4eb 100755
--- a/t/t3207-branch-alias.sh
+++ b/t/t3207-branch-alias.sh
@@ -55,4 +55,17 @@ test_expect_success 'git branch --alias refuses to overwrite existing symref' '
 	test_must_fail git branch --alias syme
 '
 
+test_expect_success 'git branch -d refuses to delete a checked out symref' '
+	git branch --alias symd &&
+	git checkout symd &&
+	test_must_fail git branch -d symd
+'
+
+test_expect_success 'git branch -d refuses to delete an indirectly checked out symref' '
+	git symbolic-ref refs/heads/symd2 refs/heads/symd &&
+	git checkout symd2 &&
+	test_must_fail git branch -d symd2 &&
+	test_must_fail git branch -d symd
+'
+
 test_done
diff --git a/worktree.c b/worktree.c
index d6a0ee7f73..b58325c6c1 100644
--- a/worktree.c
+++ b/worktree.c
@@ -387,6 +387,17 @@ int is_worktree_being_bisected(const struct worktree *wt,
 	return found_rebase;
 }
 
+static int find_symref_by_name(const char *ref_name, const struct object_id *oid,
+			       int flags, void *cb_data)
+{
+	const char *target = (const char *)cb_data;
+
+	if ((flags & REF_ISSYMREF) && !strcmp(target, ref_name))
+		return 1;
+	else
+		return 0;
+}
+
 /*
  * note: this function should be able to detect shared symref even if
  * HEAD is temporarily detached (e.g. in the middle of rebase or
@@ -406,9 +417,7 @@ const struct worktree *find_shared_symref(const char *symref,
 
 	for (i = 0; worktrees[i]; i++) {
 		struct worktree *wt = worktrees[i];
-		const char *symref_target;
 		struct ref_store *refs;
-		int flags;
 
 		if (wt->is_bare)
 			continue;
@@ -425,10 +434,7 @@ const struct worktree *find_shared_symref(const char *symref,
 		}
 
 		refs = get_worktree_ref_store(wt);
-		symref_target = refs_resolve_ref_unsafe(refs, symref, 0,
-							NULL, &flags);
-		if ((flags & REF_ISSYMREF) &&
-		    symref_target && !strcmp(symref_target, target)) {
+		if(refs_for_each_ref_in_chain(refs, find_symref_by_name, (void *)target, symref)) {
 			existing = wt;
 			break;
 		}
-- 
2.17.1