worktree.c: check whether branch is bisected in another worktree
[gitweb.git] / worktree.c
index dc092a710058d20f5343eddbdb960212cde17301..aab4b9552e429692943a2b49cd4c8b7379dab68b 100644 (file)
@@ -3,6 +3,7 @@
 #include "strbuf.h"
 #include "worktree.h"
 #include "dir.h"
+#include "wt-status.h"
 
 void free_worktrees(struct worktree **worktrees)
 {
@@ -215,6 +216,45 @@ 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)
+{
+       struct wt_status_state state;
+       int found_rebase;
+
+       memset(&state, 0, sizeof(state));
+       found_rebase = wt_status_check_rebase(wt, &state) &&
+               ((state.rebase_in_progress ||
+                 state.rebase_interactive_in_progress) &&
+                state.branch &&
+                starts_with(target, "refs/heads/") &&
+                !strcmp(state.branch, target + strlen("refs/heads/")));
+       free(state.branch);
+       free(state.onto);
+       return found_rebase;
+}
+
+static int is_worktree_being_bisected(const struct worktree *wt,
+                                     const char *target)
+{
+       struct wt_status_state state;
+       int found_rebase;
+
+       memset(&state, 0, sizeof(state));
+       found_rebase = wt_status_check_bisect(wt, &state) &&
+               state.branch &&
+               starts_with(target, "refs/heads/") &&
+               !strcmp(state.branch, target + strlen("refs/heads/"));
+       free(state.branch);
+       return found_rebase;
+}
+
+/*
+ * note: this function should be able to detect shared symref even if
+ * HEAD is temporarily detached (e.g. in the middle of rebase or
+ * bisect). New commands that do similar things should update this
+ * function as well.
+ */
 const struct worktree *find_shared_symref(const char *symref,
                                          const char *target)
 {
@@ -229,10 +269,23 @@ const struct worktree *find_shared_symref(const char *symref,
        worktrees = get_worktrees();
 
        for (i = 0; worktrees[i]; i++) {
+               struct worktree *wt = worktrees[i];
+
+               if (wt->is_detached && !strcmp(symref, "HEAD")) {
+                       if (is_worktree_being_rebased(wt, target)) {
+                               existing = wt;
+                               break;
+                       }
+                       if (is_worktree_being_bisected(wt, target)) {
+                               existing = wt;
+                               break;
+                       }
+               }
+
                strbuf_reset(&path);
                strbuf_reset(&sb);
                strbuf_addf(&path, "%s/%s",
-                           get_worktree_git_dir(worktrees[i]),
+                           get_worktree_git_dir(wt),
                            symref);
 
                if (parse_ref(path.buf, &sb, NULL)) {
@@ -240,7 +293,7 @@ const struct worktree *find_shared_symref(const char *symref,
                }
 
                if (!strcmp(sb.buf, target)) {
-                       existing = worktrees[i];
+                       existing = wt;
                        break;
                }
        }