From 671fe4bb20cf36b0f9de763b863425f5bea30c06 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 3 Jul 2005 21:01:11 -0700 Subject: [PATCH] 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. --- rev-parse.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) 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; } -- 2.26.2