X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=sha1_name.c;h=dc6835520ccfd4838b47a4af81ccf139f55e1801;hb=698ce6f87e0d6db380f7306e190e8586da184577;hp=35e8dfb9c7beddab116c77b44e4da8ed1b41c995;hpb=041a7308de3e6af36c5a6cc3412b542f42314f3f;p=git.git diff --git a/sha1_name.c b/sha1_name.c index 35e8dfb9..dc683552 100644 --- a/sha1_name.c +++ b/sha1_name.c @@ -3,7 +3,7 @@ #include "commit.h" #include "tree.h" #include "blob.h" -#include "diff.h" +#include "tree-walk.h" static int find_short_object_filename(int len, const char *name, unsigned char *sha1) { @@ -450,58 +450,6 @@ static int get_sha1_1(const char *name, int len, unsigned char *sha1) return get_short_sha1(name, len, sha1, 0); } -static int get_tree_entry(const unsigned char *, const char *, unsigned char *, unsigned *); - -static int find_tree_entry(struct tree_desc *t, const char *name, unsigned char *result, unsigned *mode) -{ - int namelen = strlen(name); - while (t->size) { - const char *entry; - const unsigned char *sha1; - int entrylen, cmp; - - sha1 = tree_entry_extract(t, &entry, mode); - update_tree_entry(t); - entrylen = strlen(entry); - if (entrylen > namelen) - continue; - cmp = memcmp(name, entry, entrylen); - if (cmp > 0) - continue; - if (cmp < 0) - break; - if (entrylen == namelen) { - memcpy(result, sha1, 20); - return 0; - } - if (name[entrylen] != '/') - continue; - if (!S_ISDIR(*mode)) - break; - if (++entrylen == namelen) { - memcpy(result, sha1, 20); - return 0; - } - return get_tree_entry(sha1, name + entrylen, result, mode); - } - return -1; -} - -static int get_tree_entry(const unsigned char *tree_sha1, const char *name, unsigned char *sha1, unsigned *mode) -{ - int retval; - void *tree; - struct tree_desc t; - - tree = read_object_with_reference(tree_sha1, tree_type, &t.size, NULL); - if (!tree) - return -1; - t.buf = tree; - retval = find_tree_entry(&t, name, sha1, mode); - free(tree); - return retval; -} - /* * This is like "get_sha1_basic()", except it allows "sha1 expressions", * notably "xyz^" for "parent of xyz" @@ -510,17 +458,56 @@ int get_sha1(const char *name, unsigned char *sha1) { int ret; unsigned unused; + int namelen = strlen(name); + const char *cp; prepare_alt_odb(); - ret = get_sha1_1(name, strlen(name), sha1); - if (ret < 0) { - const char *cp = strchr(name, ':'); - if (cp) { - unsigned char tree_sha1[20]; - if (!get_sha1_1(name, cp-name, tree_sha1)) - return get_tree_entry(tree_sha1, cp+1, sha1, - &unused); + ret = get_sha1_1(name, namelen, sha1); + if (!ret) + return ret; + /* sha1:path --> object name of path in ent sha1 + * :path -> object name of path in index + * :[0-3]:path -> object name of path in index at stage + */ + if (name[0] == ':') { + int stage = 0; + struct cache_entry *ce; + int pos; + if (namelen < 3 || + name[2] != ':' || + name[1] < '0' || '3' < name[1]) + cp = name + 1; + else { + stage = name[1] - '0'; + cp = name + 3; + } + namelen = namelen - (cp - name); + if (!active_cache) + read_cache(); + if (active_nr < 0) + return -1; + pos = cache_name_pos(cp, namelen); + if (pos < 0) + pos = -pos - 1; + while (pos < active_nr) { + ce = active_cache[pos]; + if (ce_namelen(ce) != namelen || + memcmp(ce->name, cp, namelen)) + break; + if (ce_stage(ce) == stage) { + memcpy(sha1, ce->sha1, 20); + return 0; + } + pos++; } + return -1; + } + cp = strchr(name, ':'); + if (cp) { + unsigned char tree_sha1[20]; + if (!get_sha1_1(name, cp-name, tree_sha1)) + return get_tree_entry(tree_sha1, cp+1, sha1, + &unused); } return ret; }