Merge branch 'is/parsing-line-range'
[gitweb.git] / sha1-name.c
index 5b93bf8da36939376b506f96624f568875397969..e072d48ddafc5d998b9ad42ada4297a01a5fee07 100644 (file)
@@ -223,7 +223,7 @@ static int finish_object_disambiguation(struct disambiguate_state *ds,
 
 static int disambiguate_commit_only(const struct object_id *oid, void *cb_data_unused)
 {
-       int kind = oid_object_info(oid, NULL);
+       int kind = oid_object_info(the_repository, oid, NULL);
        return kind == OBJ_COMMIT;
 }
 
@@ -232,7 +232,7 @@ static int disambiguate_committish_only(const struct object_id *oid, void *cb_da
        struct object *obj;
        int kind;
 
-       kind = oid_object_info(oid, NULL);
+       kind = oid_object_info(the_repository, oid, NULL);
        if (kind == OBJ_COMMIT)
                return 1;
        if (kind != OBJ_TAG)
@@ -247,7 +247,7 @@ static int disambiguate_committish_only(const struct object_id *oid, void *cb_da
 
 static int disambiguate_tree_only(const struct object_id *oid, void *cb_data_unused)
 {
-       int kind = oid_object_info(oid, NULL);
+       int kind = oid_object_info(the_repository, oid, NULL);
        return kind == OBJ_TREE;
 }
 
@@ -256,7 +256,7 @@ static int disambiguate_treeish_only(const struct object_id *oid, void *cb_data_
        struct object *obj;
        int kind;
 
-       kind = oid_object_info(oid, NULL);
+       kind = oid_object_info(the_repository, oid, NULL);
        if (kind == OBJ_TREE || kind == OBJ_COMMIT)
                return 1;
        if (kind != OBJ_TAG)
@@ -271,7 +271,7 @@ static int disambiguate_treeish_only(const struct object_id *oid, void *cb_data_
 
 static int disambiguate_blob_only(const struct object_id *oid, void *cb_data_unused)
 {
-       int kind = oid_object_info(oid, NULL);
+       int kind = oid_object_info(the_repository, oid, NULL);
        return kind == OBJ_BLOB;
 }
 
@@ -310,7 +310,7 @@ static int init_object_disambiguation(const char *name, int len,
 {
        int i;
 
-       if (len < MINIMUM_ABBREV || len > GIT_SHA1_HEXSZ)
+       if (len < MINIMUM_ABBREV || len > the_hash_algo->hexsz)
                return -1;
 
        memset(ds, 0, sizeof(*ds));
@@ -346,11 +346,10 @@ 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;
 
-       type = oid_object_info(oid, NULL);
+       type = oid_object_info(the_repository, oid, NULL);
        if (type == OBJ_COMMIT) {
                struct commit *commit = lookup_commit(oid);
                if (commit) {
@@ -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)
 {
@@ -384,7 +417,7 @@ static int get_short_oid(const char *name, int len, struct object_id *oid,
                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;
@@ -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;
@@ -542,6 +576,8 @@ int find_unique_abbrev_r(char *hex, const struct object_id *oid, int len)
        struct disambiguate_state ds;
        struct min_abbrev_data mad;
        struct object_id oid_ret;
+       const unsigned hexsz = the_hash_algo->hexsz;
+
        if (len < 0) {
                unsigned long count = approximate_object_count();
                /*
@@ -565,8 +601,8 @@ int find_unique_abbrev_r(char *hex, const struct object_id *oid, int len)
        }
 
        oid_to_hex_r(hex, oid);
-       if (len == GIT_SHA1_HEXSZ || !len)
-               return GIT_SHA1_HEXSZ;
+       if (len == hexsz || !len)
+               return hexsz;
 
        mad.init_len = len;
        mad.cur_len = len;
@@ -672,7 +708,7 @@ static int get_oid_basic(const char *str, int len, struct object_id *oid,
        int refs_found = 0;
        int at, reflog_len, nth_prior = 0;
 
-       if (len == GIT_SHA1_HEXSZ && !get_oid_hex(str, oid)) {
+       if (len == the_hash_algo->hexsz && !get_oid_hex(str, oid)) {
                if (warn_ambiguous_refs && warn_on_object_refname_ambiguity) {
                        refs_found = dwim_ref(str, len, &tmp_oid, &real_ref);
                        if (refs_found > 0) {
@@ -716,7 +752,7 @@ static int get_oid_basic(const char *str, int len, struct object_id *oid,
                int detached;
 
                if (interpret_nth_prior_checkout(str, len, &buf) > 0) {
-                       detached = (buf.len == GIT_SHA1_HEXSZ && !get_oid_hex(buf.buf, oid));
+                       detached = (buf.len == the_hash_algo->hexsz && !get_oid_hex(buf.buf, oid));
                        strbuf_release(&buf);
                        if (detached)
                                return 0;
@@ -864,7 +900,7 @@ struct object *peel_to_type(const char *name, int namelen,
                if (o->type == OBJ_TAG)
                        o = ((struct tag*) o)->tagged;
                else if (o->type == OBJ_COMMIT)
-                       o = &(((struct commit *) o)->tree->object);
+                       o = &(get_commit_tree(((struct commit *)o))->object);
                else {
                        if (name)
                                error("%.*s: expected %s type, but the object "
@@ -1616,6 +1652,7 @@ static int get_oid_with_context_1(const char *name,
                        struct commit_list *list = NULL;
 
                        for_each_ref(handle_one_ref, &list);
+                       head_ref(handle_one_ref, &list);
                        commit_list_sort_by_date(&list);
                        return get_oid_oneline(name + 2, oid, list);
                }
@@ -1685,8 +1722,8 @@ static int get_oid_with_context_1(const char *name,
                        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,
@@ -1698,7 +1735,6 @@ static int get_oid_with_context_1(const char *name,
                                                                   name, len);
                                }
                        }
-                       hashcpy(oc->tree, tree_oid.hash);
                        if (flags & GET_OID_RECORD_PATH)
                                oc->path = xstrdup(filename);
 
@@ -1729,6 +1765,6 @@ void maybe_die_on_misspelt_object_name(const char *name, const char *prefix)
 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);
 }