]> git.ipfire.org Git - thirdparty/git.git/commitdiff
worktree: don't store main worktree twice
authorPatrick Steinhardt <ps@pks.im>
Thu, 6 Jun 2024 05:29:34 +0000 (07:29 +0200)
committerJunio C Hamano <gitster@pobox.com>
Thu, 6 Jun 2024 16:04:33 +0000 (09:04 -0700)
In `get_worktree_ref_store()` we either return the repository's main ref
store, or we look up the ref store via the map of worktree ref stores.
Which of these worktrees gets picked depends on the `is_current` bit of
the worktree, which indicates whether the worktree is the one that
corresponds to `the_repository`.

The bit is getting set in `get_worktrees()`, but only after we have
computed the list of all worktrees. This is too late though, because at
that time we have already called `get_worktree_ref_store()` on each of
the worktrees via `add_head_info()`. The consequence is that the current
worktree will not have been marked accordingly, which means that we did
not use the main ref store, but instead created a new ref store. We thus
have two separate ref stores now that map to the same ref database.

Fix this by setting `is_current` before we call `add_head_info()`.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
worktree.c

index 12eadacc618a1db5e734bea16a5fb7ae15085131..70844d023a2f796c452188a60e7404ee48298d64 100644 (file)
@@ -53,6 +53,15 @@ static void add_head_info(struct worktree *wt)
                wt->is_detached = 1;
 }
 
+static int is_current_worktree(struct worktree *wt)
+{
+       char *git_dir = absolute_pathdup(get_git_dir());
+       const char *wt_git_dir = get_worktree_git_dir(wt);
+       int is_current = !fspathcmp(git_dir, absolute_path(wt_git_dir));
+       free(git_dir);
+       return is_current;
+}
+
 /**
  * get the main worktree
  */
@@ -76,6 +85,7 @@ static struct worktree *get_main_worktree(int skip_reading_head)
         */
        worktree->is_bare = (is_bare_repository_cfg == 1) ||
                is_bare_repository();
+       worktree->is_current = is_current_worktree(worktree);
        if (!skip_reading_head)
                add_head_info(worktree);
        return worktree;
@@ -102,6 +112,7 @@ struct worktree *get_linked_worktree(const char *id,
        worktree->repo = the_repository;
        worktree->path = strbuf_detach(&worktree_path, NULL);
        worktree->id = xstrdup(id);
+       worktree->is_current = is_current_worktree(worktree);
        if (!skip_reading_head)
                add_head_info(worktree);
 
@@ -111,23 +122,6 @@ done:
        return worktree;
 }
 
-static void mark_current_worktree(struct worktree **worktrees)
-{
-       char *git_dir = absolute_pathdup(get_git_dir());
-       int i;
-
-       for (i = 0; worktrees[i]; i++) {
-               struct worktree *wt = worktrees[i];
-               const char *wt_git_dir = get_worktree_git_dir(wt);
-
-               if (!fspathcmp(git_dir, absolute_path(wt_git_dir))) {
-                       wt->is_current = 1;
-                       break;
-               }
-       }
-       free(git_dir);
-}
-
 /*
  * NEEDSWORK: This function exists so that we can look up metadata of a
  * worktree without trying to access any of its internals like the refdb. It
@@ -164,7 +158,6 @@ static struct worktree **get_worktrees_internal(int skip_reading_head)
        ALLOC_GROW(list, counter + 1, alloc);
        list[counter] = NULL;
 
-       mark_current_worktree(list);
        return list;
 }