aboutsummaryrefslogtreecommitdiffstats
path: root/rev-parse.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2005-07-03 21:01:11 -0700
committerLinus Torvalds <torvalds@g5.osdl.org>2005-07-03 21:01:11 -0700
commit671fe4bb20cf36b0f9de763b863425f5bea30c06 (patch)
tree4bdca3bd8333192d6fb8c98c82b6c74f70e6e0e9 /rev-parse.c
parent5736bef18c37e811f39bafb9895fee349fa7bbe6 (diff)
downloadgit-671fe4bb20cf36b0f9de763b863425f5bea30c06.tar.gz
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.
Diffstat (limited to 'rev-parse.c')
-rw-r--r--rev-parse.c49
1 files changed, 49 insertions, 0 deletions
diff --git a/rev-parse.c b/rev-parse.c
index 95da465f14..d62efdaf2d 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;
}