packfile: introduce function to iterate through objects

Introduce a new function `packfile_store_for_each_object()`. This function is equivalent to `odb_source_loose_for_each_object()`, except that it: - Works on a single packfile store instead of working on the object database level. Consequently, it will only yield packed objects of a single object database source. - Passes a `struct object_info` to the callback function. As such, it provides the same callback interface as we already provide for loose objects now. These functions will be used in a subsequent step to implement `odb_for_each_object()`. The `for_each_packed_object()` function continues to exist for now, but it will be removed at the end of this patch series. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Patrick Steinhardt committed Jan 26, 2026 at 10:51 UTC 736464b84f4439361ec10e9ef49bff674fea952d
2 files changed +66
packfile.c
+51
@@ -2360,6 +2360,57 @@ int for_each_packed_object(struct repository *repo, each_packed_object_fn cb,
2360 return ret ? ret : pack_errors;
2361 }
2362
2363 +struct packfile_store_for_each_object_wrapper_data {
2364 + struct packfile_store *store;
2365 + const struct object_info *request;
2366 + odb_for_each_object_cb cb;
2367 + void *cb_data;
2368 +};
2369 +
2370 +static int packfile_store_for_each_object_wrapper(const struct object_id *oid,
2371 + struct packed_git *pack,
2372 + uint32_t index_pos,
2373 + void *cb_data)
2374 +{
2375 + struct packfile_store_for_each_object_wrapper_data *data = cb_data;
2376 +
2377 + if (data->request) {
2378 + off_t offset = nth_packed_object_offset(pack, index_pos);
2379 + struct object_info oi = *data->request;
2380 +
2381 + if (packed_object_info(pack, offset, &oi) < 0) {
2382 + mark_bad_packed_object(pack, oid);
2383 + return -1;
2384 + }
2385 +
2386 + return data->cb(oid, &oi, data->cb_data);
2387 + } else {
2388 + return data->cb(oid, NULL, data->cb_data);
2389 + }
2390 +}
2391 +
2392 +int packfile_store_for_each_object(struct packfile_store *store,
2393 + const struct object_info *request,
2394 + odb_for_each_object_cb cb,
2395 + void *cb_data,
2396 + unsigned flags)
2397 +{
2398 + struct packfile_store_for_each_object_wrapper_data data = {
2399 + .store = store,
2400 + .request = request,
2401 + .cb = cb,
2402 + .cb_data = cb_data,
2403 + };
2404 + int pack_errors = 0, ret;
2405 +
2406 + ret = packfile_store_for_each_object_internal(store, packfile_store_for_each_object_wrapper,
2407 + &data, flags, &pack_errors);
2408 + if (ret)
2409 + return ret;
2410 +
2411 + return pack_errors ? -1 : 0;
2412 +}
2413 +
2414 static int add_promisor_object(const struct object_id *oid,
2415 struct packed_git *pack,
2416 uint32_t pos UNUSED,
packfile.h
+15
@@ -343,6 +343,21 @@ int for_each_object_in_pack(struct packed_git *p,
343 int for_each_packed_object(struct repository *repo, each_packed_object_fn cb,
344 void *data, unsigned flags);
345
346 +/*
347 + * Iterate through all packed objects in the given packfile store and invoke
348 + * the callback function for each of them. If an object info request is given,
349 + * then the object info will be read for every individual object and passed to
350 + * the callback as if `packfile_store_read_object_info()` was called for the
351 + * object.
352 + *
353 + * The flags parameter is a combination of `odb_for_each_object_flags`.
354 + */
355 +int packfile_store_for_each_object(struct packfile_store *store,
356 + const struct object_info *request,
357 + odb_for_each_object_cb cb,
358 + void *cb_data,
359 + unsigned flags);
360 +
361 /* A hook to report invalid files in pack directory */
362 #define PACKDIR_FILE_PACK 1
363 #define PACKDIR_FILE_IDX 2