streaming: drop the `open()` callback function

When creating a read stream we first populate the structure with the open callback function and then subsequently call the function. This layout is somewhat weird though: - The structure needs to be allocated and partially populated with the open function before we can properly initialize it. - We only ever call the `open()` callback function right after having populated the `struct odb_read_stream::open` member, and it's never called thereafter again. So it is somewhat pointless to store the callback in the first place. Especially the first point creates a problem for us. In subsequent commits we'll want to fully move construction of the read source into the respective object sources. E.g., the loose object source will be the one that is responsible for creating the structure. But this creates a problem: if we first need to create the structure so that we can call the source-specific callback we cannot fully handle creation of the structure in the source itself. We could of course work around that and have the loose object source create the structure and populate its `open()` callback, only. But this doesn't really buy us anything due to the second bullet point above. Instead, drop the callback entirely and refactor `istream_source()` so that we open the streams immediately. This unblocks a subsequent step, where we'll also start to allocate the structure in the source-specific logic. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Patrick Steinhardt committed Nov 23, 2025 at 19:59 UTC 70c8b5f5453b9f128a72fad4398acfb9e7d869c4
1 file changed +15 -22
streaming.c
+15 -22
@@ -14,10 +14,6 @@
14 #include "replace-object.h"
15 #include "packfile.h"
16
17 -typedef int (*open_istream_fn)(struct odb_read_stream *,
18 - struct repository *,
19 - const struct object_id *,
20 - enum object_type *);
17 typedef int (*close_istream_fn)(struct odb_read_stream *);
18 typedef ssize_t (*read_istream_fn)(struct odb_read_stream *, char *, size_t);
19
@@ -34,7 +30,6 @@ struct filtered_istream {
30 };
31
32 struct odb_read_stream {
37 - open_istream_fn open;
33 close_istream_fn close;
34 read_istream_fn read;
35
@@ -437,21 +432,25 @@ static int istream_source(struct odb_read_stream *st,
432
433 switch (oi.whence) {
434 case OI_LOOSE:
440 - st->open = open_istream_loose;
435 + if (open_istream_loose(st, r, oid, type) < 0)
436 + break;
437 return 0;
438 case OI_PACKED:
443 - if (!oi.u.packed.is_delta &&
444 - repo_settings_get_big_file_threshold(the_repository) < size) {
445 - st->u.in_pack.pack = oi.u.packed.pack;
446 - st->u.in_pack.pos = oi.u.packed.offset;
447 - st->open = open_istream_pack_non_delta;
448 - return 0;
449 - }
450 - /* fallthru */
451 - default:
452 - st->open = open_istream_incore;
439 + if (oi.u.packed.is_delta ||
440 + repo_settings_get_big_file_threshold(the_repository) >= size)
441 + break;
442 +
443 + st->u.in_pack.pack = oi.u.packed.pack;
444 + st->u.in_pack.pos = oi.u.packed.offset;
445 + if (open_istream_pack_non_delta(st, r, oid, type) < 0)
446 + break;
447 +
448 return 0;
449 + default:
450 + break;
451 }
452 +
453 + return open_istream_incore(st, r, oid, type);
454 }
455
456 /****************************************************************
@@ -485,12 +484,6 @@ struct odb_read_stream *open_istream(struct repository *r,
484 return NULL;
485 }
486
488 - if (st->open(st, r, real, type)) {
489 - if (open_istream_incore(st, r, real, type)) {
490 - free(st);
491 - return NULL;
492 - }
493 - }
487 if (filter) {
488 /* Add "&& !is_null_stream_filter(filter)" for performance */
489 struct odb_read_stream *nst = attach_stream_filter(st, filter);