summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sha1_name.c79
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;
}