]> git.ipfire.org Git - thirdparty/git.git/commitdiff
object-file: introduce function to iterate through objects
authorPatrick Steinhardt <ps@pks.im>
Thu, 15 Jan 2026 11:04:33 +0000 (12:04 +0100)
committerJunio C Hamano <gitster@pobox.com>
Thu, 15 Jan 2026 13:50:28 +0000 (05:50 -0800)
We have multiple divergent interfaces to iterate through objects of a
specific backend:

  - `for_each_loose_object()` yields all loose objects.

  - `for_each_packed_object()` (somewhat obviously) yields all packed
    objects.

These functions have different function signatures, which makes it hard
to create a common abstraction layer that covers both of these.

Introduce a new function `odb_source_loose_for_each_object()` to plug
this gap. This function doesn't take any data specific to loose objects,
but instead it accepts a `struct object_info` that will be populated the
exact same as if `odb_source_loose_read_object()` was called.

The benefit of this new interface is that we can continue to pass
backend-specific data, as `struct object_info` contains a union for
these exact use cases. This will allow us to unify how we iterate
through objects across both loose and packed objects in a subsequent
commit.

The `for_each_loose_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>
object-file.c
object-file.h
odb.h

index a651129426992c93207ddf9c27c3346c48a4032e..65e730684b374fcfce7de2f712090deec7baf1a3 100644 (file)
@@ -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)
index 2acf19fb91ab4121b080de572202123530ea3379..048b778531157ffc3deab7d6f47e8f12993765d7 100644 (file)
@@ -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 74503addf1462caf7b07088c1270f6d95a51a9cd..f97f249580e08ac67f64f2a1efb6bc768fe3dab6 100644 (file)
--- 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