Skip to content

Commit 1a2842d

Browse files
pks-tgitster
authored andcommitted
object-name: simplify computing common prefixes
The function `extend_abbrev_len()` computes the length of common hex characters between two object IDs. This is done by: - Making the caller provide the `hex` string for the needle object ID. - Comparing every hex position of the haystack object ID with `get_hex_char_from_oid()`. Turning the binary representation into hex first is roundabout though: we can simply compare the binary representation and give some special attention to the final nibble. Introduce a new function `oid_common_prefix_hexlen()` that does exactly this and refactor the code to use the new function. This allows us to drop the `struct min_abbrev_data::hex` field. Furthermore, this function will be used in by some other callsites in subsequent commits. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent 67f47ea commit 1a2842d

3 files changed

Lines changed: 24 additions & 20 deletions

File tree

hash.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,3 +317,21 @@ const struct git_hash_algo *unsafe_hash_algo(const struct git_hash_algo *algop)
317317
/* Otherwise use the default one. */
318318
return algop;
319319
}
320+
321+
unsigned oid_common_prefix_hexlen(const struct object_id *a,
322+
const struct object_id *b)
323+
{
324+
unsigned rawsz = hash_algos[a->algo].rawsz;
325+
326+
for (unsigned i = 0; i < rawsz; i++) {
327+
if (a->hash[i] == b->hash[i])
328+
continue;
329+
330+
if ((a->hash[i] ^ b->hash[i]) & 0xf0)
331+
return i * 2;
332+
else
333+
return i * 2 + 1;
334+
}
335+
336+
return rawsz * 2;
337+
}

hash.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,9 @@ static inline int oideq(const struct object_id *oid1, const struct object_id *oi
396396
return !memcmp(oid1->hash, oid2->hash, GIT_MAX_RAWSZ);
397397
}
398398

399+
unsigned oid_common_prefix_hexlen(const struct object_id *a,
400+
const struct object_id *b);
401+
399402
static inline void oidcpy(struct object_id *dst, const struct object_id *src)
400403
{
401404
memcpy(dst->hash, src->hash, GIT_MAX_RAWSZ);

object-name.c

Lines changed: 3 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -585,32 +585,16 @@ static unsigned msb(unsigned long val)
585585
struct min_abbrev_data {
586586
unsigned int init_len;
587587
unsigned int cur_len;
588-
char *hex;
589588
struct repository *repo;
590589
const struct object_id *oid;
591590
};
592591

593-
static inline char get_hex_char_from_oid(const struct object_id *oid,
594-
unsigned int pos)
595-
{
596-
static const char hex[] = "0123456789abcdef";
597-
598-
if ((pos & 1) == 0)
599-
return hex[oid->hash[pos >> 1] >> 4];
600-
else
601-
return hex[oid->hash[pos >> 1] & 0xf];
602-
}
603-
604592
static int extend_abbrev_len(const struct object_id *oid,
605593
struct min_abbrev_data *mad)
606594
{
607-
unsigned int i = mad->init_len;
608-
while (mad->hex[i] && mad->hex[i] == get_hex_char_from_oid(oid, i))
609-
i++;
610-
611-
if (mad->hex[i] && i >= mad->cur_len)
612-
mad->cur_len = i + 1;
613-
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;
614598
return 0;
615599
}
616600

@@ -785,7 +769,6 @@ int repo_find_unique_abbrev_r(struct repository *r, char *hex,
785769
mad.repo = r;
786770
mad.init_len = len;
787771
mad.cur_len = len;
788-
mad.hex = hex;
789772
mad.oid = oid;
790773

791774
find_abbrev_len_packed(&mad);

0 commit comments

Comments
 (0)