object-name: move logic to iterate through packed prefixed objects
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>
Patrick Steinhardt committed
Mar 20, 2026 at 08:07 UTC
e30bff8f8402f0f147a08fe00b75e24f293fa870
2 files changed
+181
-87
object-name.c
+7
-87
@@ -100,8 +100,6 @@ static void update_candidates(struct disambiguate_state *ds, const struct object
100
/* otherwise, current can be discarded and candidate is still good */
101
}
102
103
-static int match_hash(unsigned, const unsigned char *, const unsigned char *);
104
-
103
static int match_prefix(const struct object_id *oid, struct object_info *oi UNUSED, void *arg)
104
{
105
struct disambiguate_state *ds = arg;
@@ -122,103 +120,25 @@ static void find_short_object_filename(struct disambiguate_state *ds)
120
odb_source_loose_for_each_object(source, NULL, match_prefix, ds, &opts);
121
}
122
125
-static int match_hash(unsigned len, const unsigned char *a, const unsigned char *b)
126
-{
127
- do {
128
- if (*a != *b)
129
- return 0;
130
- a++;
131
- b++;
132
- len -= 2;
133
- } while (len > 1);
134
- if (len)
135
- if ((*a ^ *b) & 0xf0)
136
- return 0;
137
- return 1;
138
-}
139
-
140
-static void unique_in_midx(struct multi_pack_index *m,
141
- struct disambiguate_state *ds)
142
-{
143
- for (; m; m = m->base_midx) {
144
- uint32_t num, i, first = 0;
145
- const struct object_id *current = NULL;
146
- int len = ds->len > ds->repo->hash_algo->hexsz ?
147
- ds->repo->hash_algo->hexsz : ds->len;
148
-
149
- if (!m->num_objects)
150
- continue;
151
-
152
- num = m->num_objects + m->num_objects_in_base;
153
-
154
- bsearch_one_midx(&ds->bin_pfx, m, &first);
155
-
156
- /*
157
- * At this point, "first" is the location of the lowest
158
- * object with an object name that could match
159
- * "bin_pfx". See if we have 0, 1 or more objects that
160
- * actually match(es).
161
- */
162
- for (i = first; i < num && !ds->ambiguous; i++) {
163
- struct object_id oid;
164
- current = nth_midxed_object_oid(&oid, m, i);
165
- if (!match_hash(len, ds->bin_pfx.hash, current->hash))
166
- break;
167
- update_candidates(ds, current);
168
- }
169
- }
170
-}
171
-
172
-static void unique_in_pack(struct packed_git *p,
173
- struct disambiguate_state *ds)
174
-{
175
- uint32_t num, i, first = 0;
176
- int len = ds->len > ds->repo->hash_algo->hexsz ?
177
- ds->repo->hash_algo->hexsz : ds->len;
178
-
179
- if (p->multi_pack_index)
180
- return;
181
-
182
- if (open_pack_index(p) || !p->num_objects)
183
- return;
184
-
185
- num = p->num_objects;
186
- bsearch_pack(&ds->bin_pfx, p, &first);
187
-
188
- /*
189
- * At this point, "first" is the location of the lowest object
190
- * with an object name that could match "bin_pfx". See if we have
191
- * 0, 1 or more objects that actually match(es).
192
- */
193
- for (i = first; i < num && !ds->ambiguous; i++) {
194
- struct object_id oid;
195
- nth_packed_object_id(&oid, p, i);
196
- if (!match_hash(len, ds->bin_pfx.hash, oid.hash))
197
- break;
198
- update_candidates(ds, &oid);
199
- }
200
-}
201
-
123
static void find_short_packed_object(struct disambiguate_state *ds)
124
{
125
+ struct odb_for_each_object_options opts = {
126
+ .prefix = &ds->bin_pfx,
127
+ .prefix_hex_len = ds->len,
128
+ };
129
struct odb_source *source;
205
- struct packed_git *p;
130
131
/* Skip, unless oids from the storage hash algorithm are wanted */
132
if (ds->bin_pfx.algo && (&hash_algos[ds->bin_pfx.algo] != ds->repo->hash_algo))
133
return;
134
135
odb_prepare_alternates(ds->repo->objects);
212
- for (source = ds->repo->objects->sources; source && !ds->ambiguous; source = source->next) {
213
- struct multi_pack_index *m = get_multi_pack_index(source);
214
- if (m)
215
- unique_in_midx(m, ds);
216
- }
136
+ for (source = ds->repo->objects->sources; source; source = source->next) {
137
+ struct odb_source_files *files = odb_source_files_downcast(source);
138
218
- repo_for_each_pack(ds->repo, p) {
139
+ packfile_store_for_each_object(files->packed, NULL, match_prefix, ds, &opts);
140
if (ds->ambiguous)
141
break;
221
- unique_in_pack(p, ds);
142
}
143
}
144
packfile.c
+174
@@ -2371,6 +2371,177 @@ static int packfile_store_for_each_object_wrapper(const struct object_id *oid,
2371
}
2372
}
2373
2374
+static int match_hash(unsigned len, const unsigned char *a, const unsigned char *b)
2375
+{
2376
+ do {
2377
+ if (*a != *b)
2378
+ return 0;
2379
+ a++;
2380
+ b++;
2381
+ len -= 2;
2382
+ } while (len > 1);
2383
+ if (len)
2384
+ if ((*a ^ *b) & 0xf0)
2385
+ return 0;
2386
+ return 1;
2387
+}
2388
+
2389
+static int for_each_prefixed_object_in_midx(
2390
+ struct packfile_store *store,
2391
+ struct multi_pack_index *m,
2392
+ const struct odb_for_each_object_options *opts,
2393
+ struct packfile_store_for_each_object_wrapper_data *data)
2394
+{
2395
+ int ret;
2396
+
2397
+ for (; m; m = m->base_midx) {
2398
+ uint32_t num, i, first = 0;
2399
+ int len = opts->prefix_hex_len > m->source->odb->repo->hash_algo->hexsz ?
2400
+ m->source->odb->repo->hash_algo->hexsz : opts->prefix_hex_len;
2401
+
2402
+ if (!m->num_objects)
2403
+ continue;
2404
+
2405
+ num = m->num_objects + m->num_objects_in_base;
2406
+
2407
+ bsearch_one_midx(opts->prefix, m, &first);
2408
+
2409
+ /*
2410
+ * At this point, "first" is the location of the lowest
2411
+ * object with an object name that could match "opts->prefix".
2412
+ * See if we have 0, 1 or more objects that actually match(es).
2413
+ */
2414
+ for (i = first; i < num; i++) {
2415
+ const struct object_id *current = NULL;
2416
+ struct object_id oid;
2417
+
2418
+ current = nth_midxed_object_oid(&oid, m, i);
2419
+
2420
+ if (!match_hash(len, opts->prefix->hash, current->hash))
2421
+ break;
2422
+
2423
+ if (data->request) {
2424
+ struct object_info oi = *data->request;
2425
+
2426
+ ret = packfile_store_read_object_info(store, current,
2427
+ &oi, 0);
2428
+ if (ret)
2429
+ goto out;
2430
+
2431
+ ret = data->cb(&oid, &oi, data->cb_data);
2432
+ if (ret)
2433
+ goto out;
2434
+ } else {
2435
+ ret = data->cb(&oid, NULL, data->cb_data);
2436
+ if (ret)
2437
+ goto out;
2438
+ }
2439
+ }
2440
+ }
2441
+
2442
+ ret = 0;
2443
+
2444
+out:
2445
+ return ret;
2446
+}
2447
+
2448
+static int for_each_prefixed_object_in_pack(
2449
+ struct packfile_store *store,
2450
+ struct packed_git *p,
2451
+ const struct odb_for_each_object_options *opts,
2452
+ struct packfile_store_for_each_object_wrapper_data *data)
2453
+{
2454
+ uint32_t num, i, first = 0;
2455
+ int len = opts->prefix_hex_len > p->repo->hash_algo->hexsz ?
2456
+ p->repo->hash_algo->hexsz : opts->prefix_hex_len;
2457
+ int ret;
2458
+
2459
+ num = p->num_objects;
2460
+ bsearch_pack(opts->prefix, p, &first);
2461
+
2462
+ /*
2463
+ * At this point, "first" is the location of the lowest object
2464
+ * with an object name that could match "bin_pfx". See if we have
2465
+ * 0, 1 or more objects that actually match(es).
2466
+ */
2467
+ for (i = first; i < num; i++) {
2468
+ struct object_id oid;
2469
+
2470
+ nth_packed_object_id(&oid, p, i);
2471
+ if (!match_hash(len, opts->prefix->hash, oid.hash))
2472
+ break;
2473
+
2474
+ if (data->request) {
2475
+ struct object_info oi = *data->request;
2476
+
2477
+ ret = packfile_store_read_object_info(store, &oid, &oi, 0);
2478
+ if (ret)
2479
+ goto out;
2480
+
2481
+ ret = data->cb(&oid, &oi, data->cb_data);
2482
+ if (ret)
2483
+ goto out;
2484
+ } else {
2485
+ ret = data->cb(&oid, NULL, data->cb_data);
2486
+ if (ret)
2487
+ goto out;
2488
+ }
2489
+ }
2490
+
2491
+ ret = 0;
2492
+
2493
+out:
2494
+ return ret;
2495
+}
2496
+
2497
+static int packfile_store_for_each_prefixed_object(
2498
+ struct packfile_store *store,
2499
+ const struct odb_for_each_object_options *opts,
2500
+ struct packfile_store_for_each_object_wrapper_data *data)
2501
+{
2502
+ struct packfile_list_entry *e;
2503
+ struct multi_pack_index *m;
2504
+ bool pack_errors = false;
2505
+ int ret;
2506
+
2507
+ if (opts->flags)
2508
+ BUG("flags unsupported");
2509
+
2510
+ store->skip_mru_updates = true;
2511
+
2512
+ m = get_multi_pack_index(store->source);
2513
+ if (m) {
2514
+ ret = for_each_prefixed_object_in_midx(store, m, opts, data);
2515
+ if (ret)
2516
+ goto out;
2517
+ }
2518
+
2519
+ for (e = packfile_store_get_packs(store); e; e = e->next) {
2520
+ if (e->pack->multi_pack_index)
2521
+ continue;
2522
+
2523
+ if (open_pack_index(e->pack)) {
2524
+ pack_errors = true;
2525
+ continue;
2526
+ }
2527
+
2528
+ if (!e->pack->num_objects)
2529
+ continue;
2530
+
2531
+ ret = for_each_prefixed_object_in_pack(store, e->pack, opts, data);
2532
+ if (ret)
2533
+ goto out;
2534
+ }
2535
+
2536
+ ret = 0;
2537
+
2538
+out:
2539
+ store->skip_mru_updates = false;
2540
+ if (!ret && pack_errors)
2541
+ ret = -1;
2542
+ return ret;
2543
+}
2544
+
2545
int packfile_store_for_each_object(struct packfile_store *store,
2546
const struct object_info *request,
2547
odb_for_each_object_cb cb,
@@ -2386,6 +2557,9 @@ int packfile_store_for_each_object(struct packfile_store *store,
2557
struct packfile_list_entry *e;
2558
int pack_errors = 0, ret;
2559
2560
+ if (opts->prefix)
2561
+ return packfile_store_for_each_prefixed_object(store, opts, &data);
2562
+
2563
store->skip_mru_updates = true;
2564
2565
for (e = packfile_store_get_packs(store); e; e = e->next) {