git-rev-parse: support show sha1 names for pack entries

This is actually subtly wrong.  If a short match is found in the object
directory, but would _also_ match another SHA1 ID in a pack (or it shows
in one pack but not another), we'll never have done the pack lookup, and
we think it's unique.

I can't find it in myself to care.  You really want to use enough of a
SHA1 that there is never any ambiguity.
This commit is contained in:
Linus Torvalds 2005-07-03 21:01:11 -07:00
parent 5736bef18c
commit 671fe4bb20

View File

@ -131,8 +131,57 @@ static int find_short_object_filename(int len, const char *name, unsigned char *
return 0;
}
static int match_sha(unsigned len, const unsigned char *a, const unsigned char *b)
{
do {
if (*a != *b)
return 0;
a++;
b++;
len -= 2;
} while (len > 1);
if (len)
if ((*a ^ *b) & 0xf0)
return 0;
return 1;
}
static int find_short_packed_object(int len, const unsigned char *match, unsigned char *sha1)
{
struct packed_git *p;
prepare_packed_git();
for (p = packed_git; p; p = p->next) {
unsigned num = num_packed_objects(p);
unsigned first = 0, last = num;
while (first < last) {
unsigned mid = (first + last) / 2;
unsigned char now[20];
int cmp;
nth_packed_object_sha1(p, mid, now);
cmp = memcmp(match, now, 20);
if (!cmp) {
first = mid;
break;
}
if (cmp > 0) {
first = mid+1;
continue;
}
last = mid;
}
if (first < num) {
unsigned char now[20], next[20];
nth_packed_object_sha1(p, first, now);
if (match_sha(len, match, now)) {
if (nth_packed_object_sha1(p, first+1, next) || !match_sha(len, match, next)) {
memcpy(sha1, now, 20);
return 1;
}
}
}
}
return 0;
}