Skip to content

Commit

Permalink
git-rev-parse: support show sha1 names for pack entries
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Linus Torvalds committed Jul 4, 2005
1 parent 5736bef commit 671fe4b
Showing 1 changed file with 49 additions and 0 deletions.
49 changes: 49 additions & 0 deletions rev-parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down

0 comments on commit 671fe4b

Please sign in to comment.