Re: [PATCH v4 3/4] refs: parse and use the reference storage payload
From: Karthik Nayak <hidden>
Date: 2026-02-09 12:52:05
Patrick Steinhardt [off-list ref] writes:
On Mon, Feb 02, 2026 at 01:26:32PM +0100, Karthik Nayak wrote:quoted
The previous commit extended the 'extensions.refStorage' config to add support for a reference storage payload. The payload provides backend specific information on where to store references for a given directory. Propagate this information to individual backends when initializing them via the 'init()' function. Both the files and reftable backends will parse the information to be filesystem paths to store references. To enable this, provide a 'refs_compute_filesystem_location()' function which will parse the current 'gitdir' and the 'payload' to provide the final reference directory and common reference directory (if working in a linked worktree). Finally, for linked worktrees, traditionally references were stored in the '$GIT_DIR/worktrees/<wt_id>' path. But when using an alternate reference storage path, it doesn't make sense to store main worktree references in the new path, and linked worktree references in the $GIT_DIR path. So, let's store linked worktree references in '$ALTERNATE_REFERENCE_DIR/worktrees/<wt_id'. To do this, create thes/wt_id/&>/
Thanks!
quoted
diff --git a/Documentation/config/extensions.adoc b/Documentation/config/extensions.adoc index 532456644b..df86da6aa7 100644 --- a/Documentation/config/extensions.adoc +++ b/Documentation/config/extensions.adoc@@ -57,10 +57,24 @@ For historical reasons, this extension is respected regardless of the `core.repositoryFormatVersion` setting. refStorage::: - Specify the ref storage format to use. The acceptable values are: + Specify the ref storage format and location to use. The value can be + either a format name or a URI: + -- +* A format name alone (e.g., `reftable` or `files`) uses the default + location (the repository's common directory). + +* A URI format `<format>://<location>` explicitly specifies both theI think I mentioned this before, but shouldn't we say payload instead of location here? It may not be a location for all backends.
Yeah, you did. I missed this entirely somehow. Will re-do this.
quoted
diff --git a/builtin/worktree.c b/builtin/worktree.c index fbdaf2eb2e..800a376ac5 100644 --- a/builtin/worktree.c +++ b/builtin/worktree.c@@ -425,6 +425,40 @@ static int make_worktree_orphan(const char * ref, const struct add_opts *opts, return run_command(&cp); } +/* + * References for worktress are generally stored in '$GIT_DIR/worktrees/<wt_id>'. + * But when using alternate reference directories, we want to store the worktree + * references in '$ALTERNATE_REFERENCE_DIR/worktrees/<wt_id>'. + * + * Create the necessary folder structure to facilitate the same. But to ensure + * that the former path is still considered a Git directory, add stubs (similar + * to how we do in the reftable backend). + */I think the last part in the braces isn't necessary to say anymore given that we simply shell out to a function now.
Yeah, will remove.
quoted
diff --git a/refs.c b/refs.c index 32b4edaf2d..c1d69082a9 100644 --- a/refs.c +++ b/refs.c@@ -2224,7 +2225,11 @@ static struct ref_store *ref_store_init(struct repository *repo, if (!be) BUG("reference backend is unknown"); - refs = be->init(repo, gitdir, flags); + /* + * TODO Send in a 'struct worktree' instead of a 'gitdir', and + * allow the backend to handle how it wants to deal with worktrees. + */It would be nice if the commit message mentioned why this isn't done now already.
Will do!
quoted
diff --git a/refs/files-backend.c b/refs/files-backend.c index 240d3c3b26..160ecb53b7 100644 --- a/refs/files-backend.c +++ b/refs/files-backend.c@@ -106,19 +106,24 @@ static void clear_loose_ref_cache(struct files_ref_store *refs) * set of caches. */ static struct ref_store *files_ref_store_init(struct repository *repo, + const char *payload, const char *gitdir, unsigned int flags) { struct files_ref_store *refs = xcalloc(1, sizeof(*refs)); struct ref_store *ref_store = (struct ref_store *)refs; - struct strbuf sb = STRBUF_INIT; + struct strbuf ref_common_dir = STRBUF_INIT; + struct strbuf refdir = STRBUF_INIT; + bool is_worktree; + + refs_compute_filesystem_location(gitdir, payload, &is_worktree, &refdir, + &ref_common_dir); - base_ref_store_init(ref_store, repo, gitdir, &refs_be_files); + base_ref_store_init(ref_store, repo, refdir.buf, &refs_be_files); refs->store_flags = flags; - get_common_dir_noenv(&sb, gitdir); - refs->gitcommondir = strbuf_detach(&sb, NULL); + refs->gitcommondir = xstrdup(ref_common_dir.buf);We can use `strbuf_detach()` instead to save an allocation and then use `refs->gitcommondir` below.
That's a good suggestion.
quoted
refs->packed_ref_store = - packed_ref_store_init(repo, refs->gitcommondir, flags); + packed_ref_store_init(repo, payload, ref_common_dir.buf, flags); refs->log_all_ref_updates = repo_settings_get_log_all_ref_updates(repo); repo_config_get_bool(repo, "core.prefersymlinkrefs", &refs->prefer_symlink_refs);Patrick
Thanks!
Attachments
- signature.asc [application/pgp-signature] 690 bytes