refs/reftable: extract function to retrieve backend for worktree

Pull out the logic to retrieve a backend for a given worktree. This function will be used in a subsequent commit. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Patrick Steinhardt committed Jan 12, 2026 at 10:03 UTC 78384e2467c4e457f230e731f26409fa7dd72434
1 file changed +43 -27
refs/reftable-backend.c
+43 -27
@@ -172,6 +172,37 @@ static struct reftable_ref_store *reftable_be_downcast(struct ref_store *ref_sto
172 return refs;
173 }
174
175 +static int backend_for_worktree(struct reftable_backend **out,
176 + struct reftable_ref_store *store,
177 + const char *worktree_name)
178 +{
179 + struct strbuf worktree_dir = STRBUF_INIT;
180 + int ret;
181 +
182 + *out = strmap_get(&store->worktree_backends, worktree_name);
183 + if (*out) {
184 + ret = 0;
185 + goto out;
186 + }
187 +
188 + strbuf_addf(&worktree_dir, "%s/worktrees/%s/reftable",
189 + store->base.repo->commondir, worktree_name);
190 +
191 + CALLOC_ARRAY(*out, 1);
192 + store->err = ret = reftable_backend_init(*out, worktree_dir.buf,
193 + &store->write_options);
194 + if (ret < 0) {
195 + free(*out);
196 + goto out;
197 + }
198 +
199 + strmap_put(&store->worktree_backends, worktree_name, *out);
200 +
201 +out:
202 + strbuf_release(&worktree_dir);
203 + return ret;
204 +}
205 +
206 /*
207 * Some refs are global to the repository (refs/heads/{*}), while others are
208 * local to the worktree (eg. HEAD, refs/bisect/{*}). We solve this by having
@@ -191,19 +222,19 @@ static int backend_for(struct reftable_backend **out,
222 const char **rewritten_ref,
223 int reload)
224 {
194 - struct reftable_backend *be;
225 const char *wtname;
226 int wtname_len;
227 + int ret;
228
229 if (!refname) {
199 - be = &store->main_backend;
230 + *out = &store->main_backend;
231 + ret = 0;
232 goto out;
233 }
234
235 switch (parse_worktree_ref(refname, &wtname, &wtname_len, rewritten_ref)) {
236 case REF_WORKTREE_OTHER: {
237 static struct strbuf wtname_buf = STRBUF_INIT;
206 - struct strbuf wt_dir = STRBUF_INIT;
238
239 /*
240 * We're using a static buffer here so that we don't need to
@@ -223,20 +254,8 @@ static int backend_for(struct reftable_backend **out,
254 * already and error out when trying to write a reference via
255 * both stacks.
256 */
226 - be = strmap_get(&store->worktree_backends, wtname_buf.buf);
227 - if (!be) {
228 - strbuf_addf(&wt_dir, "%s/worktrees/%s/reftable",
229 - store->base.repo->commondir, wtname_buf.buf);
257 + ret = backend_for_worktree(out, store, wtname_buf.buf);
258
231 - CALLOC_ARRAY(be, 1);
232 - store->err = reftable_backend_init(be, wt_dir.buf,
233 - &store->write_options);
234 - assert(store->err != REFTABLE_API_ERROR);
235 -
236 - strmap_put(&store->worktree_backends, wtname_buf.buf, be);
237 - }
238 -
239 - strbuf_release(&wt_dir);
259 goto out;
260 }
261 case REF_WORKTREE_CURRENT:
@@ -245,27 +264,24 @@ static int backend_for(struct reftable_backend **out,
264 * main worktree. We thus return the main stack in that case.
265 */
266 if (!store->worktree_backend.stack)
248 - be = &store->main_backend;
267 + *out = &store->main_backend;
268 else
250 - be = &store->worktree_backend;
269 + *out = &store->worktree_backend;
270 + ret = 0;
271 goto out;
272 case REF_WORKTREE_MAIN:
273 case REF_WORKTREE_SHARED:
254 - be = &store->main_backend;
274 + *out = &store->main_backend;
275 + ret = 0;
276 goto out;
277 default:
278 BUG("unhandled worktree reference type");
279 }
280
281 out:
261 - if (reload) {
262 - int ret = reftable_stack_reload(be->stack);
263 - if (ret)
264 - return ret;
265 - }
266 - *out = be;
267 -
268 - return 0;
282 + if (reload && !ret)
283 + ret = reftable_stack_reload((*out)->stack);
284 + return ret;
285 }
286
287 static int should_write_log(struct reftable_ref_store *refs, const char *refname)