]> git.ipfire.org Git - thirdparty/git.git/commitdiff
object-name: move logic to iterate through packed prefixed objects
authorPatrick Steinhardt <ps@pks.im>
Fri, 20 Mar 2026 07:07:31 +0000 (08:07 +0100)
committerJunio C Hamano <gitster@pobox.com>
Fri, 20 Mar 2026 20:16:42 +0000 (13:16 -0700)
Similar to the preceding commit, move the logic to iterate through
objects that have a given prefix into "packfile.c".

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
object-name.c
packfile.c

index 929a68dbd0d32bebe6239cf8016867839a0d47be..ff0de06ff9bd874c9006067cbe37b1a7928f67a9 100644 (file)
@@ -100,8 +100,6 @@ static void update_candidates(struct disambiguate_state *ds, const struct object
        /* otherwise, current can be discarded and candidate is still good */
 }
 
-static int match_hash(unsigned, const unsigned char *, const unsigned char *);
-
 static int match_prefix(const struct object_id *oid, struct object_info *oi UNUSED, void *arg)
 {
        struct disambiguate_state *ds = arg;
@@ -122,103 +120,25 @@ static void find_short_object_filename(struct disambiguate_state *ds)
                odb_source_loose_for_each_object(source, NULL, match_prefix, ds, &opts);
 }
 
-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 void unique_in_midx(struct multi_pack_index *m,
-                          struct disambiguate_state *ds)
-{
-       for (; m; m = m->base_midx) {
-               uint32_t num, i, first = 0;
-               const struct object_id *current = NULL;
-               int len = ds->len > ds->repo->hash_algo->hexsz ?
-                       ds->repo->hash_algo->hexsz : ds->len;
-
-               if (!m->num_objects)
-                       continue;
-
-               num = m->num_objects + m->num_objects_in_base;
-
-               bsearch_one_midx(&ds->bin_pfx, m, &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 && !ds->ambiguous; i++) {
-                       struct object_id oid;
-                       current = nth_midxed_object_oid(&oid, m, i);
-                       if (!match_hash(len, ds->bin_pfx.hash, current->hash))
-                               break;
-                       update_candidates(ds, current);
-               }
-       }
-}
-
-static void unique_in_pack(struct packed_git *p,
-                          struct disambiguate_state *ds)
-{
-       uint32_t num, i, first = 0;
-       int len = ds->len > ds->repo->hash_algo->hexsz ?
-               ds->repo->hash_algo->hexsz : ds->len;
-
-       if (p->multi_pack_index)
-               return;
-
-       if (open_pack_index(p) || !p->num_objects)
-               return;
-
-       num = p->num_objects;
-       bsearch_pack(&ds->bin_pfx, 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 && !ds->ambiguous; i++) {
-               struct object_id oid;
-               nth_packed_object_id(&oid, p, i);
-               if (!match_hash(len, ds->bin_pfx.hash, oid.hash))
-                       break;
-               update_candidates(ds, &oid);
-       }
-}
-
 static void find_short_packed_object(struct disambiguate_state *ds)
 {
+       struct odb_for_each_object_options opts = {
+               .prefix = &ds->bin_pfx,
+               .prefix_hex_len = ds->len,
+       };
        struct odb_source *source;
-       struct packed_git *p;
 
        /* Skip, unless oids from the storage hash algorithm are wanted */
        if (ds->bin_pfx.algo && (&hash_algos[ds->bin_pfx.algo] != ds->repo->hash_algo))
                return;
 
        odb_prepare_alternates(ds->repo->objects);
-       for (source = ds->repo->objects->sources; source && !ds->ambiguous; source = source->next) {
-               struct multi_pack_index *m = get_multi_pack_index(source);
-               if (m)
-                       unique_in_midx(m, ds);
-       }
+       for (source = ds->repo->objects->sources; source; source = source->next) {
+               struct odb_source_files *files = odb_source_files_downcast(source);
 
-       repo_for_each_pack(ds->repo, p) {
+               packfile_store_for_each_object(files->packed, NULL, match_prefix, ds, &opts);
                if (ds->ambiguous)
                        break;
-               unique_in_pack(p, ds);
        }
 }
 
index a6f3d2035d44fdd40d490c91c0cf4761c4e1355f..2539a371c13e9a11e0c6508a677666a17d8b3624 100644 (file)
@@ -2371,6 +2371,177 @@ static int packfile_store_for_each_object_wrapper(const struct object_id *oid,
        }
 }
 
+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 packfile_store *store,
+       struct multi_pack_index *m,
+       const struct odb_for_each_object_options *opts,
+       struct packfile_store_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 = packfile_store_read_object_info(store, 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 packfile_store *store,
+       struct packed_git *p,
+       const struct odb_for_each_object_options *opts,
+       struct packfile_store_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 = packfile_store_read_object_info(store, &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 packfile_store *store,
+       const struct odb_for_each_object_options *opts,
+       struct packfile_store_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->source);
+       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 packfile_store *store,
                                   const struct object_info *request,
                                   odb_for_each_object_cb cb,
@@ -2386,6 +2557,9 @@ int packfile_store_for_each_object(struct packfile_store *store,
        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) {