@ -13,9 +13,13 @@ static int get_sha1_oneline(const char *, unsigned char *, struct commit_list *)
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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 *
@@ -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,
@@ -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,
@@ -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
@@ -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,
@@ -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,
@@ -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,
@@ -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;
}