[PATCH 6/8] odb/source: support writing alternates when creating the database
From: Patrick Steinhardt <hidden>
Date: 2026-08-25 14:12:49
Subsystem:
the rest · Maintainer:
Linus Torvalds
Add the ability to write alternates when creating the object database. This change allows us to remove the `write_alternates()` callback in a subsequent patch. Signed-off-by: Patrick Steinhardt <redacted> --- odb/source-files.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- odb/source.h | 18 +++++++++++--- setup.c | 4 ++- 3 files changed, 89 insertions(+), 6 deletions(-)
diff --git a/odb/source-files.c b/odb/source-files.c
index b7b3a297bb..5e77b21d9f 100644
--- a/odb/source-files.c
+++ b/odb/source-files.c@@ -18,6 +18,7 @@ #include "run-command.h" #include "strbuf.h" #include "string-list.h" +#include "strmap.h" #include "strvec.h" #include "tree.h" #include "write-or-die.h"
@@ -51,9 +52,14 @@ static void odb_source_files_close(struct odb_source *source) odb_source_close(&files->packed->base); } -static int odb_source_files_create_on_disk(struct odb_source *source) +static int odb_source_files_create_on_disk(struct odb_source *source, + const struct odb_create_on_disk_options *opts) { struct strbuf path = STRBUF_INIT; + struct strset seen = STRSET_INIT; + struct strbuf line = STRBUF_INIT; + FILE *f = NULL; + int ret; safe_create_dir(source->odb->repo, source->path, 1);
@@ -64,8 +70,71 @@ static int odb_source_files_create_on_disk(struct odb_source *source) strbuf_addf(&path, "%s/info", source->path); safe_create_dir(source->odb->repo, path.buf, 1); + if (opts->alternates && opts->alternates->nr) { + strbuf_reset(&path); + strbuf_addf(&path, "%s/info/alternates", source->path); + + /* + * The alternates file may already exist, e.g. when it has been + * seeded from a template directory. Read any preexisting + * entries so that we don't end up writing duplicates. + */ + f = fopen(path.buf, "r"); + if (f) { + while (strbuf_getline(&line, f) != EOF) + strset_add(&seen, line.buf); + + if (ferror(f)) { + ret = error_errno(_("unable to read alternates file")); + goto out; + } + + fclose(f); + } else if (errno != ENOENT) { + ret = error_errno(_("unable to read alternates file")); + goto out; + } + + f = fopen(path.buf, "a"); + if (!f) { + ret = error_errno(_("unable to open alternates file for writing")); + goto out; + } + + for (size_t i = 0; i < opts->alternates->nr; i++) { + const char *alternate = opts->alternates->v[i]; + + if (!strset_add(&seen, alternate)) + continue; + + fprintf(f, "%s\n", alternate); + } + + if (ferror(f)) { + ret = error_errno(_("unable to write alternates file")); + goto out; + } + + ret = fclose(f); + f = NULL; + if (ret) { + ret = error_errno(_("unable to write alternates file")); + goto out; + } + } + + /* Reprepare the object database to activate alternates. */ + odb_reprepare(source->odb); + + ret = 0; + +out: + if (f) + fclose(f); + strbuf_release(&line); strbuf_release(&path); - return 0; + strset_clear(&seen); + return ret; } static void odb_source_files_prepare(struct odb_source *source,
diff --git a/odb/source.h b/odb/source.h
index ea8675247e..86b82fab3b 100644
--- a/odb/source.h
+++ b/odb/source.h@@ -5,6 +5,7 @@ #include "object.h" #include "odb.h" #include "odb/transaction.h" +#include "strvec.h" enum odb_source_type { /*
@@ -26,6 +27,15 @@ enum odb_source_type { ODB_SOURCE_INMEMORY, }; +struct odb_create_on_disk_options { + /* + * Alternates that shall be written into the newly created object + * database. Whether or not this option can be handled is specific to + * the backend. + */ + const struct strvec *alternates; +}; + /* * Convert between the enum and its name. Returns the equivalent of "unknown" * for unknown types.
@@ -106,7 +116,8 @@ struct odb_source { * This callback may be NULL in case the source does not need any * on-disk setup. */ - int (*create_on_disk)(struct odb_source *source); + int (*create_on_disk)(struct odb_source *source, + const struct odb_create_on_disk_options *opts); /* * This callback is expected to prepare the source so that it becomes
@@ -356,11 +367,12 @@ static inline void odb_source_close(struct odb_source *source) * Create on-disk data structures that are required for this source to operate * correctly. Returns 0 on success, a negative error code otherwise. */ -static inline int odb_source_create_on_disk(struct odb_source *source) +static inline int odb_source_create_on_disk(struct odb_source *source, + const struct odb_create_on_disk_options *opts) { if (!source->create_on_disk) return 0; - return source->create_on_disk(source); + return source->create_on_disk(source, opts); } /*
diff --git a/setup.c b/setup.c
index e654e27d05..426cc7dff8 100644
--- a/setup.c
+++ b/setup.c@@ -2649,6 +2649,8 @@ static int create_default_files(struct repository *repo, void create_object_database(struct repository *repo) { + struct odb_create_on_disk_options opts = { 0 }; + /* * Create the "objects" directory in the common directory. This is done * so that the repository can be discovered regardless of the backend
@@ -2668,7 +2670,7 @@ void create_object_database(struct repository *repo) repo->objects = odb_new(repo, ODB_NEW_HONOR_ENV); - if (odb_source_create_on_disk(repo->objects->sources) < 0) + if (odb_source_create_on_disk(repo->objects->sources, &opts) < 0) die(_("failed creating object database")); }
--
2.55.0.822.g20453c30eb.dirty