object-file: move logic to compute packed abbreviation length
Same as the preceding commit, move the logic that computes the minimum required prefix length to make a given object ID unique for the packfile store into a new function `packfile_store_find_abbrev_len()` that is part of "packfile.c". This prepares for making the logic fully generic via pluggable object databases. 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
6c2ede6e4abed754bb5891c2904212c05efcfb11
3 files changed
+128
-123
object-name.c
+12
-123
@@ -582,115 +582,6 @@ static unsigned msb(unsigned long val)
582
return r;
583
}
584
585
-struct min_abbrev_data {
586
- unsigned int init_len;
587
- unsigned int cur_len;
588
- struct repository *repo;
589
- const struct object_id *oid;
590
-};
591
-
592
-static int extend_abbrev_len(const struct object_id *oid,
593
- struct min_abbrev_data *mad)
594
-{
595
- unsigned len = oid_common_prefix_hexlen(oid, mad->oid);
596
- if (len != hash_algos[oid->algo].hexsz && len >= mad->cur_len)
597
- mad->cur_len = len + 1;
598
- return 0;
599
-}
600
-
601
-static void find_abbrev_len_for_midx(struct multi_pack_index *m,
602
- struct min_abbrev_data *mad)
603
-{
604
- for (; m; m = m->base_midx) {
605
- int match = 0;
606
- uint32_t num, first = 0;
607
- struct object_id oid;
608
- const struct object_id *mad_oid;
609
-
610
- if (!m->num_objects)
611
- continue;
612
-
613
- num = m->num_objects + m->num_objects_in_base;
614
- mad_oid = mad->oid;
615
- match = bsearch_one_midx(mad_oid, m, &first);
616
-
617
- /*
618
- * first is now the position in the packfile where we
619
- * would insert mad->hash if it does not exist (or the
620
- * position of mad->hash if it does exist). Hence, we
621
- * consider a maximum of two objects nearby for the
622
- * abbreviation length.
623
- */
624
- mad->init_len = 0;
625
- if (!match) {
626
- if (nth_midxed_object_oid(&oid, m, first))
627
- extend_abbrev_len(&oid, mad);
628
- } else if (first < num - 1) {
629
- if (nth_midxed_object_oid(&oid, m, first + 1))
630
- extend_abbrev_len(&oid, mad);
631
- }
632
- if (first > 0) {
633
- if (nth_midxed_object_oid(&oid, m, first - 1))
634
- extend_abbrev_len(&oid, mad);
635
- }
636
- mad->init_len = mad->cur_len;
637
- }
638
-}
639
-
640
-static void find_abbrev_len_for_pack(struct packed_git *p,
641
- struct min_abbrev_data *mad)
642
-{
643
- int match = 0;
644
- uint32_t num, first = 0;
645
- struct object_id oid;
646
- const struct object_id *mad_oid;
647
-
648
- if (p->multi_pack_index)
649
- return;
650
-
651
- if (open_pack_index(p) || !p->num_objects)
652
- return;
653
-
654
- num = p->num_objects;
655
- mad_oid = mad->oid;
656
- match = bsearch_pack(mad_oid, p, &first);
657
-
658
- /*
659
- * first is now the position in the packfile where we would insert
660
- * mad->hash if it does not exist (or the position of mad->hash if
661
- * it does exist). Hence, we consider a maximum of two objects
662
- * nearby for the abbreviation length.
663
- */
664
- mad->init_len = 0;
665
- if (!match) {
666
- if (!nth_packed_object_id(&oid, p, first))
667
- extend_abbrev_len(&oid, mad);
668
- } else if (first < num - 1) {
669
- if (!nth_packed_object_id(&oid, p, first + 1))
670
- extend_abbrev_len(&oid, mad);
671
- }
672
- if (first > 0) {
673
- if (!nth_packed_object_id(&oid, p, first - 1))
674
- extend_abbrev_len(&oid, mad);
675
- }
676
- mad->init_len = mad->cur_len;
677
-}
678
-
679
-static void find_abbrev_len_packed(struct min_abbrev_data *mad)
680
-{
681
- struct packed_git *p;
682
-
683
- odb_prepare_alternates(mad->repo->objects);
684
- for (struct odb_source *source = mad->repo->objects->sources; source; source = source->next) {
685
- struct multi_pack_index *m = get_multi_pack_index(source);
686
- if (m)
687
- find_abbrev_len_for_midx(m, mad);
688
- }
689
-
690
- repo_for_each_pack(mad->repo, p)
691
- find_abbrev_len_for_pack(p, mad);
692
-}
693
-
585
void strbuf_repo_add_unique_abbrev(struct strbuf *sb, struct repository *repo,
586
const struct object_id *oid, int abbrev_len)
587
{
@@ -707,14 +598,14 @@ void strbuf_add_unique_abbrev(struct strbuf *sb, const struct object_id *oid,
598
}
599
600
int repo_find_unique_abbrev_r(struct repository *r, char *hex,
710
- const struct object_id *oid, int len)
601
+ const struct object_id *oid, int min_len)
602
{
603
const struct git_hash_algo *algo =
604
oid->algo ? &hash_algos[oid->algo] : r->hash_algo;
714
- struct min_abbrev_data mad;
605
const unsigned hexsz = algo->hexsz;
606
+ unsigned len;
607
717
- if (len < 0) {
608
+ if (min_len < 0) {
609
unsigned long count;
610
611
if (odb_count_objects(r->objects, ODB_COUNT_OBJECTS_APPROXIMATE, &count) < 0)
@@ -738,25 +629,23 @@ int repo_find_unique_abbrev_r(struct repository *r, char *hex,
629
*/
630
if (len < FALLBACK_DEFAULT_ABBREV)
631
len = FALLBACK_DEFAULT_ABBREV;
632
+ } else {
633
+ len = min_len;
634
}
635
636
oid_to_hex_r(hex, oid);
637
if (len >= hexsz || !len)
638
return hexsz;
639
747
- mad.repo = r;
748
- mad.init_len = len;
749
- mad.cur_len = len;
750
- mad.oid = oid;
751
-
752
- find_abbrev_len_packed(&mad);
753
-
640
odb_prepare_alternates(r->objects);
755
- for (struct odb_source *s = r->objects->sources; s; s = s->next)
756
- odb_source_loose_find_abbrev_len(s, mad.oid, mad.cur_len, &mad.cur_len);
641
+ for (struct odb_source *s = r->objects->sources; s; s = s->next) {
642
+ struct odb_source_files *files = odb_source_files_downcast(s);
643
+ packfile_store_find_abbrev_len(files->packed, oid, len, &len);
644
+ odb_source_loose_find_abbrev_len(s, oid, len, &len);
645
+ }
646
758
- hex[mad.cur_len] = 0;
759
- return mad.cur_len;
647
+ hex[len] = 0;
648
+ return len;
649
}
650
651
const char *repo_find_unique_abbrev(struct repository *r,
packfile.c
+111
@@ -2597,6 +2597,117 @@ out:
2597
return ret;
2598
}
2599
2600
+static int extend_abbrev_len(const struct object_id *a,
2601
+ const struct object_id *b,
2602
+ unsigned *out)
2603
+{
2604
+ unsigned len = oid_common_prefix_hexlen(a, b);
2605
+ if (len != hash_algos[a->algo].hexsz && len >= *out)
2606
+ *out = len + 1;
2607
+ return 0;
2608
+}
2609
+
2610
+static void find_abbrev_len_for_midx(struct multi_pack_index *m,
2611
+ const struct object_id *oid,
2612
+ unsigned min_len,
2613
+ unsigned *out)
2614
+{
2615
+ unsigned len = min_len;
2616
+
2617
+ for (; m; m = m->base_midx) {
2618
+ int match = 0;
2619
+ uint32_t num, first = 0;
2620
+ struct object_id found_oid;
2621
+
2622
+ if (!m->num_objects)
2623
+ continue;
2624
+
2625
+ num = m->num_objects + m->num_objects_in_base;
2626
+ match = bsearch_one_midx(oid, m, &first);
2627
+
2628
+ /*
2629
+ * first is now the position in the packfile where we
2630
+ * would insert the object ID if it does not exist (or the
2631
+ * position of the object ID if it does exist). Hence, we
2632
+ * consider a maximum of two objects nearby for the
2633
+ * abbreviation length.
2634
+ */
2635
+
2636
+ if (!match) {
2637
+ if (nth_midxed_object_oid(&found_oid, m, first))
2638
+ extend_abbrev_len(&found_oid, oid, &len);
2639
+ } else if (first < num - 1) {
2640
+ if (nth_midxed_object_oid(&found_oid, m, first + 1))
2641
+ extend_abbrev_len(&found_oid, oid, &len);
2642
+ }
2643
+ if (first > 0) {
2644
+ if (nth_midxed_object_oid(&found_oid, m, first - 1))
2645
+ extend_abbrev_len(&found_oid, oid, &len);
2646
+ }
2647
+ }
2648
+
2649
+ *out = len;
2650
+}
2651
+
2652
+static void find_abbrev_len_for_pack(struct packed_git *p,
2653
+ const struct object_id *oid,
2654
+ unsigned min_len,
2655
+ unsigned *out)
2656
+{
2657
+ int match;
2658
+ uint32_t num, first = 0;
2659
+ struct object_id found_oid;
2660
+ unsigned len = min_len;
2661
+
2662
+ num = p->num_objects;
2663
+ match = bsearch_pack(oid, p, &first);
2664
+
2665
+ /*
2666
+ * first is now the position in the packfile where we would insert
2667
+ * the object ID if it does not exist (or the position of mad->hash if
2668
+ * it does exist). Hence, we consider a maximum of two objects
2669
+ * nearby for the abbreviation length.
2670
+ */
2671
+ if (!match) {
2672
+ if (!nth_packed_object_id(&found_oid, p, first))
2673
+ extend_abbrev_len(&found_oid, oid, &len);
2674
+ } else if (first < num - 1) {
2675
+ if (!nth_packed_object_id(&found_oid, p, first + 1))
2676
+ extend_abbrev_len(&found_oid, oid, &len);
2677
+ }
2678
+ if (first > 0) {
2679
+ if (!nth_packed_object_id(&found_oid, p, first - 1))
2680
+ extend_abbrev_len(&found_oid, oid, &len);
2681
+ }
2682
+
2683
+ *out = len;
2684
+}
2685
+
2686
+int packfile_store_find_abbrev_len(struct packfile_store *store,
2687
+ const struct object_id *oid,
2688
+ unsigned min_len,
2689
+ unsigned *out)
2690
+{
2691
+ struct packfile_list_entry *e;
2692
+ struct multi_pack_index *m;
2693
+
2694
+ m = get_multi_pack_index(store->source);
2695
+ if (m)
2696
+ find_abbrev_len_for_midx(m, oid, min_len, &min_len);
2697
+
2698
+ for (e = packfile_store_get_packs(store); e; e = e->next) {
2699
+ if (e->pack->multi_pack_index)
2700
+ continue;
2701
+ if (open_pack_index(e->pack) || !e->pack->num_objects)
2702
+ continue;
2703
+
2704
+ find_abbrev_len_for_pack(e->pack, oid, min_len, &min_len);
2705
+ }
2706
+
2707
+ *out = min_len;
2708
+ return 0;
2709
+}
2710
+
2711
struct add_promisor_object_data {
2712
struct repository *repo;
2713
struct oidset *set;
packfile.h
+5
@@ -369,6 +369,11 @@ int packfile_store_for_each_object(struct packfile_store *store,
369
void *cb_data,
370
const struct odb_for_each_object_options *opts);
371
372
+int packfile_store_find_abbrev_len(struct packfile_store *store,
373
+ const struct object_id *oid,
374
+ unsigned min_len,
375
+ unsigned *out);
376
+
377
/* A hook to report invalid files in pack directory */
378
#define PACKDIR_FILE_PACK 1
379
#define PACKDIR_FILE_IDX 2