sha1_name.c: refactor find_short_packed_object()

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@pobox.com>
This commit is contained in:
Junio C Hamano 2012-06-18 13:10:38 -07:00
parent 1b27c2f01a
commit f703e6ea5e

View File

@ -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;
for (p = packed_git; p && found < 2; p = p->next)
found = unique_in_pack(len, match, p, &found_sha1, found);
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;
}
}
}
}
if (found == 1)
hashcpy(sha1, found_sha1);
return found;