[PATCH 15/17] odb/source: make `read_alternates()` function pluggable
- From
Patrick Steinhardt <ps@pks.im>
- Date
- Feb 23, 2026, 16:18 UTC
- Message-ID
- <20260223-b4-pks-odb-source-pluggable-v1-15-253bac1db598@pks.im>
- In-Reply-To
- <20260223-b4-pks-odb-source-pluggable-v1-0-253bac1db598@pks.im>
Introduce a new callback function in `struct odb_source` to make the function pluggable.
Signed-off-by: Patrick Steinhardt <ps@pks.im> --- odb.c | 26 ++++---------------------- odb.h | 5 +++++ odb/source-files.c | 22 ++++++++++++++++++++++ odb/source.h | 29 +++++++++++++++++++++++++++++ 4 files changed, 60 insertions(+), 22 deletions(-)
diff --git a/odb.c b/odb.c index f439de9db2..d9424cdfd0 100644 --- a/odb.c +++ b/odb.c @@ -131,10 +131,10 @@ static bool odb_is_source_usable(struct object_database *o, const char *path) return usable; } -static void parse_alternates(const char *string, - int sep, - const char *relative_base, - struct strvec *out) +void parse_alternates(const char *string, + int sep, + const char *relative_base, + struct strvec *out) { struct strbuf pathbuf = STRBUF_INIT; struct strbuf buf = STRBUF_INIT; @@ -198,24 +198,6 @@ static void parse_alternates(const char *string, strbuf_release(&buf); } -static void odb_source_read_alternates(struct odb_source *source, - struct strvec *out) -{ - struct strbuf buf = STRBUF_INIT; - char *path; - - path = xstrfmt("%s/info/alternates", source->path); - if (strbuf_read_file(&buf, path, 1024) < 0) { - warn_on_fopen_errors(path); - free(path); - return; - } - parse_alternates(buf.buf, '\n', source->path, out); - - strbuf_release(&buf); - free(path); -} - static struct odb_source *odb_add_alternate_recursively(struct object_database *odb, const char *source, int depth) diff --git a/odb.h b/odb.h index 692d9029ef..86e0365c24 100644 --- a/odb.h +++ b/odb.h @@ -500,4 +500,9 @@ int odb_write_object_stream(struct object_database *odb, struct odb_write_stream *stream, size_t len, struct object_id *oid); +void parse_alternates(const char *string, + int sep, + const char *relative_base, + struct strvec *out); + #endif /* ODB_H */ diff --git a/odb/source-files.c b/odb/source-files.c index b8844f11b7..199c55cfa4 100644 --- a/odb/source-files.c +++ b/odb/source-files.c @@ -2,9 +2,11 @@ #include "abspath.h" #include "chdir-notify.h" #include "object-file.h" +#include "odb.h" #include "odb/source.h" #include "odb/source-files.h" #include "packfile.h" +#include "strbuf.h" static void odb_source_files_reparent(const char *name UNUSED, const char *old_cwd, @@ -117,6 +119,25 @@ static int odb_source_files_write_object_stream(struct odb_source *source, return odb_source_loose_write_stream(source, stream, len, oid); } +static int odb_source_files_read_alternates(struct odb_source *source, + struct strvec *out) +{ + struct strbuf buf = STRBUF_INIT; + char *path; + + path = xstrfmt("%s/info/alternates", source->path); + if (strbuf_read_file(&buf, path, 1024) < 0) { + warn_on_fopen_errors(path); + free(path); + return 0; + } + parse_alternates(buf.buf, '\n', source->path, out); + + strbuf_release(&buf); + free(path); + return 0; +} + struct odb_source_files *odb_source_files_new(struct object_database *odb, const char *path, bool local) @@ -137,6 +158,7 @@ struct odb_source_files *odb_source_files_new(struct object_database *odb, files->base.freshen_object = odb_source_files_freshen_object; files->base.write_object = odb_source_files_write_object; files->base.write_object_stream = odb_source_files_write_object_stream; + files->base.read_alternates = odb_source_files_read_alternates; /* * Ideally, we would only ever store absolute paths in the source. This diff --git a/odb/source.h b/odb/source.h index ddce43eb20..14f5d56f68 100644 --- a/odb/source.h +++ b/odb/source.h @@ -55,6 +55,7 @@ struct object_id; struct object_info; struct odb_read_stream; struct odb_write_stream; +struct strvec; /* * A callback function that can be used to iterate through objects. If given, @@ -229,6 +230,20 @@ struct odb_source { int (*write_object_stream)(struct odb_source *source, struct odb_write_stream *stream, size_t len, struct object_id *oid); + + /* + * This callback is expected to read the list of alternate object + * database sources connected to it and write them into the `strvec`. + * + * The format is expected to follow the "objectStorage" extension + * format with `(backend://)?payload` syntax. If the payload contains + * paths, these paths must be resolved to absolute paths. + * + * The callback is expected to return 0 on success, a negative error + * code otherwise. + */ + int (*read_alternates)(struct odb_source *source, + struct strvec *out); }; /* @@ -379,4 +394,18 @@ static inline int odb_source_write_object_stream(struct odb_source *source, return source->write_object_stream(source, stream, len, oid); } +/* + * Read the list of alternative object database sources from the given backend + * and populate the `strvec` with them. The listing is not recursive -- that + * is, if any of the yielded alternate sources has alternates itself, those + * will not be yielded as part of this function call. + * + * Return 0 on success, a negative error code otherwise. + */ +static inline int odb_source_read_alternates(struct odb_source *source, + struct strvec *out) +{ + return source->read_alternates(source, out); +} + #endif
-- 2.53.0.536.g309c995771.dirty