aboutsummaryrefslogtreecommitdiff
path: root/rev-parse.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2005-07-03 20:27:06 -0700
committerLinus Torvalds <torvalds@g5.osdl.org>2005-07-03 20:27:06 -0700
commit5736bef18c37e811f39bafb9895fee349fa7bbe6 (patch)
tree9a080a9bbb0a85ac5b6a5568f48df33fbacb6540 /rev-parse.c
parent5f3de58ff85c49620ae2a1722d8d4d37c881a054 (diff)
downloadgit-5736bef18c37e811f39bafb9895fee349fa7bbe6.tar.gz
git-5736bef18c37e811f39bafb9895fee349fa7bbe6.tar.xz
Make git-rev-parse support cogito-style "short hex names"
Currently only for unpacked objects, but the infrastructure is there to do it for packed objects too.
Diffstat (limited to 'rev-parse.c')
-rw-r--r--rev-parse.c79
1 files changed, 76 insertions, 3 deletions
diff --git a/rev-parse.c b/rev-parse.c
index c096dc45e..95da465f1 100644
--- a/rev-parse.c
+++ b/rev-parse.c
@@ -102,13 +102,84 @@ static int get_parent(char *name, unsigned char *result, int idx)
return -1;
}
+static int find_short_object_filename(int len, const char *name, unsigned char *sha1)
+{
+ static char dirname[PATH_MAX];
+ char hex[40];
+ DIR *dir;
+ int found;
+
+ snprintf(dirname, sizeof(dirname), "%s/%.2s", get_object_directory(), name);
+ dir = opendir(dirname);
+ sprintf(hex, "%.2s", name);
+ found = 0;
+ if (dir) {
+ struct dirent *de;
+ while ((de = readdir(dir)) != NULL) {
+ if (strlen(de->d_name) != 38)
+ continue;
+ if (memcmp(de->d_name, name + 2, len-2))
+ continue;
+ memcpy(hex + 2, de->d_name, 38);
+ if (++found > 1)
+ break;
+ }
+ closedir(dir);
+ }
+ if (found == 1)
+ return get_sha1_hex(hex, sha1) == 0;
+ return 0;
+}
+
+static int find_short_packed_object(int len, const unsigned char *match, unsigned char *sha1)
+{
+ return 0;
+}
+
+static int get_short_sha1(char *name, unsigned char *sha1)
+{
+ int i;
+ char canonical[40];
+ unsigned char res[20];
+
+ memset(res, 0, 20);
+ memset(canonical, 'x', 40);
+ for (i = 0;;i++) {
+ unsigned char c = name[i];
+ unsigned char val;
+ if (!c || i > 40)
+ break;
+ if (c >= '0' && c <= '9')
+ val = c - '0';
+ else if (c >= 'a' && c <= 'f')
+ val = c - 'a' + 10;
+ else if (c >= 'A' && c <='F') {
+ val = c - 'A' + 10;
+ c -= 'A' - 'a';
+ }
+ else
+ return -1;
+ canonical[i] = c;
+ if (!(i & 1))
+ val <<= 4;
+ res[i >> 1] |= val;
+ }
+ if (i < 4)
+ return -1;
+ if (find_short_object_filename(i, canonical, sha1))
+ return 0;
+ if (find_short_packed_object(i, res, sha1))
+ return 0;
+ return -1;
+}
+
/*
* This is like "get_sha1()", except it allows "sha1 expressions",
* notably "xyz^" for "parent of xyz"
*/
static int get_extended_sha1(char *name, unsigned char *sha1)
{
- int parent;
+ int parent, ret;
int len = strlen(name);
parent = 1;
@@ -117,14 +188,16 @@ static int get_extended_sha1(char *name, unsigned char *sha1)
len--;
}
if (len > 1 && name[len-1] == '^') {
- int ret;
name[len-1] = 0;
ret = get_parent(name, sha1, parent);
name[len-1] = '^';
if (!ret)
return 0;
}
- return get_sha1(name, sha1);
+ ret = get_sha1(name, sha1);
+ if (!ret)
+ return 0;
+ return get_short_sha1(name, sha1);
}
static void show_default(void)