branch: do not rename a branch under bisect or rebase

The branch name in that case could be saved in rebase's head_name or bisect's BISECT_START files. Ideally we should try to update them as well. But it's trickier (*). Let's play safe and see if the user complains about inconveniences before doing that. (*) If we do it, bisect and rebase need to provide an API to rename branches. We can't do it in worktree.c or builtin/branch.c because when other people change rebase/bisect code, they may not be aware of this code and accidentally break it (e.g. rename the branch file, or refer to the branch in new files). It's a lot more work. Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Nguyễn Thái Ngọc Duy committed Apr 22, 2016 at 20:01 UTC 14ace5b77b493506a1f8ffde96a2f49cc7bc4db0
4 files changed +40 -4
builtin/branch.c
+25
@@ -524,6 +524,29 @@ static void print_ref_list(struct ref_filter *filter, struct ref_sorting *sortin
524 ref_array_clear(&array);
525 }
526
527 +static void reject_rebase_or_bisect_branch(const char *target)
528 +{
529 + struct worktree **worktrees = get_worktrees();
530 + int i;
531 +
532 + for (i = 0; worktrees[i]; i++) {
533 + struct worktree *wt = worktrees[i];
534 +
535 + if (!wt->is_detached)
536 + continue;
537 +
538 + if (is_worktree_being_rebased(wt, target))
539 + die(_("Branch %s is being rebased at %s"),
540 + target, wt->path);
541 +
542 + if (is_worktree_being_bisected(wt, target))
543 + die(_("Branch %s is being bisected at %s"),
544 + target, wt->path);
545 + }
546 +
547 + free_worktrees(worktrees);
548 +}
549 +
550 static void rename_branch(const char *oldname, const char *newname, int force)
551 {
552 struct strbuf oldref = STRBUF_INIT, newref = STRBUF_INIT, logmsg = STRBUF_INIT;
@@ -553,6 +576,8 @@ static void rename_branch(const char *oldname, const char *newname, int force)
576
577 validate_new_branchname(newname, &newref, force, clobber_head_ok);
578
579 + reject_rebase_or_bisect_branch(oldref.buf);
580 +
581 strbuf_addf(&logmsg, "Branch: renamed %s to %s",
582 oldref.buf, newref.buf);
583
t/t2025-worktree-add.sh
+8
@@ -254,6 +254,10 @@ test_expect_success 'not allow to delete a branch under rebase' '
254 )
255 '
256
257 +test_expect_success 'rename a branch under rebase not allowed' '
258 + test_must_fail git branch -M under-rebase rebase-with-new-name
259 +'
260 +
261 test_expect_success 'check out from current worktree branch ok' '
262 (
263 cd under-rebase &&
@@ -276,4 +280,8 @@ test_expect_success 'checkout a branch under bisect' '
280 )
281 '
282
283 +test_expect_success 'rename a branch under bisect not allowed' '
284 + test_must_fail git branch -M under-bisect bisect-with-new-name
285 +'
286 +
287 test_done
worktree.c
+4 -4
@@ -216,8 +216,8 @@ const char *get_worktree_git_dir(const struct worktree *wt)
216 return git_common_path("worktrees/%s", wt->id);
217 }
218
219 -static int is_worktree_being_rebased(const struct worktree *wt,
220 - const char *target)
219 +int is_worktree_being_rebased(const struct worktree *wt,
220 + const char *target)
221 {
222 struct wt_status_state state;
223 int found_rebase;
@@ -234,8 +234,8 @@ static int is_worktree_being_rebased(const struct worktree *wt,
234 return found_rebase;
235 }
236
237 -static int is_worktree_being_bisected(const struct worktree *wt,
238 - const char *target)
237 +int is_worktree_being_bisected(const struct worktree *wt,
238 + const char *target)
239 {
240 struct wt_status_state state;
241 int found_rebase;
worktree.h
+3
@@ -42,6 +42,9 @@ extern void free_worktrees(struct worktree **);
42 extern const struct worktree *find_shared_symref(const char *symref,
43 const char *target);
44
45 +int is_worktree_being_rebased(const struct worktree *wt, const char *target);
46 +int is_worktree_being_bisected(const struct worktree *wt, const char *target);
47 +
48 /*
49 * Similar to git_path() but can produce paths for a specified
50 * worktree instead of current one