branch: do not rename a branch under bisect or rebase
authorNguyễn Thái Ngọc Duy <pclouds@gmail.com>
Fri, 22 Apr 2016 13:01:36 +0000 (20:01 +0700)
committerJunio C Hamano <gitster@pobox.com>
Fri, 22 Apr 2016 21:09:39 +0000 (14:09 -0700)
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>
builtin/branch.c
t/t2025-worktree-add.sh
worktree.c
worktree.h
index bcde87d8e72d53f94f6d0e9caec6737dc2774f1a..b488c3fb3c7b1d51588057a44df784676c297537 100644 (file)
@@ -524,6 +524,29 @@ static void print_ref_list(struct ref_filter *filter, struct ref_sorting *sortin
        ref_array_clear(&array);
 }
 
+static void reject_rebase_or_bisect_branch(const char *target)
+{
+       struct worktree **worktrees = get_worktrees();
+       int i;
+
+       for (i = 0; worktrees[i]; i++) {
+               struct worktree *wt = worktrees[i];
+
+               if (!wt->is_detached)
+                       continue;
+
+               if (is_worktree_being_rebased(wt, target))
+                       die(_("Branch %s is being rebased at %s"),
+                           target, wt->path);
+
+               if (is_worktree_being_bisected(wt, target))
+                       die(_("Branch %s is being bisected at %s"),
+                           target, wt->path);
+       }
+
+       free_worktrees(worktrees);
+}
+
 static void rename_branch(const char *oldname, const char *newname, int force)
 {
        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)
 
        validate_new_branchname(newname, &newref, force, clobber_head_ok);
 
+       reject_rebase_or_bisect_branch(oldref.buf);
+
        strbuf_addf(&logmsg, "Branch: renamed %s to %s",
                 oldref.buf, newref.buf);
 
index 8f53944cb21e1d9e3097a8bb5c3aa6ee016a46f1..3a22fc55fc324fbfbfdcdf39fb71e829c89729b5 100755 (executable)
@@ -254,6 +254,10 @@ test_expect_success 'not allow to delete a branch under rebase' '
        )
 '
 
+test_expect_success 'rename a branch under rebase not allowed' '
+       test_must_fail git branch -M under-rebase rebase-with-new-name
+'
+
 test_expect_success 'check out from current worktree branch ok' '
        (
                cd under-rebase &&
@@ -276,4 +280,8 @@ test_expect_success 'checkout a branch under bisect' '
        )
 '
 
+test_expect_success 'rename a branch under bisect not allowed' '
+       test_must_fail git branch -M under-bisect bisect-with-new-name
+'
+
 test_done
index aab4b9552e429692943a2b49cd4c8b7379dab68b..4817d600556e444f9b22551a4f59a8dadcf258f2 100644 (file)
@@ -216,8 +216,8 @@ const char *get_worktree_git_dir(const struct worktree *wt)
                return git_common_path("worktrees/%s", wt->id);
 }
 
-static int is_worktree_being_rebased(const struct worktree *wt,
-                                    const char *target)
+int is_worktree_being_rebased(const struct worktree *wt,
+                             const char *target)
 {
        struct wt_status_state state;
        int found_rebase;
@@ -234,8 +234,8 @@ static int is_worktree_being_rebased(const struct worktree *wt,
        return found_rebase;
 }
 
-static int is_worktree_being_bisected(const struct worktree *wt,
-                                     const char *target)
+int is_worktree_being_bisected(const struct worktree *wt,
+                              const char *target)
 {
        struct wt_status_state state;
        int found_rebase;
index 0da8c1f2bdf0c7037a3ee82d2a913efbf546b5c2..13949093cc1610fcafbefb22d1f8b9441fbd4ade 100644 (file)
@@ -42,6 +42,9 @@ extern void free_worktrees(struct worktree **);
 extern const struct worktree *find_shared_symref(const char *symref,
                                                 const char *target);
 
+int is_worktree_being_rebased(const struct worktree *wt, const char *target);
+int is_worktree_being_bisected(const struct worktree *wt, const char *target);
+
 /*
  * Similar to git_path() but can produce paths for a specified
  * worktree instead of current one