struct strbuf desc = STRBUF_INIT;
int type;
-
if (ds->fn && !ds->fn(oid, ds->cb_data))
return 0;
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)
{
return -1;
if (HAS_MULTI_BITS(flags & GET_OID_DISAMBIGUATORS))
- die("BUG: multiple get_short_oid disambiguator flags");
+ BUG("multiple get_short_oid disambiguator flags");
if (flags & GET_OID_COMMIT)
ds.fn = disambiguate_commit_only;
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);
/*
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;
if (new_filename)
filename = new_filename;
if (flags & GET_OID_FOLLOW_SYMLINKS) {
- ret = get_tree_entry_follow_symlinks(tree_oid.hash,
- filename, oid->hash, &oc->symlink_path,
+ ret = get_tree_entry_follow_symlinks(&tree_oid,
+ filename, oid, &oc->symlink_path,
&oc->mode);
} else {
ret = get_tree_entry(&tree_oid, filename, oid,
name, len);
}
}
- hashcpy(oc->tree, tree_oid.hash);
if (flags & GET_OID_RECORD_PATH)
oc->path = xstrdup(filename);
int get_oid_with_context(const char *str, unsigned flags, struct object_id *oid, struct object_context *oc)
{
if (flags & GET_OID_FOLLOW_SYMLINKS && flags & GET_OID_ONLY_TO_DIE)
- die("BUG: incompatible flags for get_sha1_with_context");
+ BUG("incompatible flags for get_sha1_with_context");
return get_oid_with_context_1(str, flags, NULL, oid, oc);
}