]> git.ipfire.org Git - thirdparty/git.git/commitdiff
odb: introduce `struct odb_for_each_object_options`
authorPatrick Steinhardt <ps@pks.im>
Fri, 20 Mar 2026 07:07:29 +0000 (08:07 +0100)
committerJunio C Hamano <gitster@pobox.com>
Fri, 20 Mar 2026 20:16:41 +0000 (13:16 -0700)
The `odb_for_each_object()` function only accepts a bitset of flags. In
a subsequent commit we'll want to change object iteration to also
support iterating over only those objects that have a specific prefix.
While we could of course add the prefix to the function signature, or
alternatively introduce a new function, both of these options don't
really seem to be that sensible.

Instead, introduce a new `struct odb_for_each_object_options` that can
be passed to a new `odb_for_each_object_ext()` function. Splice through
the options structure into the respective object database sources.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
builtin/cat-file.c
builtin/pack-objects.c
commit-graph.c
object-file.c
object-file.h
odb.c
odb.h
odb/source-files.c
odb/source.h
packfile.c
packfile.h

index b6f12f41d6070a9733588d8f2f258a65c5903da7..cd13a3a89f185176b1ffdd3e3d5b913285d9fc15 100644 (file)
@@ -848,6 +848,9 @@ static void batch_each_object(struct batch_options *opt,
                .callback = callback,
                .payload = _payload,
        };
+       struct odb_for_each_object_options opts = {
+               .flags = flags,
+       };
        struct bitmap_index *bitmap = NULL;
        struct odb_source *source;
 
@@ -860,7 +863,7 @@ static void batch_each_object(struct batch_options *opt,
        odb_prepare_alternates(the_repository->objects);
        for (source = the_repository->objects->sources; source; source = source->next) {
                int ret = odb_source_loose_for_each_object(source, NULL, batch_one_object_oi,
-                                                          &payload, flags);
+                                                          &payload, &opts);
                if (ret)
                        break;
        }
@@ -884,7 +887,7 @@ static void batch_each_object(struct batch_options *opt,
                for (source = the_repository->objects->sources; source; source = source->next) {
                        struct odb_source_files *files = odb_source_files_downcast(source);
                        int ret = packfile_store_for_each_object(files->packed, &oi,
-                                                                batch_one_object_oi, &payload, flags);
+                                                                batch_one_object_oi, &payload, &opts);
                        if (ret)
                                break;
                }
index cd013c0b68a6a3ecd8bd5453b6eb3db3f02b08d8..3bb57ff1837290dcab3b266845c1a0312b761707 100644 (file)
@@ -4344,6 +4344,12 @@ static void add_objects_in_unpacked_packs(void)
 {
        struct odb_source *source;
        time_t mtime;
+       struct odb_for_each_object_options opts = {
+               .flags = ODB_FOR_EACH_OBJECT_PACK_ORDER |
+                        ODB_FOR_EACH_OBJECT_LOCAL_ONLY |
+                        ODB_FOR_EACH_OBJECT_SKIP_IN_CORE_KEPT_PACKS |
+                        ODB_FOR_EACH_OBJECT_SKIP_ON_DISK_KEPT_PACKS,
+       };
        struct object_info oi = {
                .mtimep = &mtime,
        };
@@ -4356,11 +4362,7 @@ static void add_objects_in_unpacked_packs(void)
                        continue;
 
                if (packfile_store_for_each_object(files->packed, &oi,
-                                                  add_object_in_unpacked_pack, NULL,
-                                                  ODB_FOR_EACH_OBJECT_PACK_ORDER |
-                                                  ODB_FOR_EACH_OBJECT_LOCAL_ONLY |
-                                                  ODB_FOR_EACH_OBJECT_SKIP_IN_CORE_KEPT_PACKS |
-                                                  ODB_FOR_EACH_OBJECT_SKIP_ON_DISK_KEPT_PACKS))
+                                                  add_object_in_unpacked_pack, NULL, &opts))
                        die(_("cannot open pack index"));
        }
 }
index c03000333044042cdb87cc32987faba2d018dbc0..df4b4a125e977bff4fa8743336b01a5e689b7b3a 100644 (file)
@@ -1969,6 +1969,9 @@ static void fill_oids_from_all_packs(struct write_commit_graph_context *ctx)
 {
        struct odb_source *source;
        enum object_type type;
+       struct odb_for_each_object_options opts = {
+               .flags = ODB_FOR_EACH_OBJECT_PACK_ORDER,
+       };
        struct object_info oi = {
                .typep = &type,
        };
@@ -1983,7 +1986,7 @@ static void fill_oids_from_all_packs(struct write_commit_graph_context *ctx)
        for (source = ctx->r->objects->sources; source; source = source->next) {
                struct odb_source_files *files = odb_source_files_downcast(source);
                packfile_store_for_each_object(files->packed, &oi, add_packed_commits_oi,
-                                              ctx, ODB_FOR_EACH_OBJECT_PACK_ORDER);
+                                              ctx, &opts);
        }
 
        if (ctx->progress_done < ctx->approx_nr_objects)
