Extract the logic to find object(s) that match a given prefix inside a single pack into a separate helper function, and give it a bit more comment. Signed-off-by: Junio C Hamano <gitster@xxxxxxxxx> --- sha1_name.c | 103 +++++++++++++++++++++++++++++++++--------------------------- 1 file changed, 56 insertions(+), 47 deletions(-) diff --git a/sha1_name.c b/sha1_name.c index 5224f39..e03992c 100644 --- a/sha1_name.c +++ b/sha1_name.c @@ -78,6 +78,59 @@ static int match_sha(unsigned len, const unsigned char *a, const unsigned char * return 1; } +static int unique_in_pack(int len, + const unsigned char *match, + struct packed_git *p, + const unsigned char **found_sha1, + int seen_so_far) +{ + uint32_t num, last, i, first = 0; + const unsigned char *current = NULL; + + open_pack_index(p); + num = p->num_objects; + last = num; + while (first < last) { + uint32_t mid = (first + last) / 2; + const unsigned char *current; + int cmp; + + current = nth_packed_object_sha1(p, mid); + cmp = hashcmp(match, current); + if (!cmp) { + first = mid; + break; + } + if (cmp > 0) { + first = mid+1; + continue; + } + last = mid; + } + + /* + * At this point, "first" is the location of the lowest object + * with an object name that could match "match". See if we have + * 0, 1 or more objects that actually match(es). + */ + for (i = first; i < num; i++) { + current = nth_packed_object_sha1(p, first); + if (!match_sha(len, match, current)) + break; + + /* current matches */ + if (!seen_so_far) { + *found_sha1 = current; + seen_so_far++; + } else if (seen_so_far) { + /* is it the same as the one previously found elsewhere? */ + if (hashcmp(*found_sha1, current)) + return 2; /* definitely not unique */ + } + } + return seen_so_far; +} + static int find_short_packed_object(int len, const unsigned char *match, unsigned char *sha1) { struct packed_git *p; @@ -85,53 +138,9 @@ static int find_short_packed_object(int len, const unsigned char *match, unsigne int found = 0; prepare_packed_git(); - for (p = packed_git; p && found < 2; p = p->next) { - uint32_t num, last; - uint32_t first = 0; - open_pack_index(p); - num = p->num_objects; - last = num; - while (first < last) { - uint32_t mid = (first + last) / 2; - const unsigned char *current; - int cmp; - - current = nth_packed_object_sha1(p, mid); - cmp = hashcmp(match, current); - if (!cmp) { - first = mid; - break; - } - if (cmp > 0) { - first = mid+1; - continue; - } - last = mid; - } - if (first < num) { - const unsigned char *current, *next; - current = nth_packed_object_sha1(p, first); - if (match_sha(len, match, current)) { - next = nth_packed_object_sha1(p, first+1); - if (!next|| !match_sha(len, match, next)) { - /* unique within this pack */ - if (!found) { - found_sha1 = current; - found++; - } - else if (hashcmp(found_sha1, current)) { - found = 2; - break; - } - } - else { - /* not even unique within this pack */ - found = 2; - break; - } - } - } - } + for (p = packed_git; p && found < 2; p = p->next) + found = unique_in_pack(len, match, p, &found_sha1, found); + if (found == 1) hashcpy(sha1, found_sha1); return found; -- 1.7.11 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html