blob: allow lookup_blob to handle arbitrary repositories
[gitweb.git] / sha1-name.c
index 80030b159a74cb768c4cfc483e9b51da38baa0d6..009faab4aefc34f55daf6fd7e6e63ec0f0ee108a 100644 (file)
@@ -239,7 +239,8 @@ static int disambiguate_committish_only(const struct object_id *oid, void *cb_da
                return 0;
 
        /* We need to do this the hard way... */
-       obj = deref_tag(parse_object(oid), NULL, 0);
+       obj = deref_tag(the_repository, parse_object(the_repository, oid),
+                       NULL, 0);
        if (obj && obj->type == OBJ_COMMIT)
                return 1;
        return 0;
@@ -263,7 +264,8 @@ static int disambiguate_treeish_only(const struct object_id *oid, void *cb_data_
                return 0;
 
        /* We need to do this the hard way... */
-       obj = deref_tag(parse_object(oid), NULL, 0);
+       obj = deref_tag(the_repository, parse_object(the_repository, oid),
+                       NULL, 0);
        if (obj && (obj->type == OBJ_TREE || obj->type == OBJ_COMMIT))
                return 1;
        return 0;
@@ -346,20 +348,19 @@ 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(the_repository, oid, NULL);
        if (type == OBJ_COMMIT) {
-               struct commit *commit = lookup_commit(oid);
+               struct commit *commit = lookup_commit(the_repository, oid);
                if (commit) {
                        struct pretty_print_context pp = {0};
                        pp.date_mode.type = DATE_SHORT;
                        format_commit_message(commit, " %ad - %s", &desc, &pp);
                }
        } else if (type == OBJ_TAG) {
-               struct tag *tag = lookup_tag(oid);
+               struct tag *tag = lookup_tag(the_repository, oid);
                if (!parse_tag(tag) && tag->tag)
                        strbuf_addf(&desc, " %s", tag->tag);
        }
@@ -373,6 +374,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 +419,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 +439,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 +453,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;
@@ -810,7 +846,7 @@ static int get_parent(const char *name, int len,
 
        if (ret)
                return ret;
-       commit = lookup_commit_reference(&oid);
+       commit = lookup_commit_reference(the_repository, &oid);
        if (parse_commit(commit))
                return -1;
        if (!idx) {
@@ -838,7 +874,7 @@ static int get_nth_ancestor(const char *name, int len,
        ret = get_oid_1(name, len, &oid, GET_OID_COMMITTISH);
        if (ret)
                return ret;
-       commit = lookup_commit_reference(&oid);
+       commit = lookup_commit_reference(the_repository, &oid);
        if (!commit)
                return -1;
 
@@ -857,7 +893,7 @@ struct object *peel_to_type(const char *name, int namelen,
        if (name && !namelen)
                namelen = strlen(name);
        while (1) {
-               if (!o || (!o->parsed && !parse_object(&o->oid)))
+               if (!o || (!o->parsed && !parse_object(the_repository, &o->oid)))
                        return NULL;
                if (expected_type == OBJ_ANY || o->type == expected_type)
                        return o;
@@ -930,12 +966,12 @@ static int peel_onion(const char *name, int len, struct object_id *oid,
        if (get_oid_1(name, sp - name - 2, &outer, lookup_flags))
                return -1;
 
-       o = parse_object(&outer);
+       o = parse_object(the_repository, &outer);
        if (!o)
                return -1;
        if (!expected_type) {
-               o = deref_tag(o, name, sp - name - 2);
-               if (!o || (!o->parsed && !parse_object(&o->oid)))
+               o = deref_tag(the_repository, o, name, sp - name - 2);
+               if (!o || (!o->parsed && !parse_object(the_repository, &o->oid)))
                        return -1;
                oidcpy(oid, &o->oid);
                return 0;
@@ -1062,11 +1098,12 @@ static int handle_one_ref(const char *path, const struct object_id *oid,
                          int flag, void *cb_data)
 {
        struct commit_list **list = cb_data;
-       struct object *object = parse_object(oid);
+       struct object *object = parse_object(the_repository, oid);
        if (!object)
                return 0;
        if (object->type == OBJ_TAG) {
-               object = deref_tag(object, path, strlen(path));
+               object = deref_tag(the_repository, object, path,
+                                  strlen(path));
                if (!object)
                        return 0;
        }
@@ -1108,7 +1145,7 @@ static int get_oid_oneline(const char *prefix, struct object_id *oid,
                int matches;
 
                commit = pop_most_recent_commit(&list, ONELINE_SEEN);
-               if (!parse_object(&commit->object.oid))
+               if (!parse_object(the_repository, &commit->object.oid))
                        continue;
                buf = get_commit_buffer(commit, NULL);
                p = strstr(buf, "\n\n");
@@ -1217,13 +1254,13 @@ int get_oid_mb(const char *name, struct object_id *oid)
        }
        if (st)
                return st;
-       one = lookup_commit_reference_gently(&oid_tmp, 0);
+       one = lookup_commit_reference_gently(the_repository, &oid_tmp, 0);
        if (!one)
                return -1;
 
        if (get_oid_committish(dots[3] ? (dots + 3) : "HEAD", &oid_tmp))
                return -1;
-       two = lookup_commit_reference_gently(&oid_tmp, 0);
+       two = lookup_commit_reference_gently(the_repository, &oid_tmp, 0);
        if (!two)
                return -1;
        mbs = get_merge_bases(one, two);
@@ -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);
 }