worktree: don't store main worktree twice

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>

Patrick Steinhardt committed Jun 6, 2024 at 07:29 UTC 1339cb3c47aafb08a51d2517fcbaed2954d7d127
1 file changed +11 -18
worktree.c
+11 -18
@@ -53,6 +53,15 @@ static void add_head_info(struct worktree *wt)
53 wt->is_detached = 1;
54 }
55
56 +static int is_current_worktree(struct worktree *wt)
57 +{
58 + char *git_dir = absolute_pathdup(get_git_dir());
59 + const char *wt_git_dir = get_worktree_git_dir(wt);
60 + int is_current = !fspathcmp(git_dir, absolute_path(wt_git_dir));
61 + free(git_dir);
62 + return is_current;
63 +}
64 +
65 /**
66 * get the main worktree
67 */
@@ -76,6 +85,7 @@ static struct worktree *get_main_worktree(int skip_reading_head)
85 */
86 worktree->is_bare = (is_bare_repository_cfg == 1) ||
87 is_bare_repository();
88 + worktree->is_current = is_current_worktree(worktree);
89 if (!skip_reading_head)
90 add_head_info(worktree);
91 return worktree;
@@ -102,6 +112,7 @@ struct worktree *get_linked_worktree(const char *id,
112 worktree->repo = the_repository;
113 worktree->path = strbuf_detach(&worktree_path, NULL);
114 worktree->id = xstrdup(id);
115 + worktree->is_current = is_current_worktree(worktree);
116 if (!skip_reading_head)
117 add_head_info(worktree);
118
@@ -111,23 +122,6 @@ done:
122 return worktree;
123 }
124
114 -static void mark_current_worktree(struct worktree **worktrees)
115 -{
116 - char *git_dir = absolute_pathdup(get_git_dir());
117 - int i;
118 -
119 - for (i = 0; worktrees[i]; i++) {
120 - struct worktree *wt = worktrees[i];
121 - const char *wt_git_dir = get_worktree_git_dir(wt);
122 -
123 - if (!fspathcmp(git_dir, absolute_path(wt_git_dir))) {
124 - wt->is_current = 1;
125 - break;
126 - }
127 - }
128 - free(git_dir);
129 -}
130 -
125 /*
126 * NEEDSWORK: This function exists so that we can look up metadata of a
127 * 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)
158 ALLOC_GROW(list, counter + 1, alloc);
159 list[counter] = NULL;
160
167 - mark_current_worktree(list);
161 return list;
162 }
163