odb/source-packed: improve lookup when enumerating objects

When iterating through objects of a packed source that have a specific prefix we do so via two different methods: - When a multi-pack index is available we use that one to efficiently loop through all objects. - We then loop through all packfiles that aren't covered by a multi-pack index. Regardless of which mechanism we use, we then iterate through all the objects indexed by the respective data structure. Curiously though, while we use the indices for enumerating the objects, we completely ignore it for the actual object lookup. Instead, we call into the generic `odb_source_read_object_info()` function, which will itself consult the indices to figure out where the object in question even lives. This has two consequences: - It's inefficient, as we basically have to figure out the position of the object a second time. - It's subtly wrong, as it may now happen that a specific object will be looked up via a different pack in case it exists multiple times. This is unlikely to have any real-world consequences, but it's still the wrong thing to do. Fix the issue by using `packed_object_info()` directly. While at it, rename the `store` variable to `source`. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Patrick Steinhardt committed Jul 15, 2026 at 08:22 UTC 27bed41ebb11ffdfcb79cf74fd4122ac41420f26
1 file changed +8 -7
odb/source-packed.c
+8 -7
@@ -143,7 +143,7 @@ static bool should_exclude_pack(struct packed_git *p, enum odb_for_each_object_f
143 }
144
145 static int for_each_prefixed_object_in_midx(
146 - struct odb_source_packed *store,
146 + struct odb_source_packed *source,
147 struct multi_pack_index *m,
148 const struct odb_for_each_object_options *opts,
149 struct odb_source_packed_for_each_object_wrapper_data *data)
@@ -170,6 +170,7 @@ static int for_each_prefixed_object_in_midx(
170 */
171 for (i = first; i < num; i++) {
172 const struct object_id *current = NULL;
173 + struct packed_git *pack;
174 struct object_id oid;
175
176 current = nth_midxed_object_oid(&oid, m, i);
@@ -177,9 +178,8 @@ static int for_each_prefixed_object_in_midx(
178 if (!match_hash(len, opts->prefix->hash, current->hash))
179 break;
180
180 - if (opts->flags) {
181 + if (opts->flags || data->request) {
182 uint32_t pack_id = nth_midxed_pack_int_id(m, i);
182 - struct packed_git *pack;
183
184 if (prepare_midx_pack(m, pack_id)) {
185 pack_errors = true;
@@ -193,9 +193,9 @@ static int for_each_prefixed_object_in_midx(
193
194 if (data->request) {
195 struct object_info oi = *data->request;
196 + off_t offset = nth_midxed_offset(m, i);
197
197 - ret = odb_source_read_object_info(&store->base, current,
198 - &oi, 0);
198 + ret = packed_object_info(source, pack, offset, &oi);
199 if (ret)
200 goto out;
201
@@ -219,7 +219,7 @@ out:
219 }
220
221 static int for_each_prefixed_object_in_pack(
222 - struct odb_source_packed *store,
222 + struct odb_source_packed *source,
223 struct packed_git *p,
224 const struct odb_for_each_object_options *opts,
225 struct odb_source_packed_for_each_object_wrapper_data *data)
@@ -246,8 +246,9 @@ static int for_each_prefixed_object_in_pack(
246
247 if (data->request) {
248 struct object_info oi = *data->request;
249 + off_t offset = nth_packed_object_offset(p, i);
250
250 - ret = odb_source_read_object_info(&store->base, &oid, &oi, 0);
251 + ret = packed_object_info(source, p, offset, &oi);
252 if (ret)
253 goto out;
254