summaryrefslogtreecommitdiff
path: root/builtin
diff options
context:
space:
mode:
authorRubén Justo <rjusto@gmail.com>2023-03-27 00:33:02 +0200
committerJunio C Hamano <gitster@pobox.com>2023-03-27 09:40:14 -0700
commit2e8af499ff6e166a5f54f18cf3d1fa8f5d9bde38 (patch)
treeb0c12fdd47381043ee46c5e6e5b97d78b2094e96 /builtin
parent73876f4861cd3d187a4682290ab75c9dccadbc56 (diff)
downloadgit-2e8af499ff6e166a5f54f18cf3d1fa8f5d9bde38.tar.gz
branch: test for failures while renaming branches
When we introduced replace_each_worktree_head_symref() in 70999e9cec (branch -m: update all per-worktree HEADs, 2016-03-27), we implemented a best effort approach. If we are asked to rename a branch that is simultaneously checked out in multiple worktrees, we try to update all of those worktrees. If we fail updating any of them, we die() as a signal that something has gone wrong. However, at this point, the branch ref has already been renamed and also updated the HEADs of the successfully updated worktrees. Despite returning an error, we do not try to rollback those changes. Let's add a test to notice if we change this behavior in the future. In next commits we will change replace_each_worktree_head_symref() to work more closely with its only caller, copy_or_rename_branch(). Let's move the former closer to its caller, to facilitate those changes. Signed-off-by: Rubén Justo <rjusto@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'builtin')
-rw-r--r--builtin/branch.c32
1 files changed, 32 insertions, 0 deletions
diff --git a/builtin/branch.c b/builtin/branch.c
index f63fd45edb..c7ace2f2da 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -509,6 +509,38 @@ static void reject_rebase_or_bisect_branch(const char *target)
free_worktrees(worktrees);
}
+/*
+ * Update all per-worktree HEADs pointing at the old ref to point the new ref.
+ * This will be used when renaming a branch. Returns 0 if successful, non-zero
+ * otherwise.
+ */
+static int replace_each_worktree_head_symref(const char *oldref, const char *newref,
+ const char *logmsg)
+{
+ int ret = 0;
+ struct worktree **worktrees = get_worktrees();
+ int i;
+
+ for (i = 0; worktrees[i]; i++) {
+ struct ref_store *refs;
+
+ if (worktrees[i]->is_detached)
+ continue;
+ if (!worktrees[i]->head_ref)
+ continue;
+ if (strcmp(oldref, worktrees[i]->head_ref))
+ continue;
+
+ refs = get_worktree_ref_store(worktrees[i]);
+ if (refs_create_symref(refs, "HEAD", newref, logmsg))
+ ret = error(_("HEAD of working tree %s is not updated"),
+ worktrees[i]->path);
+ }
+
+ free_worktrees(worktrees);
+ return ret;
+}
+
static void copy_or_rename_branch(const char *oldname, const char *newname, int copy, int force)
{
struct strbuf oldref = STRBUF_INIT, newref = STRBUF_INIT, logmsg = STRBUF_INIT;