object-file: refactor writing objects via a stream

We have two different ways to write an object into the database: - We either provide the full buffer and write the object all at once. - Or we provide an input stream that has a `read()` function so that we can chunk the object. The latter is especially used for large objects, where it may be too expensive to hold the complete object in memory all at once. While we already have `odb_write_object()` at the ODB-layer, we don't have an equivalent for streaming an object. Introduce a new function `odb_write_object_stream()` to address this gap so that callers don't have to be aware of the inner workings of how to stream an object to disk with a specific object source. Rename `stream_loose_object()` to `odb_source_loose_write_stream()` to clarify its scope. This matches our modern best practices around how to name functions. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Patrick Steinhardt committed Nov 3, 2025 at 08:42 UTC 3e5e360888316ed1a44da69bf134bb6ec70aee1b
5 files changed +27 -17
builtin/unpack-objects.c
+3 -4
@@ -363,7 +363,7 @@ struct input_zstream_data {
363 int status;
364 };
365
366 -static const void *feed_input_zstream(struct input_stream *in_stream,
366 +static const void *feed_input_zstream(struct odb_write_stream *in_stream,
367 unsigned long *readlen)
368 {
369 struct input_zstream_data *data = in_stream->data;
@@ -393,7 +393,7 @@ static void stream_blob(unsigned long size, unsigned nr)
393 {
394 git_zstream zstream = { 0 };
395 struct input_zstream_data data = { 0 };
396 - struct input_stream in_stream = {
396 + struct odb_write_stream in_stream = {
397 .read = feed_input_zstream,
398 .data = &data,
399 };
@@ -402,8 +402,7 @@ static void stream_blob(unsigned long size, unsigned nr)
402 data.zstream = &zstream;
403 git_inflate_init(&zstream);
404
405 - if (stream_loose_object(the_repository->objects->sources,
406 - &in_stream, size, &info->oid))
405 + if (odb_write_object_stream(the_repository->objects, &in_stream, size, &info->oid))
406 die(_("failed to write object in stream"));
407
408 if (data.status != Z_STREAM_END)
object-file.c
+3 -3
@@ -974,9 +974,9 @@ int odb_source_loose_freshen_object(struct odb_source *source,
974 return !!check_and_freshen_source(source, oid, 1);
975 }
976
977 -int stream_loose_object(struct odb_source *source,
978 - struct input_stream *in_stream, size_t len,
979 - struct object_id *oid)
977 +int odb_source_loose_write_stream(struct odb_source *source,
978 + struct odb_write_stream *in_stream, size_t len,
979 + struct object_id *oid)
980 {
981 const struct git_hash_algo *compat = source->odb->repo->compat_hash_algo;
982 struct object_id compat_oid;
object-file.h
+4 -10
@@ -67,6 +67,10 @@ int odb_source_loose_write_object(struct odb_source *source,
67 enum object_type type, struct object_id *oid,
68 struct object_id *compat_oid_in, unsigned flags);
69
70 +int odb_source_loose_write_stream(struct odb_source *source,
71 + struct odb_write_stream *stream, size_t len,
72 + struct object_id *oid);
73 +
74 /*
75 * Populate and return the loose object cache array corresponding to the
76 * given object ID.
@@ -173,16 +177,6 @@ enum unpack_loose_header_result unpack_loose_header(git_zstream *stream,
177 struct object_info;
178 int parse_loose_header(const char *hdr, struct object_info *oi);
179
176 -struct input_stream {
177 - const void *(*read)(struct input_stream *, unsigned long *len);
178 - void *data;
179 - int is_finished;
180 -};
181 -
182 -int stream_loose_object(struct odb_source *source,
183 - struct input_stream *in_stream, size_t len,
184 - struct object_id *oid);
185 -
180 int force_object_loose(struct odb_source *source,
181 const struct object_id *oid, time_t mtime);
182
odb.c
+7
@@ -1025,6 +1025,13 @@ int odb_write_object_ext(struct object_database *odb,
1025 oid, compat_oid, flags);
1026 }
1027
1028 +int odb_write_object_stream(struct object_database *odb,
1029 + struct odb_write_stream *stream, size_t len,
1030 + struct object_id *oid)
1031 +{
1032 + return odb_source_loose_write_stream(odb->sources, stream, len, oid);
1033 +}
1034 +
1035 struct object_database *odb_new(struct repository *repo)
1036 {
1037 struct object_database *o = xmalloc(sizeof(*o));
odb.h
+10
@@ -492,4 +492,14 @@ static inline int odb_write_object(struct object_database *odb,
492 return odb_write_object_ext(odb, buf, len, type, oid, NULL, 0);
493 }
494
495 +struct odb_write_stream {
496 + const void *(*read)(struct odb_write_stream *, unsigned long *len);
497 + void *data;
498 + int is_finished;
499 +};
500 +
501 +int odb_write_object_stream(struct object_database *odb,
502 + struct odb_write_stream *stream, size_t len,
503 + struct object_id *oid);
504 +
505 #endif /* ODB_H */