aboutsummaryrefslogtreecommitdiff
path: root/sha1_file.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-05-01 18:13:16 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-05-01 18:13:16 -0700
commit35ad33823e90fb166a6480cdc9195051535e9788 (patch)
treef74537054bb06e921350e893bf445179f1c368af /sha1_file.c
parent3c249c950649a37f2871a8b193f01a0640a20aef (diff)
downloadgit-35ad33823e90fb166a6480cdc9195051535e9788.tar.gz
git-35ad33823e90fb166a6480cdc9195051535e9788.tar.xz
Add "look up parent" logic for the simple names.
It uses the jit syntax, at least for now. 0-xxxx is the first parent of xxxx, while 1-xxxx is the second, and so on. You can use just "-xxxx" for the first parent, but a lot of commands will think that the initial '-' implies a command line flag.
Diffstat (limited to 'sha1_file.c')
-rw-r--r--sha1_file.c67
1 files changed, 62 insertions, 5 deletions
diff --git a/sha1_file.c b/sha1_file.c
index d91e072f3..e1ee0ad34 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -60,17 +60,74 @@ int get_sha1_file(const char *path, unsigned char *result)
return get_sha1_hex(buffer, result);
}
+static int get_parent(int index, const char *str, unsigned char *result)
+{
+ unsigned char sha1[20];
+ char *buffer;
+ unsigned long size, offset;
+ int ret;
+
+ if (get_sha1(str, sha1) < 0)
+ return -1;
+ buffer = read_object_with_reference(sha1, "commit", &size, NULL);
+ if (!buffer)
+ return -1;
+ ret = -1;
+ offset = 46;
+ for (;;) {
+ if (offset + 48 > size)
+ break;
+ if (memcmp(buffer + offset, "parent ", 7))
+ break;
+ if (index > 0) {
+ offset += 48;
+ index--;
+ continue;
+ }
+ ret = get_sha1_hex(buffer + offset + 7, result);
+ break;
+ }
+ free(buffer);
+ return ret;
+}
+
int get_sha1(const char *str, unsigned char *sha1)
{
static char pathname[PATH_MAX];
+ static const char *prefix[] = {
+ "",
+ "refs",
+ "refs/tags",
+ "refs/heads",
+ "refs/snap",
+ NULL
+ };
+ const char *gitdir;
+ const char **p;
if (!get_sha1_hex(str, sha1))
return 0;
- if (!get_sha1_file(str, sha1))
- return 0;
- snprintf(pathname, sizeof(pathname), ".git/%s", str);
- if (!get_sha1_file(pathname, sha1))
- return 0;
+
+ switch (*str) {
+ case '/':
+ if (!get_sha1_file(str, sha1))
+ return 0;
+ break;
+ case '-':
+ return get_parent(0, str+1, sha1);
+ case '0' ... '9':
+ if (str[1] == '-')
+ return get_parent(*str - '0', str+2, sha1);
+ break;
+ }
+
+ gitdir = ".git";
+ for (p = prefix; *p; p++) {
+ snprintf(pathname, sizeof(pathname), "%s/%s/%s", gitdir, *p, str);
+ if (!get_sha1_file(pathname, sha1))
+ return 0;
+ }
+
return -1;
}