index 9764c8dd06797f9a07642341bf1d7dc75e101e62..56cbb27ab908a80c7391e5da009391417eb7b9cd 100644 (file)
@@ -1849,7 +1849,7 @@ int odb_source_loose_for_each_object(struct odb_source *source,
                                     const struct object_info *request,
                                     odb_for_each_object_cb cb,
                                     void *cb_data,
-                                    unsigned flags)
+                                    const struct odb_for_each_object_options *opts)
 {
        struct for_each_object_wrapper_data data = {
                .source = source,
@@ -1859,9 +1859,9 @@ int odb_source_loose_for_each_object(struct odb_source *source,
        };
 
        /* There are no loose promisor objects, so we can return immediately. */
-       if ((flags & ODB_FOR_EACH_OBJECT_PROMISOR_ONLY))
+       if ((opts->flags & ODB_FOR_EACH_OBJECT_PROMISOR_ONLY))
                return 0;
-       if ((flags & ODB_FOR_EACH_OBJECT_LOCAL_ONLY) && !source->local)
+       if ((opts->flags & ODB_FOR_EACH_OBJECT_LOCAL_ONLY) && !source->local)
                return 0;
 
        return for_each_loose_file_in_source(source, for_each_object_wrapper_cb,
@@ -1914,9 +1914,10 @@ int odb_source_loose_count_objects(struct odb_source *source,
                *out = count * 256;
                ret = 0;
        } else {
+               struct odb_for_each_object_options opts = { 0 };
                *out = 0;
                ret = odb_source_loose_for_each_object(source, NULL, count_loose_object,
-                                                      out, NULL);
+                                                      out, &opts);
        }
 
 out:
index f8d8805a18cc8cb940347c7190448e38bd7d8158..46dfa7b632b334d556cdbe795f508b10032f03a9 100644 (file)
@@ -137,7 +137,7 @@ int odb_source_loose_for_each_object(struct odb_source *source,
                                     const struct object_info *request,
                                     odb_for_each_object_cb cb,
                                     void *cb_data,
-                                    unsigned flags);
+                                    const struct odb_for_each_object_options *opts);
 
 /*
  * Count the number of loose objects in this source.
diff --git a/odb.c b/odb.c
index 350e23f3c0798d35bbb1f378b23d45ca6bcfa2bc..3019957b8747a93d5c1562f31f2e4e6ffccafe17 100644 (file)
--- a/odb.c
+++ b/odb.c
@@ -896,20 +896,20 @@ int odb_freshen_object(struct object_database *odb,
        return 0;
 }
 
-int odb_for_each_object(struct object_database *odb,
-                       const struct object_info *request,
-                       odb_for_each_object_cb cb,
-                       void *cb_data,
-                       unsigned flags)
+int odb_for_each_object_ext(struct object_database *odb,
+                           const struct object_info *request,
+                           odb_for_each_object_cb cb,
+                           void *cb_data,
+                           const struct odb_for_each_object_options *opts)
 {
        int ret;
 
        odb_prepare_alternates(odb);
        for (struct odb_source *source = odb->sources; source; source = source->next) {
-               if (flags & ODB_FOR_EACH_OBJECT_LOCAL_ONLY && !source->local)
+               if (opts->flags & ODB_FOR_EACH_OBJECT_LOCAL_ONLY && !source->local)
                        continue;
 
-               ret = odb_source_for_each_object(source, request, cb, cb_data, flags);
+               ret = odb_source_for_each_object(source, request, cb, cb_data, opts);
                if (ret)
                        return ret;
        }
@@ -917,6 +917,18 @@ int odb_for_each_object(struct object_database *odb,
        return 0;
 }
 
+int odb_for_each_object(struct object_database *odb,
+                       const struct object_info *request,
+                       odb_for_each_object_cb cb,
+                       void *cb_data,
+                       unsigned flags)
+{
+       struct odb_for_each_object_options opts = {
+               .flags = flags,
+       };
+       return odb_for_each_object_ext(odb, request, cb, cb_data, &opts);
+}
+
 int odb_count_objects(struct object_database *odb,
                      enum odb_count_objects_flags flags,
                      unsigned long *out)
diff --git a/odb.h b/odb.h
index 9aee260105ae5473ecc955b6f2d7102685bed190..a19a8bb50d86e78a85fa2c811464f2fef0b58813 100644 (file)
--- a/odb.h
+++ b/odb.h
@@ -481,6 +481,15 @@ typedef int (*odb_for_each_object_cb)(const struct object_id *oid,
                                      struct object_info *oi,
                                      void *cb_data);
 
+/*
+ * Options that can be passed to `odb_for_each_object()` and its
+ * backend-specific implementations.
+ */
+struct odb_for_each_object_options {
+       /* A bitfield of `odb_for_each_object_flags`. */
+       enum odb_for_each_object_flags flags;
+};
+
 /*
  * Iterate through all objects contained in the object database. Note that
  * objects may be iterated over multiple times in case they are either stored
@@ -495,6 +504,13 @@ typedef int (*odb_for_each_object_cb)(const struct object_id *oid,
  * Returns 0 on success, a negative error code in case a failure occurred, or
  * an arbitrary non-zero error code returned by the callback itself.
  */
+int odb_for_each_object_ext(struct object_database *odb,
+                           const struct object_info *request,
+                           odb_for_each_object_cb cb,
+                           void *cb_data,
+                           const struct odb_for_each_object_options *opts);
+
+/* Same as `odb_for_each_object_ext()` with `opts.flags` set to the given flags. */
 int odb_for_each_object(struct object_database *odb,
                        const struct object_info *request,
                        odb_for_each_object_cb cb,
index c08d8993e378a0c9459d4616bd3e459c0f7bca57..e90bb689bb01e64b1336c6b99c33da3c31e2f0a7 100644 (file)
@@ -75,18 +75,18 @@ static int odb_source_files_for_each_object(struct odb_source *source,
                                            const struct object_info *request,
                                            odb_for_each_object_cb cb,
                                            void *cb_data,
-                                           unsigned flags)
+                                           const struct odb_for_each_object_options *opts)
 {
        struct odb_source_files *files = odb_source_files_downcast(source);
        int ret;
 
-       if (!(flags & ODB_FOR_EACH_OBJECT_PROMISOR_ONLY)) {
-               ret = odb_source_loose_for_each_object(source, request, cb, cb_data, flags);
+       if (!(opts->flags & ODB_FOR_EACH_OBJECT_PROMISOR_ONLY)) {
+               ret = odb_source_loose_for_each_object(source, request, cb, cb_data, opts);
                if (ret)
                        return ret;
        }
 
-       ret = packfile_store_for_each_object(files->packed, request, cb, cb_data, flags);
+       ret = packfile_store_for_each_object(files->packed, request, cb, cb_data, opts);
        if (ret)
                return ret;
 
index 96c906e7a1b350ee0e8688edeaf6ce66892812f5..ee5d6ed530d519a15d20382593691e1371772258 100644 (file)
@@ -140,7 +140,7 @@ struct odb_source {
                               const struct object_info *request,
                               odb_for_each_object_cb cb,
                               void *cb_data,
-                              unsigned flags);
+                              const struct odb_for_each_object_options *opts);
 
        /*
         * This callback is expected to count objects in the given object
@@ -343,9 +343,9 @@ static inline int odb_source_for_each_object(struct odb_source *source,
                                             const struct object_info *request,
                                             odb_for_each_object_cb cb,
                                             void *cb_data,
-                                            unsigned flags)
+                                            const struct odb_for_each_object_options *opts)
 {
-       return source->for_each_object(source, request, cb, cb_data, flags);
+       return source->for_each_object(source, request, cb, cb_data, opts);
 }
 
 /*
index d4de9f3ffe831eda9a2dead1516524a2647010fb..a6f3d2035d44fdd40d490c91c0cf4761c4e1355f 100644 (file)
@@ -2375,7 +2375,7 @@ 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)
+                                  const struct odb_for_each_object_options *opts)
 {
        struct packfile_store_for_each_object_wrapper_data data = {
                .store = store,
@@ -2391,15 +2391,15 @@ int packfile_store_for_each_object(struct packfile_store *store,
        for (e = packfile_store_get_packs(store); e; e = e->next) {
                struct packed_git *p = e->pack;
 
-               if ((flags & ODB_FOR_EACH_OBJECT_LOCAL_ONLY) && !p->pack_local)
+               if ((opts->flags & ODB_FOR_EACH_OBJECT_LOCAL_ONLY) && !p->pack_local)
                        continue;
-               if ((flags & ODB_FOR_EACH_OBJECT_PROMISOR_ONLY) &&
+               if ((opts->flags & ODB_FOR_EACH_OBJECT_PROMISOR_ONLY) &&
                    !p->pack_promisor)
                        continue;
-               if ((flags & ODB_FOR_EACH_OBJECT_SKIP_IN_CORE_KEPT_PACKS) &&
+               if ((opts->flags & ODB_FOR_EACH_OBJECT_SKIP_IN_CORE_KEPT_PACKS) &&
                    p->pack_keep_in_core)
                        continue;
-               if ((flags & ODB_FOR_EACH_OBJECT_SKIP_ON_DISK_KEPT_PACKS) &&
+               if ((opts->flags & ODB_FOR_EACH_OBJECT_SKIP_ON_DISK_KEPT_PACKS) &&
                    p->pack_keep)
                        continue;
                if (open_pack_index(p)) {
@@ -2408,7 +2408,7 @@ int packfile_store_for_each_object(struct packfile_store *store,
                }
 
                ret = for_each_object_in_pack(p, packfile_store_for_each_object_wrapper,
-                                             &data, flags);
+                                             &data, opts->flags);
                if (ret)
                        goto out;
        }
index a16ec3950d2507ef76896866c988b9a75eb35792..fa41dfda3893276d43375914d2ff543f051516b7 100644 (file)
@@ -367,7 +367,7 @@ 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);
+                                  const struct odb_for_each_object_options *opts);
 
 /* A hook to report invalid files in pack directory */
 #define PACKDIR_FILE_PACK 1