]> git.ipfire.org Git - thirdparty/git.git/commitdiff
odb/source-packed: wire up `for_each_object()` callback
authorPatrick Steinhardt <ps@pks.im>
Wed, 17 Jun 2026 06:39:54 +0000 (08:39 +0200)
committerJunio C Hamano <gitster@pobox.com>
Wed, 17 Jun 2026 12:00:00 +0000 (05:00 -0700)
Move `packfile_store_for_each_object()` and its associated helpers from
"packfile.c" into "odb/source-packed.c" and wire it up as the
`for_each_object()` callback of the "packed" source.

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
odb/source-files.c
odb/source-packed.c
packfile.c
packfile.h

index 04b64006a544774860b860df8bb29a41b607a9cb..d997011531faf776c83efcaf3c1b000c1f6ff2a3 100644 (file)
@@ -916,8 +916,8 @@ 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, &opts);
+                       int ret = odb_source_for_each_object(&files->packed->base, &oi,
+                                                            batch_one_object_oi, &payload, &opts);
                        if (ret)
                                break;
                }
index 50675481e14caa76ad21343a123504b07a95691d..5e948054789a5350797d173cea1cdc226dec39a7 100644 (file)
@@ -4503,8 +4503,8 @@ static void add_objects_in_unpacked_packs(void)
                if (!source->local)
                        continue;
 
-               if (packfile_store_for_each_object(files->packed, &oi,
-                                                  add_object_in_unpacked_pack, NULL, &opts))
+               if (odb_source_for_each_object(&files->packed->base, &oi,
+                                              add_object_in_unpacked_pack, NULL, &opts))
                        die(_("cannot open pack index"));
        }
 }
index 9abe62bd5a278af0af4838c6da75d32a82aafce1..1e4038baf340a1e938e438809bca941eeef31b6d 100644 (file)
@@ -2016,8 +2016,8 @@ static void fill_oids_from_all_packs(struct write_commit_graph_context *ctx)
        odb_prepare_alternates(ctx->r->objects);
        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, &opts);
+               odb_source_for_each_object(&files->packed->base, &oi, add_packed_commits_oi,
+                                          ctx, &opts);
        }
 
        if (ctx->progress_done < ctx->approx_nr_objects)
index dff69d0e4e08c94c23709441e83dc8ef837cd2e1..c73a7e5f9096ad5ea496d6cc2ed2c1fb178869dc 100644 (file)
@@ -88,7 +88,7 @@ static int odb_source_files_for_each_object(struct odb_source *source,
                        return ret;
        }
 
-       ret = packfile_store_for_each_object(files->packed, request, cb, cb_data, opts);
+       ret = odb_source_for_each_object(&files->packed->base, request, cb, cb_data, opts);
        if (ret)
                return ret;
 
index 23d7149fe389eff8cfd7457adb5c0dfb456f58f1..a61c809c8c8fa64e58a4f0204110f56f85440273 100644 (file)
@@ -81,6 +81,263 @@ static int odb_source_packed_read_object_stream(struct odb_read_stream **out,
        return packfile_read_object_stream(out, oid, e.p, e.offset);
 }
 
