X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=sha1_name.c;h=dc6835520ccfd4838b47a4af81ccf139f55e1801;hb=698ce6f87e0d6db380f7306e190e8586da184577;hp=d67de18ba5f5aa1f5b3dd1c5c81e75618d12e330;hpb=3f6726e1f112d221bd2a919e9b1b2927aeef6150;p=git.git diff --git a/sha1_name.c b/sha1_name.c index d67de18b..dc683552 100644 --- a/sha1_name.c +++ b/sha1_name.c @@ -3,6 +3,7 @@ #include "commit.h" #include "tree.h" #include "blob.h" +#include "tree-walk.h" static int find_short_object_filename(int len, const char *name, unsigned char *sha1) { @@ -235,14 +236,21 @@ static int ambiguous_path(const char *path, int len) static int get_sha1_basic(const char *str, int len, unsigned char *sha1) { - static const char *prefix[] = { - "", - "refs", - "refs/tags", - "refs/heads", + static const char *fmt[] = { + "%.*s", + "refs/%.*s", + "refs/tags/%.*s", + "refs/heads/%.*s", + "refs/remotes/%.*s", + "refs/remotes/%.*s/HEAD", NULL }; const char **p; + const char *warning = "warning: refname '%.*s' is ambiguous.\n"; + char *pathname; + int already_found = 0; + unsigned char *this_result; + unsigned char sha1_from_ref[20]; if (len == 40 && !get_sha1_hex(str, sha1)) return 0; @@ -251,11 +259,21 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1) if (ambiguous_path(str, len)) return -1; - for (p = prefix; *p; p++) { - char *pathname = git_path("%s/%.*s", *p, len, str); - if (!read_ref(pathname, sha1)) - return 0; + for (p = fmt; *p; p++) { + this_result = already_found ? sha1_from_ref : sha1; + pathname = git_path(*p, len, str); + if (!read_ref(pathname, this_result)) { + if (warn_ambiguous_refs) { + if (already_found) + fprintf(stderr, warning, len, str); + already_found++; + } + else + return 0; + } } + if (already_found) + return 0; return -1; } @@ -438,6 +456,58 @@ static int get_sha1_1(const char *name, int len, unsigned char *sha1) */ int get_sha1(const char *name, unsigned char *sha1) { + int ret; + unsigned unused; + int namelen = strlen(name); + const char *cp; + prepare_alt_odb(); - return get_sha1_1(name, strlen(name), sha1); + 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; }