git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v3 13/13] object-file: refactor writing objects via a stream

From
Patrick Steinhardt <ps@pks.im>
Date
Nov 3, 2025, 07:42 UTC
Message-ID
<20251103-b4-pks-odb-loose-backend-v3-13-6a61ea977393@pks.im>
In-Reply-To
<20251103-b4-pks-odb-loose-backend-v3-0-6a61ea977393@pks.im>
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>
---
 builtin/unpack-objects.c |  7 +++----
 object-file.c            |  6 +++---
 object-file.h            | 14 ++++----------
 odb.c                    |  7 +++++++
 odb.h                    | 10 ++++++++++
 5 files changed, 27 insertions(+), 17 deletions(-)
diff --git a/builtin/unpack-objects.c b/builtin/unpack-objects.c
index ef79e43715d..6fc64e9e4b8 100644
--- a/builtin/unpack-objects.c
+++ b/builtin/unpack-objects.c
@@ -363,7 +363,7 @@ struct input_zstream_data {
 	int status;
 };
 
-static const void *feed_input_zstream(struct input_stream *in_stream,
+static const void *feed_input_zstream(struct odb_write_stream *in_stream,
 				      unsigned long *readlen)
 {
 	struct input_zstream_data *data = in_stream->data;
@@ -393,7 +393,7 @@ static void stream_blob(unsigned long size, unsigned nr)
 {
 	git_zstream zstream = { 0 };
 	struct input_zstream_data data = { 0 };
-	struct input_stream in_stream = {
+	struct odb_write_stream in_stream = {
 		.read = feed_input_zstream,
 		.data = &data,
 	};
@@ -402,8 +402,7 @@ static void stream_blob(unsigned long size, unsigned nr)
 	data.zstream = &zstream;
 	git_inflate_init(&zstream);
 
-	if (stream_loose_object(the_repository->objects->sources,
-				&in_stream, size, &info->oid))
+	if (odb_write_object_stream(the_repository->objects, &in_stream, size, &info->oid))
 		die(_("failed to write object in stream"));
 
 	if (data.status != Z_STREAM_END)
diff --git a/object-file.c b/object-file.c
index fdc644a4275..811c569ed36 100644
--- a/object-file.c
+++ b/object-file.c
@@ -974,9 +974,9 @@ int odb_source_loose_freshen_object(struct odb_source *source,
 	return !!check_and_freshen_source(source, oid, 1);
 }
 
-int stream_loose_object(struct odb_source *source,
-			struct input_stream *in_stream, size_t len,
-			struct object_id *oid)
+int odb_source_loose_write_stream(struct odb_source *source,
+				  struct odb_write_stream *in_stream, size_t len,
+				  struct object_id *oid)
 {
 	const struct git_hash_algo *compat = source->odb->repo->compat_hash_algo;
 	struct object_id compat_oid;
diff --git a/object-file.h b/object-file.h
index 36a60e15c40..eeffa67bbda 100644
--- a/object-file.h
+++ b/object-file.h
@@ -67,6 +67,10 @@ int odb_source_loose_write_object(struct odb_source *source,
 				  enum object_type type, struct object_id *oid,
 				  struct object_id *compat_oid_in, unsigned flags);
 
+int odb_source_loose_write_stream(struct odb_source *source,
+				  struct odb_write_stream *stream, size_t len,
+				  struct object_id *oid);
+
 /*
  * Populate and return the loose object cache array corresponding to the
  * given object ID.
@@ -173,16 +177,6 @@ enum unpack_loose_header_result unpack_loose_header(git_zstream *stream,
 struct object_info;
 int parse_loose_header(const char *hdr, struct object_info *oi);
 
-struct input_stream {
-	const void *(*read)(struct input_stream *, unsigned long *len);
-	void *data;
-	int is_finished;
-};
-
-int stream_loose_object(struct odb_source *source,
-			struct input_stream *in_stream, size_t len,
-			struct object_id *oid);
-
 int force_object_loose(struct odb_source *source,
 		       const struct object_id *oid, time_t mtime);
 
diff --git a/odb.c b/odb.c
index da44f1d63b4..3ec21ef24e1 100644
--- a/odb.c
+++ b/odb.c
@@ -1025,6 +1025,13 @@ int odb_write_object_ext(struct object_database *odb,
 					     oid, compat_oid, flags);
 }
 
+int odb_write_object_stream(struct object_database *odb,
+			    struct odb_write_stream *stream, size_t len,
+			    struct object_id *oid)
+{
+	return odb_source_loose_write_stream(odb->sources, stream, len, oid);
+}
+
 struct object_database *odb_new(struct repository *repo)
 {
 	struct object_database *o = xmalloc(sizeof(*o));
diff --git a/odb.h b/odb.h
index 2653247e0cc..9bb28008b1d 100644
--- a/odb.h
+++ b/odb.h
@@ -492,4 +492,14 @@ static inline int odb_write_object(struct object_database *odb,
 	return odb_write_object_ext(odb, buf, len, type, oid, NULL, 0);
 }
 
+struct odb_write_stream {
+	const void *(*read)(struct odb_write_stream *, unsigned long *len);
+	void *data;
+	int is_finished;
+};
+
+int odb_write_object_stream(struct object_database *odb,
+			    struct odb_write_stream *stream, size_t len,
+			    struct object_id *oid);
+
 #endif /* ODB_H */
-- 
2.51.2.1041.gc1ab5b90ca.dirty
Previous: Patrick SteinhardtNext: Karthik Nayak
Message 57 of 58 in “Carve out loose object source”
  1. 00/13 Carve out loose object sourcePatrick Steinhardt, Oct 24, 2025
  2. 01/13 odb: fix subtle logic to check whether an alternate is usablePatrick Steinhardt, Oct 24, 2025
  3. Junio C HamanoOct 24, 2025
  4. Karthik NayakOct 30, 2025
  5. 02/13 odb: introduce `odb_source_new()`Patrick Steinhardt, Oct 24, 2025
  6. Junio C HamanoOct 24, 2025
  7. Patrick SteinhardtOct 27, 2025
  8. 03/13 odb: adjust naming to free object sourcesPatrick Steinhardt, Oct 24, 2025
  9. Karthik NayakOct 30, 2025
  10. 04/13 object-file: move `fetch_if_missing`Patrick Steinhardt, Oct 24, 2025
  11. 05/13 object-file: introduce `struct odb_loose_source`Patrick Steinhardt, Oct 24, 2025
  12. Karthik NayakOct 30, 2025
  13. Patrick SteinhardtOct 30, 2025
  14. Patrick SteinhardtOct 31, 2025
  15. Junio C HamanoOct 31, 2025
  16. Patrick SteinhardtNov 3, 2025
  17. Junio C HamanoOct 31, 2025
  18. 06/13 object-file: move loose object cache into loose sourcePatrick Steinhardt, Oct 24, 2025
  19. Junio C HamanoOct 24, 2025
  20. Patrick SteinhardtOct 27, 2025
  21. 07/13 object-file: hide internals when we need to reprepare loose sourcesPatrick Steinhardt, Oct 24, 2025
  22. 08/13 object-file: move loose object map into loose sourcePatrick Steinhardt, Oct 24, 2025
  23. 09/13 object-file: read objects via the loose object sourcePatrick Steinhardt, Oct 24, 2025
  24. Karthik NayakOct 30, 2025
  25. 10/13 object-file: rename `has_loose_object()`Patrick Steinhardt, Oct 24, 2025
  26. 11/13 object-file: refactor freshening of objectsPatrick Steinhardt, Oct 24, 2025
  27. 12/13 object-file: rename `write_object_file()`Patrick Steinhardt, Oct 24, 2025
  28. 13/13 object-file: refactor writing objects via a streamPatrick Steinhardt, Oct 24, 2025
  29. Karthik NayakOct 30, 2025
  30. 00/13 Carve out loose object sourcePatrick Steinhardt, Oct 31, 2025
  31. 01/13 odb: fix subtle logic to check whether an alternate is usablePatrick Steinhardt, Oct 31, 2025
  32. 02/13 odb: introduce `odb_source_new()`Patrick Steinhardt, Oct 31, 2025
  33. 03/13 odb: adjust naming to free object sourcesPatrick Steinhardt, Oct 31, 2025
  34. 04/13 object-file: move `fetch_if_missing`Patrick Steinhardt, Oct 31, 2025
  35. 05/13 object-file: introduce `struct odb_loose_source`Patrick Steinhardt, Oct 31, 2025
  36. 06/13 object-file: move loose object cache into loose sourcePatrick Steinhardt, Oct 31, 2025
  37. 07/13 object-file: hide internals when we need to reprepare loose sourcesPatrick Steinhardt, Oct 31, 2025
  38. 08/13 object-file: move loose object map into loose sourcePatrick Steinhardt, Oct 31, 2025
  39. 09/13 object-file: read objects via the loose object sourcePatrick Steinhardt, Oct 31, 2025
  40. 10/13 object-file: rename `has_loose_object()`Patrick Steinhardt, Oct 31, 2025
  41. 11/13 object-file: refactor freshening of objectsPatrick Steinhardt, Oct 31, 2025
  42. 12/13 object-file: rename `write_object_file()`Patrick Steinhardt, Oct 31, 2025
  43. 13/13 object-file: refactor writing objects via a streamPatrick Steinhardt, Oct 31, 2025
  44. 00/13 Carve out loose object sourcePatrick Steinhardt, Nov 3, 2025
  45. 01/13 odb: fix subtle logic to check whether an alternate is usablePatrick Steinhardt, Nov 3, 2025
  46. 02/13 odb: introduce `odb_source_new()`Patrick Steinhardt, Nov 3, 2025
  47. 03/13 odb: adjust naming to free object sourcesPatrick Steinhardt, Nov 3, 2025
  48. 04/13 object-file: move `fetch_if_missing`Patrick Steinhardt, Nov 3, 2025
  49. 05/13 object-file: introduce `struct odb_source_loose`Patrick Steinhardt, Nov 3, 2025
  50. 06/13 object-file: move loose object cache into loose sourcePatrick Steinhardt, Nov 3, 2025
  51. 07/13 object-file: hide internals when we need to reprepare loose sourcesPatrick Steinhardt, Nov 3, 2025
  52. 08/13 object-file: move loose object map into loose sourcePatrick Steinhardt, Nov 3, 2025
  53. 09/13 object-file: read objects via the loose object sourcePatrick Steinhardt, Nov 3, 2025
  54. 10/13 object-file: rename `has_loose_object()`Patrick Steinhardt, Nov 3, 2025
  55. 11/13 object-file: refactor freshening of objectsPatrick Steinhardt, Nov 3, 2025
  56. 12/13 object-file: rename `write_object_file()`Patrick Steinhardt, Nov 3, 2025
  57. 13/13 object-file: refactor writing objects via a streamPatrick Steinhardt, Nov 3, 2025
  58. Karthik NayakNov 3, 2025

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.