odb/source: make `read_object_stream()` function pluggable

Introduce a new callback function in `struct odb_source` to make the function pluggable. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Patrick Steinhardt committed Mar 5, 2026 at 15:19 UTC 1f3fd68e065b0f44432dc78c1b6f6e636929363e
3 files changed +37 -7
odb/source-files.c
+12
@@ -55,6 +55,17 @@ static int odb_source_files_read_object_info(struct odb_source *source,
55 return -1;
56 }
57
58 +static int odb_source_files_read_object_stream(struct odb_read_stream **out,
59 + struct odb_source *source,
60 + const struct object_id *oid)
61 +{
62 + struct odb_source_files *files = odb_source_files_downcast(source);
63 + if (!packfile_store_read_object_stream(out, files->packed, oid) ||
64 + !odb_source_loose_read_object_stream(out, source, oid))
65 + return 0;
66 + return -1;
67 +}
68 +
69 struct odb_source_files *odb_source_files_new(struct object_database *odb,
70 const char *path,
71 bool local)
@@ -70,6 +81,7 @@ struct odb_source_files *odb_source_files_new(struct object_database *odb,
81 files->base.close = odb_source_files_close;
82 files->base.reprepare = odb_source_files_reprepare;
83 files->base.read_object_info = odb_source_files_read_object_info;
84 + files->base.read_object_stream = odb_source_files_read_object_stream;
85
86 /*
87 * Ideally, we would only ever store absolute paths in the source. This
odb/source.h
+23
@@ -50,6 +50,7 @@ enum object_info_flags {
50
51 struct object_id;
52 struct object_info;
53 +struct odb_read_stream;
54
55 /*
56 * The source is the part of the object database that stores the actual
@@ -138,6 +139,17 @@ struct odb_source {
139 const struct object_id *oid,
140 struct object_info *oi,
141 enum object_info_flags flags);
142 +
143 + /*
144 + * This callback is expected to create a new read stream that can be
145 + * used to stream the object identified by the given ID.
146 + *
147 + * The callback is expected to return a negative error code in case
148 + * creating the object stream has failed, 0 otherwise.
149 + */
150 + int (*read_object_stream)(struct odb_read_stream **out,
151 + struct odb_source *source,
152 + const struct object_id *oid);
153 };
154
155 /*
@@ -209,4 +221,15 @@ static inline int odb_source_read_object_info(struct odb_source *source,
221 return source->read_object_info(source, oid, oi, flags);
222 }
223
224 +/*
225 + * Create a new read stream for the given object ID. Returns 0 on success, a
226 + * negative error code otherwise.
227 + */
228 +static inline int odb_source_read_object_stream(struct odb_read_stream **out,
229 + struct odb_source *source,
230 + const struct object_id *oid)
231 +{
232 + return source->read_object_stream(out, source, oid);
233 +}
234 +
235 #endif
odb/streaming.c
+2 -7
@@ -6,11 +6,9 @@
6 #include "convert.h"
7 #include "environment.h"
8 #include "repository.h"
9 -#include "object-file.h"
9 #include "odb.h"
10 #include "odb/streaming.h"
11 #include "replace-object.h"
13 -#include "packfile.h"
12
13 #define FILTER_BUFFER (1024*16)
14
@@ -186,12 +184,9 @@ static int istream_source(struct odb_read_stream **out,
184 struct odb_source *source;
185
186 odb_prepare_alternates(odb);
189 - for (source = odb->sources; source; source = source->next) {
190 - struct odb_source_files *files = odb_source_files_downcast(source);
191 - if (!packfile_store_read_object_stream(out, files->packed, oid) ||
192 - !odb_source_loose_read_object_stream(out, source, oid))
187 + for (source = odb->sources; source; source = source->next)
188 + if (!odb_source_read_object_stream(out, source, oid))
189 return 0;
194 - }
190
191 return open_istream_incore(out, odb, oid);
192 }