aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Steinhardt <ps@pks.im>2026-03-20 08:07:38 +0100
committerJunio C Hamano <gitster@pobox.com>2026-03-20 13:16:42 -0700
commitab3ab1038dd38d2be62e3bacf39a3248929a7a98 (patch)
tree569657bfdc996d2b84ab4e3e1bbf493b6590d692
parent1a2842d1b1e91d5e068d231cf4df4e783bdf9205 (diff)
downloadgit-ab3ab1038dd38d2be62e3bacf39a3248929a7a98.tar.xz
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>
-rw-r--r--object-file.c38
-rw-r--r--object-file.h12
-rw-r--r--object-name.c27
3 files changed, 54 insertions, 23 deletions
diff --git a/object-file.c b/object-file.c
index 13732f324f..4f77ce0982 100644
--- a/object-file.c
+++ b/object-file.c
@@ -1952,6 +1952,44 @@ out:
return ret;
}
+struct find_abbrev_len_data {
+ const struct object_id *oid;
+ unsigned len;
+};
+
+static int find_abbrev_len_cb(const struct object_id *oid,
+ struct object_info *oi UNUSED,
+ void *cb_data)
+{
+ struct find_abbrev_len_data *data = cb_data;
+ unsigned len = oid_common_prefix_hexlen(oid, data->oid);
+ if (len != hash_algos[oid->algo].hexsz && len >= data->len)
+ data->len = len + 1;
+ return 0;
+}
+
+int odb_source_loose_find_abbrev_len(struct odb_source *source,
+ const struct object_id *oid,
+ unsigned min_len,
+ unsigned *out)
+{
+ struct odb_for_each_object_options opts = {
+ .prefix = oid,
+ .prefix_hex_len = min_len,
+ };
+ struct find_abbrev_len_data data = {
+ .oid = oid,
+ .len = min_len,
+ };
+ int ret;
+
+ ret = odb_source_loose_for_each_object(source, NULL, find_abbrev_len_cb,
+ &data, &opts);
+ *out = data.len;
+
+ return ret;
+}
+
static int append_loose_object(const struct object_id *oid,
const char *path UNUSED,
void *data)
diff --git a/object-file.h b/object-file.h
index f11ad58f6c..3686f182e4 100644
--- a/object-file.h
+++ b/object-file.h
@@ -146,6 +146,18 @@ int odb_source_loose_count_objects(struct odb_source *source,
enum odb_count_objects_flags flags,
unsigned long *out);
+/*
+ * Find the shortest unique prefix for the given object ID, where `min_len` is
+ * the minimum length that the prefix should have.
+ *
+ * Returns 0 on success, in which case the computed length will be written to
+ * `out`. Otherwise, a negative error code is returned.
+ */
+int odb_source_loose_find_abbrev_len(struct odb_source *source,
+ const struct object_id *oid,
+ unsigned min_len,
+ unsigned *out);
+
/**
* format_object_header() is a thin wrapper around s xsnprintf() that
* writes the initial "<type> <obj-len>" part of the loose object
diff --git a/object-name.c b/object-name.c
index 32e9c23e40..4e21dbfa97 100644
--- a/object-name.c
+++ b/object-name.c
@@ -598,28 +598,6 @@ static int extend_abbrev_len(const struct object_id *oid,
return 0;
}
-static int extend_abbrev_len_loose(const struct object_id *oid,
- struct object_info *oi UNUSED,
- void *cb_data)
-{
- struct min_abbrev_data *data = cb_data;
- extend_abbrev_len(oid, data);
- return 0;
-}
-
-static void find_abbrev_len_loose(struct min_abbrev_data *mad)
-{
- struct odb_for_each_object_options opts = {
- .prefix = mad->oid,
- .prefix_hex_len = mad->cur_len,
- };
- struct odb_source *source;
-
- for (source = mad->repo->objects->sources; source; source = source->next)
- odb_source_loose_for_each_object(source, NULL, extend_abbrev_len_loose,
- mad, &opts);
-}
-
static void find_abbrev_len_for_midx(struct multi_pack_index *m,
struct min_abbrev_data *mad)
{
@@ -772,7 +750,10 @@ int repo_find_unique_abbrev_r(struct repository *r, char *hex,
mad.oid = oid;
find_abbrev_len_packed(&mad);
- find_abbrev_len_loose(&mad);
+
+ odb_prepare_alternates(r->objects);
+ for (struct odb_source *s = r->objects->sources; s; s = s->next)
+ odb_source_loose_find_abbrev_len(s, mad.oid, mad.cur_len, &mad.cur_len);
hex[mad.cur_len] = 0;
return mad.cur_len;