rev-parse --disambiguate=<prefix>
The new option allows you to feed an ambiguous prefix and enumerate all the objects that share it as a prefix of their object names. Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
c036c4c5e4
commit
957d74062c
@ -101,6 +101,12 @@ OPTIONS
|
||||
The option core.warnAmbiguousRefs is used to select the strict
|
||||
abbreviation mode.
|
||||
|
||||
--disambiguate=<prefix>::
|
||||
Show every object whose name begins with the given prefix.
|
||||
The <prefix> must be at least 4 hexadecimal digits long to
|
||||
avoid listing each and every object in the repository by
|
||||
mistake.
|
||||
|
||||
--all::
|
||||
Show all refs found in `refs/`.
|
||||
|
||||
|
@ -195,6 +195,12 @@ static int anti_reference(const char *refname, const unsigned char *sha1, int fl
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int show_abbrev(const unsigned char *sha1, void *cb_data)
|
||||
{
|
||||
show_rev(NORMAL, sha1, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void show_datestring(const char *flag, const char *datestr)
|
||||
{
|
||||
static char buffer[100];
|
||||
@ -589,6 +595,10 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
|
||||
for_each_ref(show_reference, NULL);
|
||||
continue;
|
||||
}
|
||||
if (!prefixcmp(arg, "--disambiguate=")) {
|
||||
for_each_abbrev(arg + 15, show_abbrev, NULL);
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(arg, "--bisect")) {
|
||||
for_each_ref_in("refs/bisect/bad", show_reference, NULL);
|
||||
for_each_ref_in("refs/bisect/good", anti_reference, NULL);
|
||||
|
3
cache.h
3
cache.h
@ -828,6 +828,9 @@ extern int get_sha1_blob(const char *str, unsigned char *sha1);
|
||||
extern void maybe_die_on_misspelt_object_name(const char *name, const char *prefix);
|
||||
extern int get_sha1_with_context(const char *str, unsigned flags, unsigned char *sha1, struct object_context *orc);
|
||||
|
||||
typedef int each_abbrev_fn(const unsigned char *sha1, void *);
|
||||
extern int for_each_abbrev(const char *prefix, each_abbrev_fn, void *);
|
||||
|
||||
/*
|
||||
* Try to read a SHA1 in hexadecimal format from the 40 characters
|
||||
* starting at hex. Write the 20-byte result to sha1 in binary form.
|
||||
|
59
sha1_name.c
59
sha1_name.c
@ -20,10 +20,15 @@ struct disambiguate_state {
|
||||
unsigned candidate_ok:1;
|
||||
unsigned disambiguate_fn_used:1;
|
||||
unsigned ambiguous:1;
|
||||
unsigned always_call_fn:1;
|
||||
};
|
||||
|
||||
static void update_candidates(struct disambiguate_state *ds, const unsigned char *current)
|
||||
{
|
||||
if (ds->always_call_fn) {
|
||||
ds->ambiguous = ds->fn(current, ds->cb_data) ? 1 : 0;
|
||||
return;
|
||||
}
|
||||
if (!ds->candidate_exists) {
|
||||
/* this is the first candidate */
|
||||
hashcpy(ds->candidate, current);
|
||||
@ -272,17 +277,12 @@ static int disambiguate_blob_only(const unsigned char *sha1, void *cb_data_unuse
|
||||
return kind == OBJ_BLOB;
|
||||
}
|
||||
|
||||
static int get_short_sha1(const char *name, int len, unsigned char *sha1,
|
||||
unsigned flags)
|
||||
static int prepare_prefixes(const char *name, int len,
|
||||
unsigned char *bin_pfx,
|
||||
char *hex_pfx)
|
||||
{
|
||||
int i, status;
|
||||
char hex_pfx[40];
|
||||
unsigned char bin_pfx[20];
|
||||
struct disambiguate_state ds;
|
||||
int quietly = !!(flags & GET_SHA1_QUIETLY);
|
||||
int i;
|
||||
|
||||
if (len < MINIMUM_ABBREV || len > 40)
|
||||
return -1;
|
||||
hashclr(bin_pfx);
|
||||
memset(hex_pfx, 'x', 40);
|
||||
for (i = 0; i < len ;i++) {
|
||||
@ -303,6 +303,22 @@ static int get_short_sha1(const char *name, int len, unsigned char *sha1,
|
||||
val <<= 4;
|
||||
bin_pfx[i >> 1] |= val;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
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)
|
||||
return -1;
|
||||
|
||||
prepare_alt_odb();
|
||||
|
||||
@ -327,6 +343,31 @@ static int get_short_sha1(const char *name, int len, unsigned char *sha1,
|
||||
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)
|
||||
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);
|
||||
return ds.ambiguous;
|
||||
}
|
||||
|
||||
const char *find_unique_abbrev(const unsigned char *sha1, int len)
|
||||
{
|
||||
int status, exists;
|
||||
|
@ -252,4 +252,13 @@ test_expect_success 'ambiguous commit-ish' '
|
||||
test_must_fail git log 000000000...
|
||||
'
|
||||
|
||||
test_expect_success 'rev-parse --disambiguate' '
|
||||
# The test creates 16 objects that share the prefix and two
|
||||
# commits created by commit-tree in earlier tests do not share
|
||||
# the prefix.
|
||||
git rev-parse --disambiguate=000000000 >actual &&
|
||||
test "$(wc -l <actual)" = 16 &&
|
||||
test "$(sed -e "s/^\(.........\).*/\1/" actual | sort -u)" = 000000000
|
||||
'
|
||||
|
||||
test_done
|
||||
|
Loading…
Reference in New Issue
Block a user