object-name: move logic to compute loose abbreviation length

The function `repo_find_unique_abbrev_r()` takes as input an object ID as well as a minimum object ID length and returns the minimum required prefix to make the object ID unique. The logic that computes the abbreviation length for loose objects is deeply tied to the loose object storage format. As such, it would fail in case a different object storage format was used. Prepare for making this logic generic to the backend by moving the logic into a new `odb_source_loose_find_abbrev_len()` function that is part of "object-file.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 ab3ab1038dd38d2be62e3bacf39a3248929a7a98
3 files changed +54 -23
object-file.c
+38
@@ -1952,6 +1952,44 @@ out:
1952 return ret;
1953 }
1954
1955 +struct find_abbrev_len_data {
1956 + const struct object_id *oid;
1957 + unsigned len;
1958 +};
1959 +
1960 +static int find_abbrev_len_cb(const struct object_id *oid,
1961 + struct object_info *oi UNUSED,
1962 + void *cb_data)
1963 +{
1964 + struct find_abbrev_len_data *data = cb_data;
1965 + unsigned len = oid_common_prefix_hexlen(oid, data->oid);
1966 + if (len != hash_algos[oid->algo].hexsz && len >= data->len)
1967 + data->len = len + 1;
1968 + return 0;
1969 +}
1970 +
1971 +int odb_source_loose_find_abbrev_len(struct odb_source *source,
1972 + const struct object_id *oid,
1973 + unsigned min_len,
1974 + unsigned *out)
1975 +{
1976 + struct odb_for_each_object_options opts = {
1977 + .prefix = oid,
1978 + .prefix_hex_len = min_len,
1979 + };
1980 + struct find_abbrev_len_data data = {
1981 + .oid = oid,
1982 + .len = min_len,
1983 + };
1984 + int ret;
1985 +
1986 + ret = odb_source_loose_for_each_object(source, NULL, find_abbrev_len_cb,
1987 + &data, &opts);
1988 + *out = data.len;
1989 +
1990 + return ret;
1991 +}
1992 +
1993 static int append_loose_object(const struct object_id *oid,
1994 const char *path UNUSED,
1995 void *data)
object-file.h
+12
@@ -146,6 +146,18 @@ int odb_source_loose_count_objects(struct odb_source *source,
146 enum odb_count_objects_flags flags,
147 unsigned long *out);
148
149 +/*
150 + * Find the shortest unique prefix for the given object ID, where `min_len` is
151 + * the minimum length that the prefix should have.
152 + *
153 + * Returns 0 on success, in which case the computed length will be written to
154 + * `out`. Otherwise, a negative error code is returned.
155 + */
156 +int odb_source_loose_find_abbrev_len(struct odb_source *source,
157 + const struct object_id *oid,
158 + unsigned min_len,
159 + unsigned *out);
160 +
161 /**
162 * format_object_header() is a thin wrapper around s xsnprintf() that
163 * writes the initial "<type> <obj-len>" part of the loose object
object-name.c
+4 -23
@@ -598,28 +598,6 @@ static int extend_abbrev_len(const struct object_id *oid,
598 return 0;
599 }
600
601 -static int extend_abbrev_len_loose(const struct object_id *oid,
602 - struct object_info *oi UNUSED,
603 - void *cb_data)
604 -{
605 - struct min_abbrev_data *data = cb_data;
606 - extend_abbrev_len(oid, data);
607 - return 0;
608 -}
609 -
610 -static void find_abbrev_len_loose(struct min_abbrev_data *mad)
611 -{
612 - struct odb_for_each_object_options opts = {
613 - .prefix = mad->oid,
614 - .prefix_hex_len = mad->cur_len,
615 - };
616 - struct odb_source *source;
617 -
618 - for (source = mad->repo->objects->sources; source; source = source->next)
619 - odb_source_loose_for_each_object(source, NULL, extend_abbrev_len_loose,
620 - mad, &opts);
621 -}
622 -
601 static void find_abbrev_len_for_midx(struct multi_pack_index *m,
602 struct min_abbrev_data *mad)
603 {
@@ -772,7 +750,10 @@ int repo_find_unique_abbrev_r(struct repository *r, char *hex,
750 mad.oid = oid;
751
752 find_abbrev_len_packed(&mad);
775 - find_abbrev_len_loose(&mad);
753 +
754 + 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);
757
758 hex[mad.cur_len] = 0;
759 return mad.cur_len;