diff options
author | Linus Torvalds <torvalds@g5.osdl.org> | 2005-07-03 21:01:11 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-07-03 21:01:11 -0700 |
commit | 671fe4bb20cf36b0f9de763b863425f5bea30c06 (patch) | |
tree | 4bdca3bd8333192d6fb8c98c82b6c74f70e6e0e9 | |
parent | 5736bef18c37e811f39bafb9895fee349fa7bbe6 (diff) | |
download | git-671fe4bb20cf36b0f9de763b863425f5bea30c06.tar.gz git-671fe4bb20cf36b0f9de763b863425f5bea30c06.tar.xz |
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.
-rw-r--r-- | rev-parse.c | 49 |
1 files changed, 49 insertions, 0 deletions
diff --git a/rev-parse.c b/rev-parse.c index 95da465f1..d62efdaf2 100644 --- a/rev-parse.c +++ b/rev-parse.c @@ -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; } |