diff --git a/object-file.c b/object-file.c index a651129426..65e730684b 100644 --- a/object-file.c +++ b/object-file.c @@ -1801,6 +1801,47 @@ int for_each_loose_object(struct object_database *odb, return 0; } +struct for_each_object_wrapper_data { + struct odb_source *source; + struct object_info *oi; + odb_for_each_object_cb cb; + void *cb_data; +}; + +static int for_each_object_wrapper_cb(const struct object_id *oid, + const char *path, + void *cb_data) +{ + struct for_each_object_wrapper_data *data = cb_data; + if (data->oi && + read_object_info_from_path(data->source, path, oid, data->oi, 0) < 0) + return -1; + return data->cb(oid, data->oi, data->cb_data); +} + +int odb_source_loose_for_each_object(struct odb_source *source, + struct object_info *oi, + odb_for_each_object_cb cb, + void *cb_data, + unsigned flags) +{ + struct for_each_object_wrapper_data data = { + .source = source, + .oi = oi, + .cb = cb, + .cb_data = cb_data, + }; + + /* There are no loose promisor objects, so we can return immediately. */ + if ((flags & ODB_FOR_EACH_OBJECT_PROMISOR_ONLY)) + return 0; + if ((flags & ODB_FOR_EACH_OBJECT_LOCAL_ONLY) && !source->local) + return 0; + + return for_each_loose_file_in_source(source, for_each_object_wrapper_cb, + NULL, NULL, &data); +} + static int append_loose_object(const struct object_id *oid, const char *path UNUSED, void *data) diff --git a/object-file.h b/object-file.h index 2acf19fb91..048b778531 100644 --- a/object-file.h +++ b/object-file.h @@ -137,6 +137,17 @@ int for_each_loose_object(struct object_database *odb, each_loose_object_fn, void *, enum odb_for_each_object_flags flags); +/* + * Iterate through all loose objects in the given object database source and + * invoke the callback function for each of them. If given, the object info + * will be populated with the object's data as if you had called + * `odb_source_loose_read_object_info()` on the object. + */ +int odb_source_loose_for_each_object(struct odb_source *source, + struct object_info *oi, + odb_for_each_object_cb cb, + void *cb_data, + unsigned flags); /** * format_object_header() is a thin wrapper around s xsnprintf() that diff --git a/odb.h b/odb.h index 74503addf1..f97f249580 100644 --- a/odb.h +++ b/odb.h @@ -463,6 +463,18 @@ enum odb_for_each_object_flags { ODB_FOR_EACH_OBJECT_SKIP_ON_DISK_KEPT_PACKS = (1<<4), }; +/* + * A callback function that can be used to iterate through objects. If given, + * the optional `oi` parameter will be populated the same as if you would call + * `odb_read_object_info()`. + * + * Returning a non-zero error code will cause iteration to abort. The error + * code will be propagated. + */ +typedef int (*odb_for_each_object_cb)(const struct object_id *oid, + struct object_info *oi, + void *cb_data); + enum { /* * By default, `odb_write_object()` does not actually write anything