+struct odb_source_packed_for_each_object_wrapper_data {
+       struct odb_source_packed *store;
+       const struct object_info *request;
+       odb_for_each_object_cb cb;
+       void *cb_data;
+};
+
+static int odb_source_packed_for_each_object_wrapper(const struct object_id *oid,
+                                                    struct packed_git *pack,
+                                                    uint32_t index_pos,
+                                                    void *cb_data)
+{
+       struct odb_source_packed_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_with_index_pos(pack, offset,
+                                                     &index_pos, &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);
+       }
+}
+
+static int match_hash(unsigned len, const unsigned char *a, const unsigned char *b)
+{
+       do {
+               if (*a != *b)
+                       return 0;
+               a++;
+               b++;
+               len -= 2;
+       } while (len > 1);
+       if (len)
+               if ((*a ^ *b) & 0xf0)
+                       return 0;
+       return 1;
+}
+
+static int for_each_prefixed_object_in_midx(
+       struct odb_source_packed *store,
+       struct multi_pack_index *m,
+       const struct odb_for_each_object_options *opts,
+       struct odb_source_packed_for_each_object_wrapper_data *data)
+{
+       int ret;
+
+       for (; m; m = m->base_midx) {
+               uint32_t num, i, first = 0;
+               int len = opts->prefix_hex_len > m->source->odb->repo->hash_algo->hexsz ?
+                       m->source->odb->repo->hash_algo->hexsz : opts->prefix_hex_len;
+
+               if (!m->num_objects)
+                       continue;
+
+               num = m->num_objects + m->num_objects_in_base;
+
+               bsearch_one_midx(opts->prefix, m, &first);
+
+               /*
+                * At this point, "first" is the location of the lowest
+                * object with an object name that could match "opts->prefix".
+                * See if we have 0, 1 or more objects that actually match(es).
+                */
+               for (i = first; i < num; i++) {
+                       const struct object_id *current = NULL;
+                       struct object_id oid;
+
+                       current = nth_midxed_object_oid(&oid, m, i);
+
+                       if (!match_hash(len, opts->prefix->hash, current->hash))
+                               break;
+
+                       if (data->request) {
+                               struct object_info oi = *data->request;
+
+                               ret = odb_source_read_object_info(&store->base, current,
+                                                                 &oi, 0);
+                               if (ret)
+                                       goto out;
+
+                               ret = data->cb(&oid, &oi, data->cb_data);
+                               if (ret)
+                                       goto out;
+                       } else {
+                               ret = data->cb(&oid, NULL, data->cb_data);
+                               if (ret)
+                                       goto out;
+                       }
+               }
+       }
+
+       ret = 0;
+
+out:
+       return ret;
+}
+
+static int for_each_prefixed_object_in_pack(
+       struct odb_source_packed *store,
+       struct packed_git *p,
+       const struct odb_for_each_object_options *opts,
+       struct odb_source_packed_for_each_object_wrapper_data *data)
+{
+       uint32_t num, i, first = 0;
+       int len = opts->prefix_hex_len > p->repo->hash_algo->hexsz ?
+               p->repo->hash_algo->hexsz : opts->prefix_hex_len;
+       int ret;
+
+       num = p->num_objects;
+       bsearch_pack(opts->prefix, p, &first);
+
+       /*
+        * At this point, "first" is the location of the lowest object
+        * with an object name that could match "bin_pfx".  See if we have
+        * 0, 1 or more objects that actually match(es).
+        */
+       for (i = first; i < num; i++) {
+               struct object_id oid;
+
+               nth_packed_object_id(&oid, p, i);
+               if (!match_hash(len, opts->prefix->hash, oid.hash))
+                       break;
+
+               if (data->request) {
+                       struct object_info oi = *data->request;
+
+                       ret = odb_source_read_object_info(&store->base, &oid, &oi, 0);
+                       if (ret)
+                               goto out;
+
+                       ret = data->cb(&oid, &oi, data->cb_data);
+                       if (ret)
+                               goto out;
+               } else {
+                       ret = data->cb(&oid, NULL, data->cb_data);
+                       if (ret)
+                               goto out;
+               }
+       }
+
+       ret = 0;
+
+out:
+       return ret;
+}
+
+static int odb_source_packed_for_each_prefixed_object(
+       struct odb_source_packed *store,
+       const struct odb_for_each_object_options *opts,
+       struct odb_source_packed_for_each_object_wrapper_data *data)
+{
+       struct packfile_list_entry *e;
+       struct multi_pack_index *m;
+       bool pack_errors = false;
+       int ret;
+
+       if (opts->flags)
+               BUG("flags unsupported");
+
+       store->skip_mru_updates = true;
+
+       m = get_multi_pack_index(&store->files->base);
+       if (m) {
+               ret = for_each_prefixed_object_in_midx(store, m, opts, data);
+               if (ret)
+                       goto out;
+       }
+
+       for (e = packfile_store_get_packs(store); e; e = e->next) {
+               if (e->pack->multi_pack_index)
+                       continue;
+
+               if (open_pack_index(e->pack)) {
+                       pack_errors = true;
+                       continue;
+               }
+
+               if (!e->pack->num_objects)
+                       continue;
+
+               ret = for_each_prefixed_object_in_pack(store, e->pack, opts, data);
+               if (ret)
+                       goto out;
+       }
+
+       ret = 0;
+
+out:
+       store->skip_mru_updates = false;
+       if (!ret && pack_errors)
+               ret = -1;
+       return ret;
+}
+
+static int odb_source_packed_for_each_object(struct odb_source *source,
+                                            const struct object_info *request,
+                                            odb_for_each_object_cb cb,
+                                            void *cb_data,
+                                            const struct odb_for_each_object_options *opts)
+{
+       struct odb_source_packed *packed = odb_source_packed_downcast(source);
+       struct odb_source_packed_for_each_object_wrapper_data data = {
+               .store = packed,
+               .request = request,
+               .cb = cb,
+               .cb_data = cb_data,
+       };
+       struct packfile_list_entry *e;
+       int pack_errors = 0, ret;
+
+       if (opts->prefix)
+               return odb_source_packed_for_each_prefixed_object(packed, opts, &data);
+
+       packed->skip_mru_updates = true;
+
+       for (e = packfile_store_get_packs(packed); e; e = e->next) {
+               struct packed_git *p = e->pack;
+
+               if ((opts->flags & ODB_FOR_EACH_OBJECT_LOCAL_ONLY) && !p->pack_local)
+                       continue;
+               if ((opts->flags & ODB_FOR_EACH_OBJECT_PROMISOR_ONLY) &&
+                   !p->pack_promisor)
+                       continue;
+               if ((opts->flags & ODB_FOR_EACH_OBJECT_SKIP_IN_CORE_KEPT_PACKS) &&
+                   p->pack_keep_in_core)
+                       continue;
+               if ((opts->flags & ODB_FOR_EACH_OBJECT_SKIP_ON_DISK_KEPT_PACKS) &&
+                   p->pack_keep)
+                       continue;
+               if (open_pack_index(p)) {
+                       pack_errors = 1;
+                       continue;
+               }
+
+               ret = for_each_object_in_pack(p, odb_source_packed_for_each_object_wrapper,
+                                             &data, opts->flags);
+               if (ret)
+                       goto out;
+       }
+
+       ret = 0;
+
+out:
+       packed->skip_mru_updates = false;
+
+       if (!ret && pack_errors)
+               ret = -1;
+       return ret;
+}
+
 void (*report_garbage)(unsigned seen_bits, const char *path);
 
 static void report_helper(const struct string_list *list,
@@ -291,6 +548,7 @@ struct odb_source_packed *odb_source_packed_new(struct odb_source_files *parent)
        packed->base.reprepare = odb_source_packed_reprepare;
        packed->base.read_object_info = odb_source_packed_read_object_info;
        packed->base.read_object_stream = odb_source_packed_read_object_stream;
+       packed->base.for_each_object = odb_source_packed_for_each_object;
 
        if (!is_absolute_path(parent->base.path))
                chdir_notify_register(NULL, odb_source_packed_reparent, packed);
index 42c84397eb266731795ab693b685a91f603c64e7..b8d6054c16aa726b5acc48118767d67676c0d049 100644 (file)
@@ -1362,8 +1362,8 @@ static void add_delta_base_cache(struct packed_git *p, off_t base_offset,
        hashmap_add(&delta_base_cache, &ent->ent);
 }
 
-static int packed_object_info_with_index_pos(struct packed_git *p, off_t obj_offset,
-                                            uint32_t *maybe_index_pos, struct object_info *oi)
+int packed_object_info_with_index_pos(struct packed_git *p, off_t obj_offset,
+                                     uint32_t *maybe_index_pos, struct object_info *oi)
 {
        struct pack_window *w_curs = NULL;
        size_t size;
@@ -2068,262 +2068,6 @@ int for_each_object_in_pack(struct packed_git *p,
        return r;
 }
 
-struct odb_source_packed_for_each_object_wrapper_data {
-       struct odb_source_packed *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 odb_source_packed_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_with_index_pos(pack, offset,
-                                                     &index_pos, &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);
-       }
-}
-
-static int match_hash(unsigned len, const unsigned char *a, const unsigned char *b)
-{
-       do {
-               if (*a != *b)
-                       return 0;
-               a++;
-               b++;
-               len -= 2;
-       } while (len > 1);
-       if (len)
-               if ((*a ^ *b) & 0xf0)
-                       return 0;
-       return 1;
-}
-
-static int for_each_prefixed_object_in_midx(
-       struct odb_source_packed *store,
-       struct multi_pack_index *m,
-       const struct odb_for_each_object_options *opts,
-       struct odb_source_packed_for_each_object_wrapper_data *data)
-{
-       int ret;
-
-       for (; m; m = m->base_midx) {
-               uint32_t num, i, first = 0;
-               int len = opts->prefix_hex_len > m->source->odb->repo->hash_algo->hexsz ?
-                       m->source->odb->repo->hash_algo->hexsz : opts->prefix_hex_len;
-
-               if (!m->num_objects)
-                       continue;
-
-               num = m->num_objects + m->num_objects_in_base;
-
-               bsearch_one_midx(opts->prefix, m, &first);
-
-               /*
-                * At this point, "first" is the location of the lowest
-                * object with an object name that could match "opts->prefix".
-                * See if we have 0, 1 or more objects that actually match(es).
-                */
-               for (i = first; i < num; i++) {
-                       const struct object_id *current = NULL;
-                       struct object_id oid;
-
-                       current = nth_midxed_object_oid(&oid, m, i);
-
-                       if (!match_hash(len, opts->prefix->hash, current->hash))
-                               break;
-
-                       if (data->request) {
-                               struct object_info oi = *data->request;
-
-                               ret = odb_source_read_object_info(&store->base, current,
-                                                                 &oi, 0);
-                               if (ret)
-                                       goto out;
-
-                               ret = data->cb(&oid, &oi, data->cb_data);
-                               if (ret)
-                                       goto out;
-                       } else {
-                               ret = data->cb(&oid, NULL, data->cb_data);
-                               if (ret)
-                                       goto out;
-                       }
-               }
-       }
-
-       ret = 0;
-
-out:
-       return ret;
-}
-
-static int for_each_prefixed_object_in_pack(
-       struct odb_source_packed *store,
-       struct packed_git *p,
-       const struct odb_for_each_object_options *opts,
-       struct odb_source_packed_for_each_object_wrapper_data *data)
-{
-       uint32_t num, i, first = 0;
-       int len = opts->prefix_hex_len > p->repo->hash_algo->hexsz ?
-               p->repo->hash_algo->hexsz : opts->prefix_hex_len;
-       int ret;
-
-       num = p->num_objects;
-       bsearch_pack(opts->prefix, p, &first);
-
-       /*
-        * At this point, "first" is the location of the lowest object
-        * with an object name that could match "bin_pfx".  See if we have
-        * 0, 1 or more objects that actually match(es).
-        */
-       for (i = first; i < num; i++) {
-               struct object_id oid;
-
-               nth_packed_object_id(&oid, p, i);
-               if (!match_hash(len, opts->prefix->hash, oid.hash))
-                       break;
-
-               if (data->request) {
-                       struct object_info oi = *data->request;
-
-                       ret = odb_source_read_object_info(&store->base, &oid, &oi, 0);
-                       if (ret)
-                               goto out;
-
-                       ret = data->cb(&oid, &oi, data->cb_data);
-                       if (ret)
-                               goto out;
-               } else {
-                       ret = data->cb(&oid, NULL, data->cb_data);
-                       if (ret)
-                               goto out;
-               }
-       }
-
-       ret = 0;
-
-out:
-       return ret;
-}
-
-static int packfile_store_for_each_prefixed_object(
-       struct odb_source_packed *store,
-       const struct odb_for_each_object_options *opts,
-       struct odb_source_packed_for_each_object_wrapper_data *data)
-{
-       struct packfile_list_entry *e;
-       struct multi_pack_index *m;
-       bool pack_errors = false;
-       int ret;
-
-       if (opts->flags)
-               BUG("flags unsupported");
-
-       store->skip_mru_updates = true;
-
-       m = get_multi_pack_index(&store->files->base);
-       if (m) {
-               ret = for_each_prefixed_object_in_midx(store, m, opts, data);
-               if (ret)
-                       goto out;
-       }
-
-       for (e = packfile_store_get_packs(store); e; e = e->next) {
-               if (e->pack->multi_pack_index)
-                       continue;
-
-               if (open_pack_index(e->pack)) {
-                       pack_errors = true;
-                       continue;
-               }
-
-               if (!e->pack->num_objects)
-                       continue;
-
-               ret = for_each_prefixed_object_in_pack(store, e->pack, opts, data);
-               if (ret)
-                       goto out;
-       }
-
-       ret = 0;
-
-out:
-       store->skip_mru_updates = false;
-       if (!ret && pack_errors)
-               ret = -1;
-       return ret;
-}
-
-int packfile_store_for_each_object(struct odb_source_packed *store,
-                                  const struct object_info *request,
-                                  odb_for_each_object_cb cb,
-                                  void *cb_data,
-                                  const struct odb_for_each_object_options *opts)
-{
-       struct odb_source_packed_for_each_object_wrapper_data data = {
-               .store = store,
-               .request = request,
-               .cb = cb,
-               .cb_data = cb_data,
-       };
-       struct packfile_list_entry *e;
-       int pack_errors = 0, ret;
-
-       if (opts->prefix)
-               return packfile_store_for_each_prefixed_object(store, opts, &data);
-
-       store->skip_mru_updates = true;
-
-       for (e = packfile_store_get_packs(store); e; e = e->next) {
-               struct packed_git *p = e->pack;
-
-               if ((opts->flags & ODB_FOR_EACH_OBJECT_LOCAL_ONLY) && !p->pack_local)
-                       continue;
-               if ((opts->flags & ODB_FOR_EACH_OBJECT_PROMISOR_ONLY) &&
-                   !p->pack_promisor)
-                       continue;
-               if ((opts->flags & ODB_FOR_EACH_OBJECT_SKIP_IN_CORE_KEPT_PACKS) &&
-                   p->pack_keep_in_core)
-                       continue;
-               if ((opts->flags & ODB_FOR_EACH_OBJECT_SKIP_ON_DISK_KEPT_PACKS) &&
-                   p->pack_keep)
-                       continue;
-               if (open_pack_index(p)) {
-                       pack_errors = 1;
-                       continue;
-               }
-
-               ret = for_each_object_in_pack(p, packfile_store_for_each_object_wrapper,
-                                             &data, opts->flags);
-               if (ret)
-                       goto out;
-       }
-
-       ret = 0;
-
-out:
-       store->skip_mru_updates = false;
-
-       if (!ret && pack_errors)
-               ret = -1;
-       return ret;
-}
-
 static int extend_abbrev_len(const struct object_id *a,
                             const struct object_id *b,
                             unsigned *out)
index dd97684e7098ddd6e15c138864c8021ba3f3f4ae..0097de0b274ff9446f47d114153264fee8d68572 100644 (file)
@@ -227,21 +227,6 @@ int for_each_object_in_pack(struct packed_git *p,
                            each_packed_object_fn, void *data,
                            enum odb_for_each_object_flags 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 odb_source_packed *store,
-                                  const struct object_info *request,
-                                  odb_for_each_object_cb cb,
-                                  void *cb_data,
-                                  const struct odb_for_each_object_options *opts);
-
 int packfile_store_find_abbrev_len(struct odb_source_packed *store,
                                   const struct object_id *oid,
                                   unsigned min_len,
@@ -354,6 +339,8 @@ extern int do_check_packed_object_crc;
  */
 int packed_object_info(struct packed_git *pack,
                       off_t offset, struct object_info *);
+int packed_object_info_with_index_pos(struct packed_git *p, off_t obj_offset,
+                                     uint32_t *maybe_index_pos, struct object_info *oi);
 
 void mark_bad_packed_object(struct packed_git *, const struct object_id *);
 const struct packed_git *has_packed_and_bad(struct repository *, const struct object_id *);