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>
maint
Patrick Steinhardt 2026-01-26 10:51:22 +01:00 committed by Junio C Hamano
parent 3735311904
commit 736464b84f
2 changed files with 66 additions and 0 deletions

View File

@ -2360,6 +2360,57 @@ int for_each_packed_object(struct repository *repo, each_packed_object_fn cb,
return ret ? ret : pack_errors;
}

struct packfile_store_for_each_object_wrapper_data {
struct packfile_store *store;
const struct object_info *request;
odb_for_each_object_cb cb;
void *cb_data;
};

static int packfile_store_for_each_object_wrapper(const struct object_id *oid,
struct packed_git *pack,
uint32_t index_pos,
void *cb_data)
{
struct packfile_store_for_each_object_wrapper_data *data = cb_data;

if (data->request) {
off_t offset = nth_packed_object_offset(pack, index_pos);
struct object_info oi = *data->request;

if (packed_object_info(pack, offset, &oi) < 0) {
mark_bad_packed_object(pack, oid);
return -1;
}

return data->cb(oid, &oi, data->cb_data);
} else {
return data->cb(oid, NULL, data->cb_data);
}
}

int packfile_store_for_each_object(struct packfile_store *store,
const struct object_info *request,
odb_for_each_object_cb cb,
void *cb_data,
unsigned flags)
{
struct packfile_store_for_each_object_wrapper_data data = {
.store = store,
.request = request,
.cb = cb,
.cb_data = cb_data,
};
int pack_errors = 0, ret;

ret = packfile_store_for_each_object_internal(store, packfile_store_for_each_object_wrapper,
&data, flags, &pack_errors);
if (ret)
return ret;

return pack_errors ? -1 : 0;
}

static int add_promisor_object(const struct object_id *oid,
struct packed_git *pack,
uint32_t pos UNUSED,

View File

@ -343,6 +343,21 @@ int for_each_object_in_pack(struct packed_git *p,
int for_each_packed_object(struct repository *repo, each_packed_object_fn cb,
void *data, unsigned flags);

/*
* Iterate through all packed objects in the given packfile store and invoke
* the callback function for each of them. If an object info request is given,
* then the object info will be read for every individual object and passed to
* the callback as if `packfile_store_read_object_info()` was called for the
* object.
*
* The flags parameter is a combination of `odb_for_each_object_flags`.
*/
int packfile_store_for_each_object(struct packfile_store *store,
const struct object_info *request,
odb_for_each_object_cb cb,
void *cb_data,
unsigned flags);

/* A hook to report invalid files in pack directory */
#define PACKDIR_FILE_PACK 1
#define PACKDIR_FILE_IDX 2