Thread (108 messages) 108 messages, 8 authors, 2026-02-25

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 the
s/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 the
I 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

Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help