summaryrefslogtreecommitdiff
path: root/sha1-name.c
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2018-05-30 05:04:11 (GMT)
committerJunio C Hamano <gitster@pobox.com>2018-05-30 05:04:11 (GMT)
commitab48bc0aeadd7f6b661bc125a913e1c7d145cd5e (patch)
tree98bbbcf8dd2e210de83c71b2aecc508e9e7ba395 /sha1-name.c
parent54db5c0e1edf0d92bd474f515fab349b98c18a24 (diff)
parent5cc044e02571e93048160d94e64fe6d8dd96597e (diff)
downloadgit-ab48bc0aeadd7f6b661bc125a913e1c7d145cd5e.zip
git-ab48bc0aeadd7f6b661bc125a913e1c7d145cd5e.tar.gz
git-ab48bc0aeadd7f6b661bc125a913e1c7d145cd5e.tar.bz2
Merge branch 'ab/get-short-oid'
When a short hexadecimal string is used to name an object but there are multiple objects that share the string as the prefix of their names, the code lists these ambiguous candidates in a help message. These object names are now sorted according to their types for easier eyeballing. * ab/get-short-oid: get_short_oid: sort ambiguous objects by type, then SHA-1 sha1-name.c: move around the collect_ambiguous() function git-p4: change "commitish" typo to "committish" sha1-array.h: align function arguments sha1-name.c: remove stray newline
Diffstat (limited to 'sha1-name.c')
-rw-r--r--sha1-name.c50
1 files changed, 42 insertions, 8 deletions
diff --git a/sha1-name.c b/sha1-name.c
index cc0028e..60d9ef3 100644
--- a/sha1-name.c
+++ b/sha1-name.c
@@ -346,7 +346,6 @@ static int show_ambiguous_object(const struct object_id *oid, void *data)
struct strbuf desc = STRBUF_INIT;
int type;
-
if (ds->fn && !ds->fn(oid, ds->cb_data))
return 0;
@@ -373,6 +372,40 @@ static int show_ambiguous_object(const struct object_id *oid, void *data)
return 0;
}
+static int collect_ambiguous(const struct object_id *oid, void *data)
+{
+ oid_array_append(data, oid);
+ return 0;
+}
+
+static int sort_ambiguous(const void *a, const void *b)
+{
+ int a_type = oid_object_info(the_repository, a, NULL);
+ int b_type = oid_object_info(the_repository, b, NULL);
+ int a_type_sort;
+ int b_type_sort;
+
+ /*
+ * Sorts by hash within the same object type, just as
+ * oid_array_for_each_unique() would do.
+ */
+ if (a_type == b_type)
+ return oidcmp(a, b);
+
+ /*
+ * Between object types show tags, then commits, and finally
+ * trees and blobs.
+ *
+ * The object_type enum is commit, tree, blob, tag, but we
+ * want tag, commit, tree blob. Cleverly (perhaps too
+ * cleverly) do that with modulus, since the enum assigns 1 to
+ * commit, so tag becomes 0.
+ */
+ a_type_sort = a_type % 4;
+ b_type_sort = b_type % 4;
+ return a_type_sort > b_type_sort ? 1 : -1;
+}
+
static int get_short_oid(const char *name, int len, struct object_id *oid,
unsigned flags)
{
@@ -404,6 +437,8 @@ static int get_short_oid(const char *name, int len, struct object_id *oid,
status = finish_object_disambiguation(&ds, oid);
if (!quietly && (status == SHORT_NAME_AMBIGUOUS)) {
+ struct oid_array collect = OID_ARRAY_INIT;
+
error(_("short SHA1 %s is ambiguous"), ds.hex_pfx);
/*
@@ -416,18 +451,17 @@ static int get_short_oid(const char *name, int len, struct object_id *oid,
ds.fn = NULL;
advise(_("The candidates are:"));
- for_each_abbrev(ds.hex_pfx, show_ambiguous_object, &ds);
+ for_each_abbrev(ds.hex_pfx, collect_ambiguous, &collect);
+ QSORT(collect.oid, collect.nr, sort_ambiguous);
+
+ if (oid_array_for_each(&collect, show_ambiguous_object, &ds))
+ BUG("show_ambiguous_object shouldn't return non-zero");
+ oid_array_clear(&collect);
}
return status;
}
-static int collect_ambiguous(const struct object_id *oid, void *data)
-{
- oid_array_append(data, oid);
- return 0;
-}
-
int for_each_abbrev(const char *prefix, each_abbrev_fn fn, void *cb_data)
{
struct oid_array collect = OID_ARRAY_INIT;