diff options
-rw-r--r-- | sha1_name.c | 79 |
1 files changed, 35 insertions, 44 deletions
diff --git a/sha1_name.c b/sha1_name.c index 66365049a7..bd10700b30 100644 --- a/sha1_name.c +++ b/sha1_name.c @@ -13,9 +13,13 @@ static int get_sha1_oneline(const char *, unsigned char *, struct commit_list *) typedef int (*disambiguate_hint_fn)(const unsigned char *, void *); struct disambiguate_state { + int len; /* length of prefix in hex chars */ + char hex_pfx[GIT_SHA1_HEXSZ]; + unsigned char bin_pfx[GIT_SHA1_RAWSZ]; + disambiguate_hint_fn fn; void *cb_data; - unsigned char candidate[20]; + unsigned char candidate[GIT_SHA1_RAWSZ]; unsigned candidate_exists:1; unsigned candidate_checked:1; unsigned candidate_ok:1; @@ -72,10 +76,10 @@ static void update_candidates(struct disambiguate_state *ds, const unsigned char /* otherwise, current can be discarded and candidate is still good */ } -static void find_short_object_filename(int len, const char *hex_pfx, struct disambiguate_state *ds) +static void find_short_object_filename(struct disambiguate_state *ds) { struct alternate_object_database *alt; - char hex[40]; + char hex[GIT_SHA1_HEXSZ]; static struct alternate_object_database *fakeent; if (!fakeent) { @@ -95,7 +99,7 @@ static void find_short_object_filename(int len, const char *hex_pfx, struct disa } fakeent->next = alt_odb_list; - xsnprintf(hex, sizeof(hex), "%.2s", hex_pfx); + xsnprintf(hex, sizeof(hex), "%.2s", ds->hex_pfx); for (alt = fakeent; alt && !ds->ambiguous; alt = alt->next) { struct dirent *de; DIR *dir; @@ -103,7 +107,7 @@ static void find_short_object_filename(int len, const char *hex_pfx, struct disa * every alt_odb struct has 42 extra bytes after the base * for exactly this purpose */ - xsnprintf(alt->name, 42, "%.2s/", hex_pfx); + xsnprintf(alt->name, 42, "%.2s/", ds->hex_pfx); dir = opendir(alt->base); if (!dir) continue; @@ -113,7 +117,7 @@ static void find_short_object_filename(int len, const char *hex_pfx, struct disa if (strlen(de->d_name) != 38) continue; - if (memcmp(de->d_name, hex_pfx + 2, len - 2)) + if (memcmp(de->d_name, ds->hex_pfx + 2, ds->len - 2)) continue; memcpy(hex + 2, de->d_name, 38); if (!get_sha1_hex(hex, sha1)) @@ -138,9 +142,7 @@ static int match_sha(unsigned len, const unsigned char *a, const unsigned char * return 1; } -static void unique_in_pack(int len, - const unsigned char *bin_pfx, - struct packed_git *p, +static void unique_in_pack(struct packed_git *p, struct disambiguate_state *ds) { uint32_t num, last, i, first = 0; @@ -155,7 +157,7 @@ static void unique_in_pack(int len, int cmp; current = nth_packed_object_sha1(p, mid); - cmp = hashcmp(bin_pfx, current); + cmp = hashcmp(ds->bin_pfx, current); if (!cmp) { first = mid; break; @@ -174,20 +176,19 @@ static void unique_in_pack(int len, */ for (i = first; i < num && !ds->ambiguous; i++) { current = nth_packed_object_sha1(p, i); - if (!match_sha(len, bin_pfx, current)) + if (!match_sha(ds->len, ds->bin_pfx, current)) break; update_candidates(ds, current); } } -static void find_short_packed_object(int len, const unsigned char *bin_pfx, - struct disambiguate_state *ds) +static void find_short_packed_object(struct disambiguate_state *ds) { struct packed_git *p; prepare_packed_git(); for (p = packed_git; p && !ds->ambiguous; p = p->next) - unique_in_pack(len, bin_pfx, p, ds); + unique_in_pack(p, ds); } #define SHORT_NAME_NOT_FOUND (-1) @@ -281,14 +282,17 @@ static int disambiguate_blob_only(const unsigned char *sha1, void *cb_data_unuse return kind == OBJ_BLOB; } -static int prepare_prefixes(const char *name, int len, - unsigned char *bin_pfx, - char *hex_pfx) +static int init_object_disambiguation(const char *name, int len, + struct disambiguate_state *ds) { int i; - hashclr(bin_pfx); - memset(hex_pfx, 'x', 40); + if (len < MINIMUM_ABBREV || len > GIT_SHA1_HEXSZ) + return -1; + + memset(ds, 0, sizeof(*ds)); + memset(ds->hex_pfx, 'x', GIT_SHA1_HEXSZ); + for (i = 0; i < len ;i++) { unsigned char c = name[i]; unsigned char val; @@ -302,11 +306,14 @@ static int prepare_prefixes(const char *name, int len, } else return -1; - hex_pfx[i] = c; + ds->hex_pfx[i] = c; if (!(i & 1)) val <<= 4; - bin_pfx[i >> 1] |= val; + ds->bin_pfx[i >> 1] |= val; } + + ds->len = len; + prepare_alt_odb(); return 0; } @@ -314,20 +321,12 @@ static int get_short_sha1(const char *name, int len, unsigned char *sha1, unsigned flags) { int status; - char hex_pfx[40]; - unsigned char bin_pfx[20]; struct disambiguate_state ds; int quietly = !!(flags & GET_SHA1_QUIETLY); - if (len < MINIMUM_ABBREV || len > 40) - return -1; - if (prepare_prefixes(name, len, bin_pfx, hex_pfx) < 0) + if (init_object_disambiguation(name, len, &ds) < 0) return -1; - prepare_alt_odb(); - - memset(&ds, 0, sizeof(ds)); - if (HAS_MULTI_BITS(flags & GET_SHA1_DISAMBIGUATORS)) die("BUG: multiple get_short_sha1 disambiguator flags"); @@ -342,36 +341,28 @@ static int get_short_sha1(const char *name, int len, unsigned char *sha1, else if (flags & GET_SHA1_BLOB) ds.fn = disambiguate_blob_only; - find_short_object_filename(len, hex_pfx, &ds); - find_short_packed_object(len, bin_pfx, &ds); + find_short_object_filename(&ds); + find_short_packed_object(&ds); status = finish_object_disambiguation(&ds, sha1); if (!quietly && (status == SHORT_NAME_AMBIGUOUS)) - return error("short SHA1 %.*s is ambiguous.", len, hex_pfx); + return error("short SHA1 %.*s is ambiguous.", ds.len, ds.hex_pfx); return status; } int for_each_abbrev(const char *prefix, each_abbrev_fn fn, void *cb_data) { - char hex_pfx[40]; - unsigned char bin_pfx[20]; struct disambiguate_state ds; - int len = strlen(prefix); - if (len < MINIMUM_ABBREV || len > 40) + if (init_object_disambiguation(prefix, strlen(prefix), &ds) < 0) return -1; - if (prepare_prefixes(prefix, len, bin_pfx, hex_pfx) < 0) - return -1; - - prepare_alt_odb(); - memset(&ds, 0, sizeof(ds)); ds.always_call_fn = 1; ds.cb_data = cb_data; ds.fn = fn; - find_short_object_filename(len, hex_pfx, &ds); - find_short_packed_object(len, bin_pfx, &ds); + find_short_object_filename(&ds); + find_short_packed_object(&ds); return ds.ambiguous; } |