Skip to content

Commit 957d740

Browse files
committed
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 <[email protected]>
1 parent c036c4c commit 957d740

File tree

5 files changed

+78
-9
lines changed

5 files changed

+78
-9
lines changed

Documentation/git-rev-parse.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,12 @@ OPTIONS
101101
The option core.warnAmbiguousRefs is used to select the strict
102102
abbreviation mode.
103103

104+
--disambiguate=<prefix>::
105+
Show every object whose name begins with the given prefix.
106+
The <prefix> must be at least 4 hexadecimal digits long to
107+
avoid listing each and every object in the repository by
108+
mistake.
109+
104110
--all::
105111
Show all refs found in `refs/`.
106112

builtin/rev-parse.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,12 @@ static int anti_reference(const char *refname, const unsigned char *sha1, int fl
195195
return 0;
196196
}
197197

198+
static int show_abbrev(const unsigned char *sha1, void *cb_data)
199+
{
200+
show_rev(NORMAL, sha1, NULL);
201+
return 0;
202+
}
203+
198204
static void show_datestring(const char *flag, const char *datestr)
199205
{
200206
static char buffer[100];
@@ -589,6 +595,10 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
589595
for_each_ref(show_reference, NULL);
590596
continue;
591597
}
598+
if (!prefixcmp(arg, "--disambiguate=")) {
599+
for_each_abbrev(arg + 15, show_abbrev, NULL);
600+
continue;
601+
}
592602
if (!strcmp(arg, "--bisect")) {
593603
for_each_ref_in("refs/bisect/bad", show_reference, NULL);
594604
for_each_ref_in("refs/bisect/good", anti_reference, NULL);

cache.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -828,6 +828,9 @@ extern int get_sha1_blob(const char *str, unsigned char *sha1);
828828
extern void maybe_die_on_misspelt_object_name(const char *name, const char *prefix);
829829
extern int get_sha1_with_context(const char *str, unsigned flags, unsigned char *sha1, struct object_context *orc);
830830

831+
typedef int each_abbrev_fn(const unsigned char *sha1, void *);
832+
extern int for_each_abbrev(const char *prefix, each_abbrev_fn, void *);
833+
831834
/*
832835
* Try to read a SHA1 in hexadecimal format from the 40 characters
833836
* starting at hex. Write the 20-byte result to sha1 in binary form.

sha1_name.c

Lines changed: 50 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,15 @@ struct disambiguate_state {
2020
unsigned candidate_ok:1;
2121
unsigned disambiguate_fn_used:1;
2222
unsigned ambiguous:1;
23+
unsigned always_call_fn:1;
2324
};
2425

2526
static void update_candidates(struct disambiguate_state *ds, const unsigned char *current)
2627
{
28+
if (ds->always_call_fn) {
29+
ds->ambiguous = ds->fn(current, ds->cb_data) ? 1 : 0;
30+
return;
31+
}
2732
if (!ds->candidate_exists) {
2833
/* this is the first candidate */
2934
hashcpy(ds->candidate, current);
@@ -272,17 +277,12 @@ static int disambiguate_blob_only(const unsigned char *sha1, void *cb_data_unuse
272277
return kind == OBJ_BLOB;
273278
}
274279

275-
static int get_short_sha1(const char *name, int len, unsigned char *sha1,
276-
unsigned flags)
280+
static int prepare_prefixes(const char *name, int len,
281+
unsigned char *bin_pfx,
282+
char *hex_pfx)
277283
{
278-
int i, status;
279-
char hex_pfx[40];
280-
unsigned char bin_pfx[20];
281-
struct disambiguate_state ds;
282-
int quietly = !!(flags & GET_SHA1_QUIETLY);
284+
int i;
283285

284-
if (len < MINIMUM_ABBREV || len > 40)
285-
return -1;
286286
hashclr(bin_pfx);
287287
memset(hex_pfx, 'x', 40);
288288
for (i = 0; i < len ;i++) {
@@ -303,6 +303,22 @@ static int get_short_sha1(const char *name, int len, unsigned char *sha1,
303303
val <<= 4;
304304
bin_pfx[i >> 1] |= val;
305305
}
306+
return 0;
307+
}
308+
309+
static int get_short_sha1(const char *name, int len, unsigned char *sha1,
310+
unsigned flags)
311+
{
312+
int status;
313+
char hex_pfx[40];
314+
unsigned char bin_pfx[20];
315+
struct disambiguate_state ds;
316+
int quietly = !!(flags & GET_SHA1_QUIETLY);
317+
318+
if (len < MINIMUM_ABBREV || len > 40)
319+
return -1;
320+
if (prepare_prefixes(name, len, bin_pfx, hex_pfx) < 0)
321+
return -1;
306322

307323
prepare_alt_odb();
308324

@@ -327,6 +343,31 @@ static int get_short_sha1(const char *name, int len, unsigned char *sha1,
327343
return status;
328344
}
329345

346+
347+
int for_each_abbrev(const char *prefix, each_abbrev_fn fn, void *cb_data)
348+
{
349+
char hex_pfx[40];
350+
unsigned char bin_pfx[20];
351+
struct disambiguate_state ds;
352+
int len = strlen(prefix);
353+
354+
if (len < MINIMUM_ABBREV || len > 40)
355+
return -1;
356+
if (prepare_prefixes(prefix, len, bin_pfx, hex_pfx) < 0)
357+
return -1;
358+
359+
prepare_alt_odb();
360+
361+
memset(&ds, 0, sizeof(ds));
362+
ds.always_call_fn = 1;
363+
ds.cb_data = cb_data;
364+
ds.fn = fn;
365+
366+
find_short_object_filename(len, hex_pfx, &ds);
367+
find_short_packed_object(len, bin_pfx, &ds);
368+
return ds.ambiguous;
369+
}
370+
330371
const char *find_unique_abbrev(const unsigned char *sha1, int len)
331372
{
332373
int status, exists;

t/t1512-rev-parse-disambiguation.sh

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,4 +252,13 @@ test_expect_success 'ambiguous commit-ish' '
252252
test_must_fail git log 000000000...
253253
'
254254

255+
test_expect_success 'rev-parse --disambiguate' '
256+
# The test creates 16 objects that share the prefix and two
257+
# commits created by commit-tree in earlier tests do not share
258+
# the prefix.
259+
git rev-parse --disambiguate=000000000 >actual &&
260+
test "$(wc -l <actual)" = 16 &&
261+
test "$(sed -e "s/^\(.........\).*/\1/" actual | sort -u)" = 000000000
262+
'
263+
255264
test_done

0 commit comments

Comments
 (0)