[PATCH v2 0/8] Refactor handling of alternates to work via sources
From: Patrick Steinhardt <hidden>
Date: 2025-12-10 15:32:41
Hi,
this patch series refactors how we handle alternate object directories
so that the interface is structured around the object database source.
Next to being simpler to reason about, it also allows us to eventually
abstract handling of alternates to use different mechanisms based on the
specific backend used. In a world of pluggable object databases not
every backend may use a physical directory, so it may not be possible to
read alternates via "objects/info/alternates". Consequently, formats may
need a different mechanism entirely to make this list available.
Changes in v2:
- Rename `odb_add_source()` to `odb_add_alternates_recursive()` to
highlight that this function is recursive.
- Link to v1: https://lore.kernel.org/r/20251208-b4-pks-odb-alternates-via-source-v1-0-e7ebb8b18c03@pks.im (local)
Thanks!
Patrick
---
Patrick Steinhardt (8):
odb: refactor parsing of alternates to be self-contained
odb: resolve relative alternative paths when parsing
odb: move computation of normalized objdir into `alt_odb_usable()`
odb: adapt `odb_add_to_alternates_file()` to call `odb_add_source()`
odb: remove mutual recursion when parsing alternates
odb: drop forward declaration of `read_info_alternates()`
odb: read alternates via sources
odb: write alternates via sources
odb.c | 307 ++++++++++++++++++++++++++++++++++--------------------------------
1 file changed, 158 insertions(+), 149 deletions(-)
Range-diff versus v1:
1: 18b0d15865 = 1: 392036039f odb: refactor parsing of alternates to be self-contained
2: aaf9d4e162 ! 2: 0107d40816 odb: resolve relative alternative paths when parsing
@@ Commit message
cannot be resolved to a directory then `alt_odb_usable()` still knows to
bail out.
- While at it, rename the function to `odb_add_source()` to more clearly
- indicate what its intent is and to align it with modern terminology.
+ While at it, rename the function to `odb_add_alternate_recursively()` to
+ more clearly indicate what its intent is and to align it with modern
+ terminology.
Signed-off-by: Patrick Steinhardt [off-list ref]
@@ odb.c: static struct odb_source *odb_source_new(struct object_database *odb,
- const char *dir,
- const char *relative_base,
- int depth)
-+static struct odb_source *odb_add_source(struct object_database *odb,
-+ const char *source,
-+ int depth)
++static struct odb_source *odb_add_alternate_recursively(struct object_database *odb,
++ const char *source,
++ int depth)
{
struct odb_source *alternate = NULL;
- struct strbuf pathbuf = STRBUF_INIT;
@@ odb.c: static void link_alt_odb_entries(struct object_database *odb, const char
for (size_t i = 0; i < alternates.nr; i++)
- link_alt_odb_entry(odb, alternates.v[i], relative_base, depth);
-+ odb_add_source(odb, alternates.v[i], depth);
++ odb_add_alternate_recursively(odb, alternates.v[i], depth);
strvec_clear(&alternates);
}
@@ odb.c: struct odb_source *odb_add_to_alternates_memory(struct object_database *o
*/
odb_prepare_alternates(odb);
- return link_alt_odb_entry(odb, dir, NULL, 0);
-+ return odb_add_source(odb, dir, 0);
++ return odb_add_alternate_recursively(odb, dir, 0);
}
struct odb_source *odb_set_temporary_primary_source(struct object_database *odb,
3: 077480d200 ! 3: 8b918fec33 odb: move computation of normalized objdir into `alt_odb_usable()`
@@ odb.c: static int alt_odb_usable(struct object_database *o, const char *path,
}
/*
-@@ odb.c: static struct odb_source *odb_add_source(struct object_database *odb,
- int depth)
+@@ odb.c: static struct odb_source *odb_add_alternate_recursively(struct object_database *
+ int depth)
{
struct odb_source *alternate = NULL;
- struct strbuf tmp = STRBUF_INIT;
@@ odb.c: static struct odb_source *odb_add_source(struct object_database *odb,
goto error;
alternate = odb_source_new(odb, source, false);
-@@ odb.c: static struct odb_source *odb_add_source(struct object_database *odb,
+@@ odb.c: static struct odb_source *odb_add_alternate_recursively(struct object_database *
read_info_alternates(odb, alternate->path, depth + 1);
error:
4: f536d0afc3 = 4: 618bfedf22 odb: adapt `odb_add_to_alternates_file()` to call `odb_add_source()`
5: 0930371378 ! 5: 50e93145e4 odb: remove mutual recursion when parsing alternates
@@ Commit message
Refactor the function to remove the mutual recursion between adding
sources and parsing alternates. The parsing step thus becomes completely
oblivious to the fact that there is recursive behaviour going on at all.
- Instead, the recursion is handled exclusively by `odb_add_source()`,
+ The recursion is handled by `odb_add_alternate_recursively()` instead,
which now recurses with itself.
This refactoring allows us to move parsing of alternates into object
@@ odb.c: static bool odb_is_source_usable(struct object_database *o, const char *p
static struct odb_source *odb_source_new(struct object_database *odb,
const char *path,
-@@ odb.c: static struct odb_source *odb_add_source(struct object_database *odb,
- int depth)
+@@ odb.c: static struct odb_source *odb_add_alternate_recursively(struct object_database *
+ int depth)
{
struct odb_source *alternate = NULL;
+ struct strvec sources = STRVEC_INIT;
khiter_t pos;
int ret;
-@@ odb.c: static struct odb_source *odb_add_source(struct object_database *odb,
+@@ odb.c: static struct odb_source *odb_add_alternate_recursively(struct object_database *
kh_value(odb->source_by_path, pos) = alternate;
/* recursively add alternates */
@@ odb.c: static struct odb_source *odb_add_source(struct object_database *odb,
+ source);
+ } else {
+ for (size_t i = 0; i < sources.nr; i++)
-+ odb_add_source(odb, sources.v[i], depth + 1);
++ odb_add_alternate_recursively(odb, sources.v[i], depth + 1);
+ }
error:
@@ odb.c: static void parse_alternates(const char *string,
- parse_alternates(alt, sep, relative_base, &alternates);
-
- for (size_t i = 0; i < alternates.nr; i++)
-- odb_add_source(odb, alternates.v[i], depth);
+- odb_add_alternate_recursively(odb, alternates.v[i], depth);
-
- strvec_clear(&alternates);
-}
@@ odb.c: static void read_info_alternates(struct object_database *odb,
strbuf_release(&buf);
free(path);
}
+@@ odb.c: void odb_add_to_alternates_file(struct object_database *odb,
+ if (commit_lock_file(&lock))
+ die_errno(_("unable to move new alternates file into place"));
+ if (odb->loaded_alternates)
+- odb_add_source(odb, dir, 0);
++ odb_add_alternate_recursively(odb, dir, 0);
+ }
+ free(alts);
+ }
@@ odb.c: int odb_for_each_alternate(struct object_database *odb,
void odb_prepare_alternates(struct object_database *odb)
@@ odb.c: int odb_for_each_alternate(struct object_database *odb,
+ parse_alternates(odb->alternate_db, PATH_SEP, NULL, &sources);
+ read_info_alternates(odb->sources->path, &sources);
+ for (size_t i = 0; i < sources.nr; i++)
-+ odb_add_source(odb, sources.v[i], 0);
++ odb_add_alternate_recursively(odb, sources.v[i], 0);
- read_info_alternates(odb, odb->sources->path, 0);
odb->loaded_alternates = 1;
6: be857d1b09 ! 6: d397255cdb odb: drop forward declaration of `read_info_alternates()`
@@ odb.c: static bool odb_is_source_usable(struct object_database *o, const char *p
- return source;
-}
-
--static struct odb_source *odb_add_source(struct object_database *odb,
-- const char *source,
-- int depth)
+-static struct odb_source *odb_add_alternate_recursively(struct object_database *odb,
+- const char *source,
+- int depth)
-{
- struct odb_source *alternate = NULL;
- struct strvec sources = STRVEC_INIT;
@@ odb.c: static bool odb_is_source_usable(struct object_database *o, const char *p
- source);
- } else {
- for (size_t i = 0; i < sources.nr; i++)
-- odb_add_source(odb, sources.v[i], depth + 1);
+- odb_add_alternate_recursively(odb, sources.v[i], depth + 1);
- }
-
- error:
@@ odb.c: static void read_info_alternates(const char *relative_base,
+ return source;
+}
+
-+static struct odb_source *odb_add_source(struct object_database *odb,
-+ const char *source,
-+ int depth)
++static struct odb_source *odb_add_alternate_recursively(struct object_database *odb,
++ const char *source,
++ int depth)
+{
+ struct odb_source *alternate = NULL;
+ struct strvec sources = STRVEC_INIT;
@@ odb.c: static void read_info_alternates(const char *relative_base,
+ source);
+ } else {
+ for (size_t i = 0; i < sources.nr; i++)
-+ odb_add_source(odb, sources.v[i], depth + 1);
++ odb_add_alternate_recursively(odb, sources.v[i], depth + 1);
+ }
+
+ error:
7: a811f6abd6 ! 7: a39997318c odb: read alternates via sources
@@ odb.c: static void parse_alternates(const char *string,
strbuf_release(&buf);
free(path);
-@@ odb.c: static struct odb_source *odb_add_source(struct object_database *odb,
+@@ odb.c: static struct odb_source *odb_add_alternate_recursively(struct object_database *
kh_value(odb->source_by_path, pos) = alternate;
/* recursively add alternates */
@@ odb.c: void odb_prepare_alternates(struct object_database *odb)
- read_info_alternates(odb->sources->path, &sources);
+ odb_source_read_alternates(odb->sources, &sources);
for (size_t i = 0; i < sources.nr; i++)
- odb_add_source(odb, sources.v[i], 0);
+ odb_add_alternate_recursively(odb, sources.v[i], 0);
8: be62ab52ab ! 8: 082eb43b82 odb: write alternates via sources
@@ Commit message
Signed-off-by: Patrick Steinhardt [off-list ref]
## odb.c ##
-@@ odb.c: static struct odb_source *odb_add_source(struct object_database *odb,
+@@ odb.c: static struct odb_source *odb_add_alternate_recursively(struct object_database *
return alternate;
}
@@ odb.c: void odb_add_to_alternates_file(struct object_database *odb,
- if (commit_lock_file(&lock))
- die_errno(_("unable to move new alternates file into place"));
- if (odb->loaded_alternates)
-- odb_add_source(odb, dir, 0);
+- odb_add_alternate_recursively(odb, dir, 0);
+ fprintf_or_die(out, "%s\n", alternate);
+ if (commit_lock_file(&lock)) {
+ ret = error_errno(_("unable to move new alternates file into place"));
@@ odb.c: void odb_add_to_alternates_file(struct object_database *odb,
+ if (ret < 0)
+ die(NULL);
+ if (odb->loaded_alternates)
-+ odb_add_source(odb, dir, 0);
++ odb_add_alternate_recursively(odb, dir, 0);
}
struct odb_source *odb_add_to_alternates_memory(struct object_database *odb,
---
base-commit: bdc5341ff65278a3cc80b2e8a02a2f02aa1fac06
change-id: 20251206-b4-pks-odb-alternates-via-source-802d87cbbda5