odb/source-inmemory: implement `for_each_object()` callback

Implement the `for_each_object()` callback function for the in-memory source. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Patrick Steinhardt committed Apr 10, 2026 at 14:12 UTC 4babe3b673882adf853526475192ae7e3007877c
1 file changed +72 -16
odb/source-inmemory.c
+72 -16
@@ -33,6 +33,28 @@ static const struct inmemory_object *find_cached_object(struct odb_source_inmemo
33 return NULL;
34 }
35
36 +static void populate_object_info(struct odb_source_inmemory *source,
37 + struct object_info *oi,
38 + const struct inmemory_object *object)
39 +{
40 + if (!oi)
41 + return;
42 +
43 + if (oi->typep)
44 + *(oi->typep) = object->type;
45 + if (oi->sizep)
46 + *(oi->sizep) = object->size;
47 + if (oi->disk_sizep)
48 + *(oi->disk_sizep) = 0;
49 + if (oi->delta_base_oid)
50 + oidclr(oi->delta_base_oid, source->base.odb->repo->hash_algo);
51 + if (oi->contentp)
52 + *oi->contentp = xmemdupz(object->buf, object->size);
53 + if (oi->mtimep)
54 + *oi->mtimep = 0;
55 + oi->whence = OI_CACHED;
56 +}
57 +
58 static int odb_source_inmemory_read_object_info(struct odb_source *source,
59 const struct object_id *oid,
60 struct object_info *oi,
@@ -45,22 +67,7 @@ static int odb_source_inmemory_read_object_info(struct odb_source *source,
67 if (!object)
68 return -1;
69
48 - if (oi) {
49 - if (oi->typep)
50 - *(oi->typep) = object->type;
51 - if (oi->sizep)
52 - *(oi->sizep) = object->size;
53 - if (oi->disk_sizep)
54 - *(oi->disk_sizep) = 0;
55 - if (oi->delta_base_oid)
56 - oidclr(oi->delta_base_oid, source->odb->repo->hash_algo);
57 - if (oi->contentp)
58 - *oi->contentp = xmemdupz(object->buf, object->size);
59 - if (oi->mtimep)
60 - *oi->mtimep = 0;
61 - oi->whence = OI_CACHED;
62 - }
63 -
70 + populate_object_info(inmemory, oi, object);
71 return 0;
72 }
73
@@ -114,6 +121,54 @@ static int odb_source_inmemory_read_object_stream(struct odb_read_stream **out,
121 return 0;
122 }
123
124 +struct odb_source_inmemory_for_each_object_data {
125 + struct odb_source_inmemory *inmemory;
126 + const struct object_info *request;
127 + odb_for_each_object_cb cb;
128 + void *cb_data;
129 +};
130 +
131 +static int odb_source_inmemory_for_each_object_cb(const struct object_id *oid,
132 + void *node_data, void *cb_data)
133 +{
134 + struct odb_source_inmemory_for_each_object_data *data = cb_data;
135 + struct inmemory_object *object = node_data;
136 +
137 + if (data->request) {
138 + struct object_info oi = *data->request;
139 + populate_object_info(data->inmemory, &oi, object);
140 + return data->cb(oid, &oi, data->cb_data);
141 + } else {
142 + return data->cb(oid, NULL, data->cb_data);
143 + }
144 +}
145 +
146 +static int odb_source_inmemory_for_each_object(struct odb_source *source,
147 + const struct object_info *request,
148 + odb_for_each_object_cb cb,
149 + void *cb_data,
150 + const struct odb_for_each_object_options *opts)
151 +{
152 + struct odb_source_inmemory *inmemory = odb_source_inmemory_downcast(source);
153 + struct odb_source_inmemory_for_each_object_data payload = {
154 + .inmemory = inmemory,
155 + .request = request,
156 + .cb = cb,
157 + .cb_data = cb_data,
158 + };
159 + struct object_id null_oid = { 0 };
160 +
161 + if ((opts->flags & ODB_FOR_EACH_OBJECT_PROMISOR_ONLY) ||
162 + (opts->flags & ODB_FOR_EACH_OBJECT_LOCAL_ONLY && !source->local))
163 + return 0;
164 + if (!inmemory->objects)
165 + return 0;
166 +
167 + return oidtree_each(inmemory->objects,
168 + opts->prefix ? opts->prefix : &null_oid, opts->prefix_hex_len,
169 + odb_source_inmemory_for_each_object_cb, &payload);
170 +}
171 +
172 static int odb_source_inmemory_write_object(struct odb_source *source,
173 const void *buf, unsigned long len,
174 enum object_type type,
@@ -219,6 +274,7 @@ struct odb_source_inmemory *odb_source_inmemory_new(struct object_database *odb)
274 source->base.free = odb_source_inmemory_free;
275 source->base.read_object_info = odb_source_inmemory_read_object_info;
276 source->base.read_object_stream = odb_source_inmemory_read_object_stream;
277 + source->base.for_each_object = odb_source_inmemory_for_each_object;
278 source->base.write_object = odb_source_inmemory_write_object;
279 source->base.write_object_stream = odb_source_inmemory_write_object_stream;
280