]> git.ipfire.org Git - thirdparty/git.git/blobdiff - sha1-name.c
Sync with maint
[thirdparty/git.git] / sha1-name.c
index 60d9ef3c7e7108c859647656972c171cce4e7d7f..200eb373ad80fbcc395c9adab0d6b7f72008b99e 100644 (file)
 #include "packfile.h"
 #include "object-store.h"
 #include "repository.h"
+#include "submodule.h"
+#include "midx.h"
+#include "commit-reach.h"
 
-static int get_oid_oneline(const char *, struct object_id *, struct commit_list *);
+static int get_oid_oneline(struct repository *r, const char *, struct object_id *, struct commit_list *);
 
-typedef int (*disambiguate_hint_fn)(const struct object_id *, void *);
+typedef int (*disambiguate_hint_fn)(struct repository *, const struct object_id *, void *);
 
 struct disambiguate_state {
        int len; /* length of prefix in hex chars */
        char hex_pfx[GIT_MAX_HEXSZ + 1];
        struct object_id bin_pfx;
 
+       struct repository *repo;
        disambiguate_hint_fn fn;
        void *cb_data;
        struct object_id candidate;
@@ -36,7 +40,7 @@ struct disambiguate_state {
 static void update_candidates(struct disambiguate_state *ds, const struct object_id *current)
 {
        if (ds->always_call_fn) {
-               ds->ambiguous = ds->fn(current, ds->cb_data) ? 1 : 0;
+               ds->ambiguous = ds->fn(ds->repo, current, ds->cb_data) ? 1 : 0;
                return;
        }
        if (!ds->candidate_exists) {
@@ -44,7 +48,7 @@ static void update_candidates(struct disambiguate_state *ds, const struct object
                oidcpy(&ds->candidate, current);
                ds->candidate_exists = 1;
                return;
-       } else if (!oidcmp(&ds->candidate, current)) {
+       } else if (oideq(&ds->candidate, current)) {
                /* the same as what we already have seen */
                return;
        }
@@ -56,7 +60,7 @@ static void update_candidates(struct disambiguate_state *ds, const struct object
        }
 
        if (!ds->candidate_checked) {
-               ds->candidate_ok = ds->fn(&ds->candidate, ds->cb_data);
+               ds->candidate_ok = ds->fn(ds->repo, &ds->candidate, ds->cb_data);
                ds->disambiguate_fn_used = 1;
                ds->candidate_checked = 1;
        }
@@ -69,7 +73,7 @@ static void update_candidates(struct disambiguate_state *ds, const struct object
        }
 
        /* if we reach this point, we know ds->candidate satisfies fn */
-       if (ds->fn(current, ds->cb_data)) {
+       if (ds->fn(ds->repo, current, ds->cb_data)) {
                /*
                 * if both current and candidate satisfy fn, we cannot
                 * disambiguate.
@@ -81,51 +85,23 @@ static void update_candidates(struct disambiguate_state *ds, const struct object
        /* otherwise, current can be discarded and candidate is still good */
 }
 
-static int append_loose_object(const struct object_id *oid, const char *path,
-                              void *data)
-{
-       oid_array_append(data, oid);
-       return 0;
-}
-
 static int match_sha(unsigned, const unsigned char *, const unsigned char *);
 
 static void find_short_object_filename(struct disambiguate_state *ds)
 {
-       int subdir_nr = ds->bin_pfx.hash[0];
-       struct alternate_object_database *alt;
-       static struct alternate_object_database *fakeent;
-
-       if (!fakeent) {
-               /*
-                * Create a "fake" alternate object database that
-                * points to our own object database, to make it
-                * easier to get a temporary working space in
-                * alt->name/alt->base while iterating over the
-                * object databases including our own.
-                */
-               fakeent = alloc_alt_odb(get_object_directory());
-       }
-       fakeent->next = the_repository->objects->alt_odb_list;
+       struct object_directory *odb;
 
-       for (alt = fakeent; alt && !ds->ambiguous; alt = alt->next) {
+       for (odb = ds->repo->objects->odb; odb && !ds->ambiguous; odb = odb->next) {
                int pos;
+               struct oid_array *loose_objects;
 
-               if (!alt->loose_objects_subdir_seen[subdir_nr]) {
-                       struct strbuf *buf = alt_scratch_buf(alt);
-                       for_each_file_in_obj_subdir(subdir_nr, buf,
-                                                   append_loose_object,
-                                                   NULL, NULL,
-                                                   &alt->loose_objects_cache);
-                       alt->loose_objects_subdir_seen[subdir_nr] = 1;
-               }
-
-               pos = oid_array_lookup(&alt->loose_objects_cache, &ds->bin_pfx);
+               loose_objects = odb_loose_cache(odb, &ds->bin_pfx);
+               pos = oid_array_lookup(loose_objects, &ds->bin_pfx);
                if (pos < 0)
                        pos = -1 - pos;
-               while (!ds->ambiguous && pos < alt->loose_objects_cache.nr) {
+               while (!ds->ambiguous && pos < loose_objects->nr) {
                        const struct object_id *oid;
-                       oid = alt->loose_objects_cache.oid + pos;
+                       oid = loose_objects->oid + pos;
                        if (!match_sha(ds->len, ds->bin_pfx.hash, oid->hash))
                                break;
                        update_candidates(ds, oid);
@@ -149,12 +125,41 @@ static int match_sha(unsigned len, const unsigned char *a, const unsigned char *
        return 1;
 }
 
+static void unique_in_midx(struct multi_pack_index *m,
+                          struct disambiguate_state *ds)
+{
+       uint32_t num, i, first = 0;
+       const struct object_id *current = NULL;
+       num = m->num_objects;
+
+       if (!num)
+               return;
+
+       bsearch_midx(&ds->bin_pfx, m, &first);
+
+       /*
+        * At this point, "first" is the location of the lowest object
+        * with an object name that could match "bin_pfx".  See if we have
+        * 0, 1 or more objects that actually match(es).
+        */
+       for (i = first; i < num && !ds->ambiguous; i++) {
+               struct object_id oid;
+               current = nth_midxed_object_oid(&oid, m, i);
+               if (!match_sha(ds->len, ds->bin_pfx.hash, current->hash))
+                       break;
+               update_candidates(ds, current);
+       }
+}
+
 static void unique_in_pack(struct packed_git *p,
                           struct disambiguate_state *ds)
 {
        uint32_t num, i, first = 0;
        const struct object_id *current = NULL;
 
+       if (p->multi_pack_index)
+               return;
+
        if (open_pack_index(p) || !p->num_objects)
                return;
 
@@ -177,16 +182,17 @@ static void unique_in_pack(struct packed_git *p,
 
 static void find_short_packed_object(struct disambiguate_state *ds)
 {
+       struct multi_pack_index *m;
        struct packed_git *p;
 
-       for (p = get_packed_git(the_repository); p && !ds->ambiguous;
+       for (m = get_multi_pack_index(ds->repo); m && !ds->ambiguous;
+            m = m->next)
+               unique_in_midx(m, ds);
+       for (p = get_packed_git(ds->repo); p && !ds->ambiguous;
             p = p->next)
                unique_in_pack(p, ds);
 }
 
-#define SHORT_NAME_NOT_FOUND (-1)
-#define SHORT_NAME_AMBIGUOUS (-2)
-
 static int finish_object_disambiguation(struct disambiguate_state *ds,
                                        struct object_id *oid)
 {
@@ -194,7 +200,7 @@ static int finish_object_disambiguation(struct disambiguate_state *ds,
                return SHORT_NAME_AMBIGUOUS;
 
        if (!ds->candidate_exists)
-               return SHORT_NAME_NOT_FOUND;
+               return MISSING_OBJECT;
 
        if (!ds->candidate_checked)
                /*
@@ -212,7 +218,7 @@ static int finish_object_disambiguation(struct disambiguate_state *ds,
                 * same repository!
                 */
                ds->candidate_ok = (!ds->disambiguate_fn_used ||
-                                   ds->fn(&ds->candidate, ds->cb_data));
+                                   ds->fn(ds->repo, &ds->candidate, ds->cb_data));
 
        if (!ds->candidate_ok)
                return SHORT_NAME_AMBIGUOUS;
@@ -221,57 +227,67 @@ static int finish_object_disambiguation(struct disambiguate_state *ds,
        return 0;
 }
 
-static int disambiguate_commit_only(const struct object_id *oid, void *cb_data_unused)
+static int disambiguate_commit_only(struct repository *r,
+                                   const struct object_id *oid,
+                                   void *cb_data_unused)
 {
-       int kind = oid_object_info(the_repository, oid, NULL);
+       int kind = oid_object_info(r, oid, NULL);
        return kind == OBJ_COMMIT;
 }
 
-static int disambiguate_committish_only(const struct object_id *oid, void *cb_data_unused)
+static int disambiguate_committish_only(struct repository *r,
+                                       const struct object_id *oid,
+                                       void *cb_data_unused)
 {
        struct object *obj;
        int kind;
 
-       kind = oid_object_info(the_repository, oid, NULL);
+       kind = oid_object_info(r, oid, NULL);
        if (kind == OBJ_COMMIT)
                return 1;
        if (kind != OBJ_TAG)
                return 0;
 
        /* We need to do this the hard way... */
-       obj = deref_tag(parse_object(oid), NULL, 0);
+       obj = deref_tag(r, parse_object(r, oid), NULL, 0);
        if (obj && obj->type == OBJ_COMMIT)
                return 1;
        return 0;
 }
 
-static int disambiguate_tree_only(const struct object_id *oid, void *cb_data_unused)
+static int disambiguate_tree_only(struct repository *r,
+                                 const struct object_id *oid,
+                                 void *cb_data_unused)
 {
-       int kind = oid_object_info(the_repository, oid, NULL);
+       int kind = oid_object_info(r, oid, NULL);
        return kind == OBJ_TREE;
 }
 
-static int disambiguate_treeish_only(const struct object_id *oid, void *cb_data_unused)
+static int disambiguate_treeish_only(struct repository *r,
+                                    const struct object_id *oid,
+                                    void *cb_data_unused)
 {
        struct object *obj;
        int kind;
 
-       kind = oid_object_info(the_repository, oid, NULL);
+       kind = oid_object_info(r, oid, NULL);
        if (kind == OBJ_TREE || kind == OBJ_COMMIT)
                return 1;
        if (kind != OBJ_TAG)
                return 0;
 
        /* We need to do this the hard way... */
-       obj = deref_tag(parse_object(oid), NULL, 0);
+       obj = deref_tag(r, parse_object(r, oid), NULL, 0);
        if (obj && (obj->type == OBJ_TREE || obj->type == OBJ_COMMIT))
                return 1;
        return 0;
 }
 
-static int disambiguate_blob_only(const struct object_id *oid, void *cb_data_unused)
+static int disambiguate_blob_only(struct repository *r,
+                                 const struct object_id *oid,
+                                 void *cb_data_unused)
 {
-       int kind = oid_object_info(the_repository, oid, NULL);
+       int kind = oid_object_info(r, oid, NULL);
        return kind == OBJ_BLOB;
 }
 
@@ -305,12 +321,13 @@ int set_disambiguate_hint_config(const char *var, const char *value)
        return error("unknown hint type for '%s': %s", var, value);
 }
 
-static int init_object_disambiguation(const char *name, int len,
+static int init_object_disambiguation(struct repository *r,
+                                     const char *name, int len,
                                      struct disambiguate_state *ds)
 {
        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));
@@ -336,7 +353,8 @@ static int init_object_disambiguation(const char *name, int len,
 
        ds->len = len;
        ds->hex_pfx[len] = '\0';
-       prepare_alt_odb(the_repository);
+       ds->repo = r;
+       prepare_alt_odb(r);
        return 0;
 }
 
@@ -346,25 +364,25 @@ 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))
+       if (ds->fn && !ds->fn(ds->repo, oid, ds->cb_data))
                return 0;
 
-       type = oid_object_info(the_repository, oid, NULL);
+       type = oid_object_info(ds->repo, oid, NULL);
        if (type == OBJ_COMMIT) {
-               struct commit *commit = lookup_commit(oid);
+               struct commit *commit = lookup_commit(ds->repo, 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(ds->repo, oid);
                if (!parse_tag(tag) && tag->tag)
                        strbuf_addf(&desc, " %s", tag->tag);
        }
 
        advise("  %s %s%s",
-              find_unique_abbrev(oid, DEFAULT_ABBREV),
+              repo_find_unique_abbrev(ds->repo, oid, DEFAULT_ABBREV),
               type_name(type) ? type_name(type) : "unknown type",
               desc.buf);
 
@@ -378,10 +396,18 @@ static int collect_ambiguous(const struct object_id *oid, void *data)
        return 0;
 }
 
-static int sort_ambiguous(const void *a, const void *b)
+static int repo_collect_ambiguous(struct repository *r,
+                                 const struct object_id *oid,
+                                 void *data)
+{
+       return collect_ambiguous(oid, data);
+}
+
+static int sort_ambiguous(const void *a, const void *b, void *ctx)
 {
-       int a_type = oid_object_info(the_repository, a, NULL);
-       int b_type = oid_object_info(the_repository, b, NULL);
+       struct repository *sort_ambiguous_repo = ctx;
+       int a_type = oid_object_info(sort_ambiguous_repo, a, NULL);
+       int b_type = oid_object_info(sort_ambiguous_repo, b, NULL);
        int a_type_sort;
        int b_type_sort;
 
@@ -406,14 +432,21 @@ static int sort_ambiguous(const void *a, const void *b)
        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)
+static void sort_ambiguous_oid_array(struct repository *r, struct oid_array *a)
+{
+       QSORT_S(a->oid, a->nr, sort_ambiguous, r);
+}
+
+static enum get_oid_result get_short_oid(struct repository *r,
+                                        const char *name, int len,
+                                        struct object_id *oid,
+                                        unsigned flags)
 {
        int status;
        struct disambiguate_state ds;
        int quietly = !!(flags & GET_OID_QUIETLY);
 
-       if (init_object_disambiguation(name, len, &ds) < 0)
+       if (init_object_disambiguation(r, name, len, &ds) < 0)
                return -1;
 
        if (HAS_MULTI_BITS(flags & GET_OID_DISAMBIGUATORS))
@@ -436,6 +469,18 @@ static int get_short_oid(const char *name, int len, struct object_id *oid,
        find_short_packed_object(&ds);
        status = finish_object_disambiguation(&ds, oid);
 
+       /*
+        * If we didn't find it, do the usual reprepare() slow-path,
+        * since the object may have recently been added to the repository
+        * or migrated from loose to packed.
+        */
+       if (status == MISSING_OBJECT) {
+               reprepare_packed_git(r);
+               find_short_object_filename(&ds);
+               find_short_packed_object(&ds);
+               status = finish_object_disambiguation(&ds, oid);
+       }
+
        if (!quietly && (status == SHORT_NAME_AMBIGUOUS)) {
                struct oid_array collect = OID_ARRAY_INIT;
 
@@ -451,8 +496,8 @@ 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, collect_ambiguous, &collect);
-               QSORT(collect.oid, collect.nr, sort_ambiguous);
+               repo_for_each_abbrev(r, ds.hex_pfx, collect_ambiguous, &collect);
+               sort_ambiguous_oid_array(r, &collect);
 
                if (oid_array_for_each(&collect, show_ambiguous_object, &ds))
                        BUG("show_ambiguous_object shouldn't return non-zero");
@@ -462,17 +507,18 @@ static int get_short_oid(const char *name, int len, struct object_id *oid,
        return status;
 }
 
-int for_each_abbrev(const char *prefix, each_abbrev_fn fn, void *cb_data)
+int repo_for_each_abbrev(struct repository *r, const char *prefix,
+                        each_abbrev_fn fn, void *cb_data)
 {
        struct oid_array collect = OID_ARRAY_INIT;
        struct disambiguate_state ds;
        int ret;
 
-       if (init_object_disambiguation(prefix, strlen(prefix), &ds) < 0)
+       if (init_object_disambiguation(r, prefix, strlen(prefix), &ds) < 0)
                return -1;
 
        ds.always_call_fn = 1;
-       ds.fn = collect_ambiguous;
+       ds.fn = repo_collect_ambiguous;
        ds.cb_data = &collect;
        find_short_object_filename(&ds);
        find_short_packed_object(&ds);
@@ -499,6 +545,7 @@ struct min_abbrev_data {
        unsigned int init_len;
        unsigned int cur_len;
        char *hex;
+       struct repository *repo;
        const struct object_id *oid;
 };
 
@@ -527,6 +574,49 @@ static int extend_abbrev_len(const struct object_id *oid, void *cb_data)
        return 0;
 }
 
+static int repo_extend_abbrev_len(struct repository *r,
+                                 const struct object_id *oid,
+                                 void *cb_data)
+{
+       return extend_abbrev_len(oid, cb_data);
+}
+
+static void find_abbrev_len_for_midx(struct multi_pack_index *m,
+                                    struct min_abbrev_data *mad)
+{
+       int match = 0;
+       uint32_t num, first = 0;
+       struct object_id oid;
+       const struct object_id *mad_oid;
+
+       if (!m->num_objects)
+               return;
+
+       num = m->num_objects;
+       mad_oid = mad->oid;
+       match = bsearch_midx(mad_oid, m, &first);
+
+       /*
+        * first is now the position in the packfile where we would insert
+        * mad->hash if it does not exist (or the position of mad->hash if
+        * it does exist). Hence, we consider a maximum of two objects
+        * nearby for the abbreviation length.
+        */
+       mad->init_len = 0;
+       if (!match) {
+               if (nth_midxed_object_oid(&oid, m, first))
+                       extend_abbrev_len(&oid, mad);
+       } else if (first < num - 1) {
+               if (nth_midxed_object_oid(&oid, m, first + 1))
+                       extend_abbrev_len(&oid, mad);
+       }
+       if (first > 0) {
+               if (nth_midxed_object_oid(&oid, m, first - 1))
+                       extend_abbrev_len(&oid, mad);
+       }
+       mad->init_len = mad->cur_len;
+}
+
 static void find_abbrev_len_for_pack(struct packed_git *p,
                                     struct min_abbrev_data *mad)
 {
@@ -535,6 +625,9 @@ static void find_abbrev_len_for_pack(struct packed_git *p,
        struct object_id oid;
        const struct object_id *mad_oid;
 
+       if (p->multi_pack_index)
+               return;
+
        if (open_pack_index(p) || !p->num_objects)
                return;
 
@@ -565,19 +658,25 @@ static void find_abbrev_len_for_pack(struct packed_git *p,
 
 static void find_abbrev_len_packed(struct min_abbrev_data *mad)
 {
+       struct multi_pack_index *m;
        struct packed_git *p;
 
-       for (p = get_packed_git(the_repository); p; p = p->next)
+       for (m = get_multi_pack_index(mad->repo); m; m = m->next)
+               find_abbrev_len_for_midx(m, mad);
+       for (p = get_packed_git(mad->repo); p; p = p->next)
                find_abbrev_len_for_pack(p, mad);
 }
 
-int find_unique_abbrev_r(char *hex, const struct object_id *oid, int len)
+int repo_find_unique_abbrev_r(struct repository *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 = r->hash_algo->hexsz;
+
        if (len < 0) {
-               unsigned long count = approximate_object_count();
+               unsigned long count = repo_approximate_object_count(r);
                /*
                 * Add one because the MSB only tells us the highest bit set,
                 * not including the value of all the _other_ bits (so "15"
@@ -599,9 +698,10 @@ 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.repo = r;
        mad.init_len = len;
        mad.cur_len = len;
        mad.hex = hex;
@@ -609,10 +709,10 @@ int find_unique_abbrev_r(char *hex, const struct object_id *oid, int len)
 
        find_abbrev_len_packed(&mad);
 
-       if (init_object_disambiguation(hex, mad.cur_len, &ds) < 0)
+       if (init_object_disambiguation(r, hex, mad.cur_len, &ds) < 0)
                return -1;
 
-       ds.fn = extend_abbrev_len;
+       ds.fn = repo_extend_abbrev_len;
        ds.always_call_fn = 1;
        ds.cb_data = (void *)&mad;
 
@@ -623,13 +723,15 @@ int find_unique_abbrev_r(char *hex, const struct object_id *oid, int len)
        return mad.cur_len;
 }
 
-const char *find_unique_abbrev(const struct object_id *oid, int len)
+const char *repo_find_unique_abbrev(struct repository *r,
+                                   const struct object_id *oid,
+                                   int len)
 {
        static int bufno;
        static char hexbuffer[4][GIT_MAX_HEXSZ + 1];
        char *hex = hexbuffer[bufno];
        bufno = (bufno + 1) % ARRAY_SIZE(hexbuffer);
-       find_unique_abbrev_r(hex, oid, len);
+       repo_find_unique_abbrev_r(r, hex, oid, len);
        return hex;
 }
 
@@ -684,11 +786,11 @@ static inline int push_mark(const char *string, int len)
        return at_mark(string, len, suffix, ARRAY_SIZE(suffix));
 }
 
-static int get_oid_1(const char *name, int len, struct object_id *oid, unsigned lookup_flags);
-static int interpret_nth_prior_checkout(const char *name, int namelen, struct strbuf *buf);
+static enum get_oid_result get_oid_1(struct repository *r, const char *name, int len, struct object_id *oid, unsigned lookup_flags);
+static int interpret_nth_prior_checkout(struct repository *r, const char *name, int namelen, struct strbuf *buf);
 
-static int get_oid_basic(const char *str, int len, struct object_id *oid,
-                         unsigned int flags)
+static int get_oid_basic(struct repository *r, const char *str, int len,
+                        struct object_id *oid, unsigned int flags)
 {
        static const char *warn_msg = "refname '%.*s' is ambiguous.";
        static const char *object_name_msg = N_(
@@ -696,7 +798,7 @@ static int get_oid_basic(const char *str, int len, struct object_id *oid,
        "because it will be ignored when you just specify 40-hex. These refs\n"
        "may be created by mistake. For example,\n"
        "\n"
-       "  git checkout -b $br $(git rev-parse ...)\n"
+       "  git switch -c $br $(git rev-parse ...)\n"
        "\n"
        "where \"$br\" is somehow empty and a 40-hex ref is created. Please\n"
        "examine these refs and maybe delete them. Turn this message off by\n"
@@ -706,9 +808,9 @@ 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 == r->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);
+                       refs_found = repo_dwim_ref(r, str, len, &tmp_oid, &real_ref);
                        if (refs_found > 0) {
                                warning(warn_msg, len, str);
                                if (advice_object_name_warning)
@@ -749,8 +851,8 @@ static int get_oid_basic(const char *str, int len, struct object_id *oid,
                struct strbuf buf = STRBUF_INIT;
                int detached;
 
-               if (interpret_nth_prior_checkout(str, len, &buf) > 0) {
-                       detached = (buf.len == GIT_SHA1_HEXSZ && !get_oid_hex(buf.buf, oid));
+               if (interpret_nth_prior_checkout(r, str, len, &buf) > 0) {
+                       detached = (buf.len == r->hash_algo->hexsz && !get_oid_hex(buf.buf, oid));
                        strbuf_release(&buf);
                        if (detached)
                                return 0;
@@ -759,18 +861,18 @@ static int get_oid_basic(const char *str, int len, struct object_id *oid,
 
        if (!len && reflog_len)
                /* allow "@{...}" to mean the current branch reflog */
-               refs_found = dwim_ref("HEAD", 4, oid, &real_ref);
+               refs_found = repo_dwim_ref(r, "HEAD", 4, oid, &real_ref);
        else if (reflog_len)
-               refs_found = dwim_log(str, len, oid, &real_ref);
+               refs_found = repo_dwim_log(r, str, len, oid, &real_ref);
        else
-               refs_found = dwim_ref(str, len, oid, &real_ref);
+               refs_found = repo_dwim_ref(r, str, len, oid, &real_ref);
 
        if (!refs_found)
                return -1;
 
        if (warn_ambiguous_refs && !(flags & GET_OID_QUIETLY) &&
            (refs_found > 1 ||
-            !get_short_oid(str, len, &tmp_oid, GET_OID_QUIETLY)))
+            !get_short_oid(r, str, len, &tmp_oid, GET_OID_QUIETLY)))
                warning(warn_msg, len, str);
 
        if (reflog_len) {
@@ -802,7 +904,8 @@ static int get_oid_basic(const char *str, int len, struct object_id *oid,
                                return -1;
                        }
                }
-               if (read_ref_at(real_ref, flags, at_time, nth, oid, NULL,
+               if (read_ref_at(get_main_ref_store(r),
+                               real_ref, flags, at_time, nth, oid, NULL,
                                &co_time, &co_tz, &co_cnt)) {
                        if (!len) {
                                if (starts_with(real_ref, "refs/heads/")) {
@@ -834,71 +937,75 @@ static int get_oid_basic(const char *str, int len, struct object_id *oid,
        return 0;
 }
 
-static int get_parent(const char *name, int len,
-                     struct object_id *result, int idx)
+static enum get_oid_result get_parent(struct repository *r,
+                                     const char *name, int len,
+                                     struct object_id *result, int idx)
 {
        struct object_id oid;
-       int ret = get_oid_1(name, len, &oid, GET_OID_COMMITTISH);
+       enum get_oid_result ret = get_oid_1(r, name, len, &oid,
+                                           GET_OID_COMMITTISH);
        struct commit *commit;
        struct commit_list *p;
 
        if (ret)
                return ret;
-       commit = lookup_commit_reference(&oid);
+       commit = lookup_commit_reference(r, &oid);
        if (parse_commit(commit))
-               return -1;
+               return MISSING_OBJECT;
        if (!idx) {
                oidcpy(result, &commit->object.oid);
-               return 0;
+               return FOUND;
        }
        p = commit->parents;
        while (p) {
                if (!--idx) {
                        oidcpy(result, &p->item->object.oid);
-                       return 0;
+                       return FOUND;
                }
                p = p->next;
        }
-       return -1;
+       return MISSING_OBJECT;
 }
 
-static int get_nth_ancestor(const char *name, int len,
-                           struct object_id *result, int generation)
+static enum get_oid_result get_nth_ancestor(struct repository *r,
+                                           const char *name, int len,
+                                           struct object_id *result,
+                                           int generation)
 {
        struct object_id oid;
        struct commit *commit;
        int ret;
 
-       ret = get_oid_1(name, len, &oid, GET_OID_COMMITTISH);
+       ret = get_oid_1(r, name, len, &oid, GET_OID_COMMITTISH);
        if (ret)
                return ret;
-       commit = lookup_commit_reference(&oid);
+       commit = lookup_commit_reference(r, &oid);
        if (!commit)
-               return -1;
+               return MISSING_OBJECT;
 
        while (generation--) {
                if (parse_commit(commit) || !commit->parents)
-                       return -1;
+                       return MISSING_OBJECT;
                commit = commit->parents->item;
        }
        oidcpy(result, &commit->object.oid);
-       return 0;
+       return FOUND;
 }
 
-struct object *peel_to_type(const char *name, int namelen,
-                           struct object *o, enum object_type expected_type)
+struct object *repo_peel_to_type(struct repository *r, const char *name, int namelen,
+                                struct object *o, enum object_type expected_type)
 {
        if (name && !namelen)
                namelen = strlen(name);
        while (1) {
-               if (!o || (!o->parsed && !parse_object(&o->oid)))
+               if (!o || (!o->parsed && !parse_object(r, &o->oid)))
                        return NULL;
                if (expected_type == OBJ_ANY || o->type == expected_type)
                        return o;
                if (o->type == OBJ_TAG)
                        o = ((struct tag*) o)->tagged;
                else if (o->type == OBJ_COMMIT)
-                       o = &(get_commit_tree(((struct commit *)o))->object);
+                       o = &(repo_get_commit_tree(r, ((struct commit *)o))->object);
                else {
                        if (name)
                                error("%.*s: expected %s type, but the object "
@@ -910,8 +1017,8 @@ struct object *peel_to_type(const char *name, int namelen,
        }
 }
 
-static int peel_onion(const char *name, int len, struct object_id *oid,
-                     unsigned lookup_flags)
+static int peel_onion(struct repository *r, const char *name, int len,
+                     struct object_id *oid, unsigned lookup_flags)
 {
        struct object_id outer;
        const char *sp;
@@ -961,15 +1068,15 @@ static int peel_onion(const char *name, int len, struct object_id *oid,
        else if (expected_type == OBJ_TREE)
                lookup_flags |= GET_OID_TREEISH;
 
-       if (get_oid_1(name, sp - name - 2, &outer, lookup_flags))
+       if (get_oid_1(r, name, sp - name - 2, &outer, lookup_flags))
                return -1;
 
-       o = parse_object(&outer);
+       o = parse_object(r, &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(r, o, name, sp - name - 2);
+               if (!o || (!o->parsed && !parse_object(r, &o->oid)))
                        return -1;
                oidcpy(oid, &o->oid);
                return 0;
@@ -980,7 +1087,7 @@ static int peel_onion(const char *name, int len, struct object_id *oid,
         * if we do not get the needed object, we should
         * barf.
         */
-       o = peel_to_type(name, len, o, expected_type);
+       o = repo_peel_to_type(r, name, len, o, expected_type);
        if (!o)
                return -1;
 
@@ -1000,14 +1107,16 @@ static int peel_onion(const char *name, int len, struct object_id *oid,
 
                prefix = xstrndup(sp + 1, name + len - 1 - (sp + 1));
                commit_list_insert((struct commit *)o, &list);
-               ret = get_oid_oneline(prefix, oid, list);
+               ret = get_oid_oneline(r, prefix, oid, list);
                free(prefix);
                return ret;
        }
        return 0;
 }
 
-static int get_describe_name(const char *name, int len, struct object_id *oid)
+static int get_describe_name(struct repository *r,
+                            const char *name, int len,
+                            struct object_id *oid)
 {
        const char *cp;
        unsigned flags = GET_OID_QUIETLY | GET_OID_COMMIT;
@@ -1021,14 +1130,18 @@ static int get_describe_name(const char *name, int len, struct object_id *oid)
                        if (ch == 'g' && cp[-1] == '-') {
                                cp++;
                                len -= cp - name;
-                               return get_short_oid(cp, len, oid, flags);
+                               return get_short_oid(r,
+                                                    cp, len, oid, flags);
                        }
                }
        }
        return -1;
 }
 
-static int get_oid_1(const char *name, int len, struct object_id *oid, unsigned lookup_flags)
+static enum get_oid_result get_oid_1(struct repository *r,
+                                    const char *name, int len,
+                                    struct object_id *oid,
+                                    unsigned lookup_flags)
 {
        int ret, has_suffix;
        const char *cp;
@@ -1047,33 +1160,42 @@ static int get_oid_1(const char *name, int len, struct object_id *oid, unsigned
        }
 
        if (has_suffix) {
-               int num = 0;
+               unsigned int num = 0;
                int len1 = cp - name;
                cp++;
-               while (cp < name + len)
-                       num = num * 10 + *cp++ - '0';
+               while (cp < name + len) {
+                       unsigned int digit = *cp++ - '0';
+                       if (unsigned_mult_overflows(num, 10))
+                               return MISSING_OBJECT;
+                       num *= 10;
+                       if (unsigned_add_overflows(num, digit))
+                               return MISSING_OBJECT;
+                       num += digit;
+               }
                if (!num && len1 == len - 1)
                        num = 1;
+               else if (num > INT_MAX)
+                       return MISSING_OBJECT;
                if (has_suffix == '^')
-                       return get_parent(name, len1, oid, num);
+                       return get_parent(r, name, len1, oid, num);
                /* else if (has_suffix == '~') -- goes without saying */
-               return get_nth_ancestor(name, len1, oid, num);
+               return get_nth_ancestor(r, name, len1, oid, num);
        }
 
-       ret = peel_onion(name, len, oid, lookup_flags);
+       ret = peel_onion(r, name, len, oid, lookup_flags);
        if (!ret)
-               return 0;
+               return FOUND;
 
-       ret = get_oid_basic(name, len, oid, lookup_flags);
+       ret = get_oid_basic(r, name, len, oid, lookup_flags);
        if (!ret)
-               return 0;
+               return FOUND;
 
        /* It could be describe output that is "SOMETHING-gXXXX" */
-       ret = get_describe_name(name, len, oid);
+       ret = get_describe_name(r, name, len, oid);
        if (!ret)
-               return 0;
+               return FOUND;
 
-       return get_short_oid(name, len, oid, lookup_flags);
+       return get_short_oid(r, name, len, oid, lookup_flags);
 }
 
 /*
@@ -1092,15 +1214,22 @@ static int get_oid_1(const char *name, int len, struct object_id *oid, unsigned
 /* Remember to update object flag allocation in object.h */
 #define ONELINE_SEEN (1u<<20)
 
+struct handle_one_ref_cb {
+       struct repository *repo;
+       struct commit_list **list;
+};
+
 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 handle_one_ref_cb *cb = cb_data;
+       struct commit_list **list = cb->list;
+       struct object *object = parse_object(cb->repo, oid);
        if (!object)
                return 0;
        if (object->type == OBJ_TAG) {
-               object = deref_tag(object, path, strlen(path));
+               object = deref_tag(cb->repo, object, path,
+                                  strlen(path));
                if (!object)
                        return 0;
        }
@@ -1110,8 +1239,9 @@ static int handle_one_ref(const char *path, const struct object_id *oid,
        return 0;
 }
 
-static int get_oid_oneline(const char *prefix, struct object_id *oid,
-                           struct commit_list *list)
+static int get_oid_oneline(struct repository *r,
+                          const char *prefix, struct object_id *oid,
+                          struct commit_list *list)
 {
        struct commit_list *backup = NULL, *l;
        int found = 0;
@@ -1142,7 +1272,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(r, &commit->object.oid))
                        continue;
                buf = get_commit_buffer(commit, NULL);
                p = strstr(buf, "\n\n");
@@ -1165,7 +1295,7 @@ static int get_oid_oneline(const char *prefix, struct object_id *oid,
 
 struct grab_nth_branch_switch_cbdata {
        int remaining;
-       struct strbuf buf;
+       struct strbuf *sb;
 };
 
 static int grab_nth_branch_switch(struct object_id *ooid, struct object_id *noid,
@@ -1183,8 +1313,8 @@ static int grab_nth_branch_switch(struct object_id *ooid, struct object_id *noid
                return 0;
        if (--(cb->remaining) == 0) {
                len = target - match;
-               strbuf_reset(&cb->buf);
-               strbuf_add(&cb->buf, match, len);
+               strbuf_reset(cb->sb);
+               strbuf_add(cb->sb, match, len);
                return 1; /* we are done */
        }
        return 0;
@@ -1194,7 +1324,8 @@ static int grab_nth_branch_switch(struct object_id *ooid, struct object_id *noid
  * Parse @{-N} syntax, return the number of characters parsed
  * if successful; otherwise signal an error with negative value.
  */
-static int interpret_nth_prior_checkout(const char *name, int namelen,
+static int interpret_nth_prior_checkout(struct repository *r,
+                                       const char *name, int namelen,
                                        struct strbuf *buf)
 {
        long nth;
@@ -1216,20 +1347,21 @@ static int interpret_nth_prior_checkout(const char *name, int namelen,
        if (nth <= 0)
                return -1;
        cb.remaining = nth;
-       strbuf_init(&cb.buf, 20);
+       cb.sb = buf;
 
-       retval = 0;
-       if (0 < for_each_reflog_ent_reverse("HEAD", grab_nth_branch_switch, &cb)) {
-               strbuf_reset(buf);
-               strbuf_addbuf(buf, &cb.buf);
+       retval = refs_for_each_reflog_ent_reverse(get_main_ref_store(r),
+                       "HEAD", grab_nth_branch_switch, &cb);
+       if (0 < retval) {
                retval = brace - name + 1;
-       }
+       } else
+               retval = 0;
 
-       strbuf_release(&cb.buf);
        return retval;
 }
 
-int get_oid_mb(const char *name, struct object_id *oid)
+int repo_get_oid_mb(struct repository *r,
+                   const char *name,
+                   struct object_id *oid)
 {
        struct commit *one, *two;
        struct commit_list *mbs;
@@ -1239,28 +1371,28 @@ int get_oid_mb(const char *name, struct object_id *oid)
 
        dots = strstr(name, "...");
        if (!dots)
-               return get_oid(name, oid);
+               return repo_get_oid(r, name, oid);
        if (dots == name)
-               st = get_oid("HEAD", &oid_tmp);
+               st = repo_get_oid(r, "HEAD", &oid_tmp);
        else {
                struct strbuf sb;
                strbuf_init(&sb, dots - name);
                strbuf_add(&sb, name, dots - name);
-               st = get_oid_committish(sb.buf, &oid_tmp);
+               st = repo_get_oid_committish(r, sb.buf, &oid_tmp);
                strbuf_release(&sb);
        }
        if (st)
                return st;
-       one = lookup_commit_reference_gently(&oid_tmp, 0);
+       one = lookup_commit_reference_gently(r, &oid_tmp, 0);
        if (!one)
                return -1;
 
-       if (get_oid_committish(dots[3] ? (dots + 3) : "HEAD", &oid_tmp))
+       if (repo_get_oid_committish(r, dots[3] ? (dots + 3) : "HEAD", &oid_tmp))
                return -1;
-       two = lookup_commit_reference_gently(&oid_tmp, 0);
+       two = lookup_commit_reference_gently(r, &oid_tmp, 0);
        if (!two)
                return -1;
-       mbs = get_merge_bases(one, two);
+       mbs = repo_get_merge_bases(r, one, two);
        if (!mbs || mbs->next)
                st = -1;
        else {
@@ -1293,7 +1425,8 @@ static int interpret_empty_at(const char *name, int namelen, int len, struct str
        return 1;
 }
 
-static int reinterpret(const char *name, int namelen, int len,
+static int reinterpret(struct repository *r,
+                      const char *name, int namelen, int len,
                       struct strbuf *buf, unsigned allowed)
 {
        /* we have extra data, which might need further processing */
@@ -1302,7 +1435,7 @@ static int reinterpret(const char *name, int namelen, int len,
        int ret;
 
        strbuf_add(buf, name + len, namelen - len);
-       ret = interpret_branch_name(buf->buf, buf->len, &tmp, allowed);
+       ret = repo_interpret_branch_name(r, buf->buf, buf->len, &tmp, allowed);
        /* that data was not interpreted, remove our cruft */
        if (ret < 0) {
                strbuf_setlen(buf, used);
@@ -1315,9 +1448,9 @@ static int reinterpret(const char *name, int namelen, int len,
        return ret - used + len;
 }
 
-static void set_shortened_ref(struct strbuf *buf, const char *ref)
+static void set_shortened_ref(struct repository *r, struct strbuf *buf, const char *ref)
 {
-       char *s = shorten_unambiguous_ref(ref, 0);
+       char *s = refs_shorten_unambiguous_ref(get_main_ref_store(r), ref, 0);
        strbuf_reset(buf);
        strbuf_addstr(buf, s);
        free(s);
@@ -1338,7 +1471,8 @@ static int branch_interpret_allowed(const char *refname, unsigned allowed)
        return 0;
 }
 
-static int interpret_branch_mark(const char *name, int namelen,
+static int interpret_branch_mark(struct repository *r,
+                                const char *name, int namelen,
                                 int at, struct strbuf *buf,
                                 int (*get_mark)(const char *, int),
                                 const char *(*get_data)(struct branch *,
@@ -1371,12 +1505,14 @@ static int interpret_branch_mark(const char *name, int namelen,
        if (!branch_interpret_allowed(value, allowed))
                return -1;
 
-       set_shortened_ref(buf, value);
+       set_shortened_ref(r, buf, value);
        return len + at;
 }
 
-int interpret_branch_name(const char *name, int namelen, struct strbuf *buf,
-                         unsigned allowed)
+int repo_interpret_branch_name(struct repository *r,
+                              const char *name, int namelen,
+                              struct strbuf *buf,
+                              unsigned allowed)
 {
        char *at;
        const char *start;
@@ -1386,14 +1522,14 @@ int interpret_branch_name(const char *name, int namelen, struct strbuf *buf,
                namelen = strlen(name);
 
        if (!allowed || (allowed & INTERPRET_BRANCH_LOCAL)) {
-               len = interpret_nth_prior_checkout(name, namelen, buf);
+               len = interpret_nth_prior_checkout(r, name, namelen, buf);
                if (!len) {
                        return len; /* syntax Ok, not enough switches */
                } else if (len > 0) {
                        if (len == namelen)
                                return len; /* consumed all */
                        else
-                               return reinterpret(name, namelen, len, buf, allowed);
+                               return reinterpret(r, name, namelen, len, buf, allowed);
                }
        }
 
@@ -1404,17 +1540,17 @@ int interpret_branch_name(const char *name, int namelen, struct strbuf *buf,
                if (!allowed || (allowed & INTERPRET_BRANCH_HEAD)) {
                        len = interpret_empty_at(name, namelen, at - name, buf);
                        if (len > 0)
-                               return reinterpret(name, namelen, len, buf,
+                               return reinterpret(r, name, namelen, len, buf,
                                                   allowed);
                }
 
-               len = interpret_branch_mark(name, namelen, at - name, buf,
+               len = interpret_branch_mark(r, name, namelen, at - name, buf,
                                            upstream_mark, branch_get_upstream,
                                            allowed);
                if (len > 0)
                        return len;
 
-               len = interpret_branch_mark(name, namelen, at - name, buf,
+               len = interpret_branch_mark(r, name, namelen, at - name, buf,
                                            push_mark, branch_get_push,
                                            allowed);
                if (len > 0)
@@ -1460,12 +1596,31 @@ int strbuf_check_branch_ref(struct strbuf *sb, const char *name)
  * This is like "get_oid_basic()", except it allows "object ID expressions",
  * notably "xyz^" for "parent of xyz"
  */
-int get_oid(const char *name, struct object_id *oid)
+int repo_get_oid(struct repository *r, const char *name, struct object_id *oid)
 {
        struct object_context unused;
-       return get_oid_with_context(name, 0, oid, &unused);
+       return get_oid_with_context(r, name, 0, oid, &unused);
 }
 
+/*
+ * This returns a non-zero value if the string (built using printf
+ * format and the given arguments) is not a valid object.
+ */
+int get_oidf(struct object_id *oid, const char *fmt, ...)
+{
+       va_list ap;
+       int ret;
+       struct strbuf sb = STRBUF_INIT;
+
+       va_start(ap, fmt);
+       strbuf_vaddf(&sb, fmt, ap);
+       va_end(ap);
+
+       ret = get_oid(sb.buf, oid);
+       strbuf_release(&sb);
+
+       return ret;
+}
 
 /*
  * Many callers know that the user meant to name a commit-ish by
@@ -1477,50 +1632,61 @@ int get_oid(const char *name, struct object_id *oid)
  * commit-ish. It is merely to give a hint to the disambiguation
  * machinery.
  */
-int get_oid_committish(const char *name, struct object_id *oid)
+int repo_get_oid_committish(struct repository *r,
+                           const char *name,
+                           struct object_id *oid)
 {
        struct object_context unused;
-       return get_oid_with_context(name, GET_OID_COMMITTISH,
+       return get_oid_with_context(r, name, GET_OID_COMMITTISH,
                                    oid, &unused);
 }
 
-int get_oid_treeish(const char *name, struct object_id *oid)
+int repo_get_oid_treeish(struct repository *r,
+                        const char *name,
+                        struct object_id *oid)
 {
        struct object_context unused;
-       return get_oid_with_context(name, GET_OID_TREEISH,
+       return get_oid_with_context(r, name, GET_OID_TREEISH,
                                    oid, &unused);
 }
 
-int get_oid_commit(const char *name, struct object_id *oid)
+int repo_get_oid_commit(struct repository *r,
+                       const char *name,
+                       struct object_id *oid)
 {
        struct object_context unused;
-       return get_oid_with_context(name, GET_OID_COMMIT,
+       return get_oid_with_context(r, name, GET_OID_COMMIT,
                                    oid, &unused);
 }
 
-int get_oid_tree(const char *name, struct object_id *oid)
+int repo_get_oid_tree(struct repository *r,
+                     const char *name,
+                     struct object_id *oid)
 {
        struct object_context unused;
-       return get_oid_with_context(name, GET_OID_TREE,
+       return get_oid_with_context(r, name, GET_OID_TREE,
                                    oid, &unused);
 }
 
-int get_oid_blob(const char *name, struct object_id *oid)
+int repo_get_oid_blob(struct repository *r,
+                     const char *name,
+                     struct object_id *oid)
 {
        struct object_context unused;
-       return get_oid_with_context(name, GET_OID_BLOB,
+       return get_oid_with_context(r, name, GET_OID_BLOB,
                                    oid, &unused);
 }
 
 /* Must be called only when object_name:filename doesn't exist. */
-static void diagnose_invalid_oid_path(const char *prefix,
+static void diagnose_invalid_oid_path(struct repository *r,
+                                     const char *prefix,
                                      const char *filename,
                                      const struct object_id *tree_oid,
                                      const char *object_name,
                                      int object_name_len)
 {
        struct object_id oid;
-       unsigned mode;
+       unsigned short mode;
 
        if (!prefix)
                prefix = "";
@@ -1531,7 +1697,7 @@ static void diagnose_invalid_oid_path(const char *prefix,
        if (is_missing_file_error(errno)) {
                char *fullname = xstrfmt("%s%s", prefix, filename);
 
-               if (!get_tree_entry(tree_oid, fullname, &oid, &mode)) {
+               if (!get_tree_entry(r, tree_oid, fullname, &oid, &mode)) {
                        die("Path '%s' exists, but not '%s'.\n"
                            "Did you mean '%.*s:%s' aka '%.*s:./%s'?",
                            fullname,
@@ -1547,10 +1713,12 @@ static void diagnose_invalid_oid_path(const char *prefix,
 }
 
 /* Must be called only when :stage:filename doesn't exist. */
-static void diagnose_invalid_index_path(int stage,
+static void diagnose_invalid_index_path(struct repository *r,
+                                       int stage,
                                        const char *prefix,
                                        const char *filename)
 {
+       struct index_state *istate = r->index;
        const struct cache_entry *ce;
        int pos;
        unsigned namelen = strlen(filename);
@@ -1560,11 +1728,11 @@ static void diagnose_invalid_index_path(int stage,
                prefix = "";
 
        /* Wrong stage number? */
-       pos = cache_name_pos(filename, namelen);
+       pos = index_name_pos(istate, filename, namelen);
        if (pos < 0)
                pos = -pos - 1;
-       if (pos < active_nr) {
-               ce = active_cache[pos];
+       if (pos < istate->cache_nr) {
+               ce = istate->cache[pos];
                if (ce_namelen(ce) == namelen &&
                    !memcmp(ce->name, filename, namelen))
                        die("Path '%s' is in the index, but not at stage %d.\n"
@@ -1576,11 +1744,11 @@ static void diagnose_invalid_index_path(int stage,
        /* Confusion between relative and absolute filenames? */
        strbuf_addstr(&fullname, prefix);
        strbuf_addstr(&fullname, filename);
-       pos = cache_name_pos(fullname.buf, fullname.len);
+       pos = index_name_pos(istate, fullname.buf, fullname.len);
        if (pos < 0)
                pos = -pos - 1;
-       if (pos < active_nr) {
-               ce = active_cache[pos];
+       if (pos < istate->cache_nr) {
+               ce = istate->cache[pos];
                if (ce_namelen(ce) == fullname.len &&
                    !memcmp(ce->name, fullname.buf, fullname.len))
                        die("Path '%s' is in the index, but not '%s'.\n"
@@ -1590,7 +1758,7 @@ static void diagnose_invalid_index_path(int stage,
                            ce_stage(ce), filename);
        }
 
-       if (file_exists(filename))
+       if (repo_file_exists(r, filename))
                die("Path '%s' exists on disk, but not in the index.", filename);
        if (is_missing_file_error(errno))
                die("Path '%s' does not exist (neither on disk nor in the index).",
@@ -1600,12 +1768,12 @@ static void diagnose_invalid_index_path(int stage,
 }
 
 
-static char *resolve_relative_path(const char *rel)
+static char *resolve_relative_path(struct repository *r, const char *rel)
 {
        if (!starts_with(rel, "./") && !starts_with(rel, "../"))
                return NULL;
 
-       if (!is_inside_work_tree())
+       if (r != the_repository || !is_inside_work_tree())
                die("relative path syntax can't be used outside working tree.");
 
        /* die() inside prefix_path() if resolved path is outside worktree */
@@ -1614,7 +1782,8 @@ static char *resolve_relative_path(const char *rel)
                           rel);
 }
 
-static int get_oid_with_context_1(const char *name,
+static enum get_oid_result get_oid_with_context_1(struct repository *repo,
+                                 const char *name,
                                  unsigned flags,
                                  const char *prefix,
                                  struct object_id *oid,
@@ -1631,7 +1800,7 @@ static int get_oid_with_context_1(const char *name,
        memset(oc, 0, sizeof(*oc));
        oc->mode = S_IFINVALID;
        strbuf_init(&oc->symlink_path, 0);
-       ret = get_oid_1(name, namelen, oid, flags);
+       ret = get_oid_1(repo, name, namelen, oid, flags);
        if (!ret)
                return ret;
        /*
@@ -1647,11 +1816,15 @@ static int get_oid_with_context_1(const char *name,
                char *new_path = NULL;
                int pos;
                if (!only_to_die && namelen > 2 && name[1] == '/') {
+                       struct handle_one_ref_cb cb;
                        struct commit_list *list = NULL;
 
-                       for_each_ref(handle_one_ref, &list);
+                       cb.repo = repo;
+                       cb.list = &list;
+                       refs_for_each_ref(repo->refs, handle_one_ref, &cb);
+                       refs_head_ref(repo->refs, handle_one_ref, &cb);
                        commit_list_sort_by_date(&list);
-                       return get_oid_oneline(name + 2, oid, list);
+                       return get_oid_oneline(repo, name + 2, oid, list);
                }
                if (namelen < 3 ||
                    name[2] != ':' ||
@@ -1661,7 +1834,7 @@ static int get_oid_with_context_1(const char *name,
                        stage = name[1] - '0';
                        cp = name + 3;
                }
-               new_path = resolve_relative_path(cp);
+               new_path = resolve_relative_path(repo, cp);
                if (!new_path) {
                        namelen = namelen - (cp - name);
                } else {
@@ -1672,13 +1845,13 @@ static int get_oid_with_context_1(const char *name,
                if (flags & GET_OID_RECORD_PATH)
                        oc->path = xstrdup(cp);
 
-               if (!active_cache)
-                       read_cache();
-               pos = cache_name_pos(cp, namelen);
+               if (!repo->index || !repo->index->cache)
+                       repo_read_index(repo);
+               pos = index_name_pos(repo->index, cp, namelen);
                if (pos < 0)
                        pos = -pos - 1;
-               while (pos < active_nr) {
-                       ce = active_cache[pos];
+               while (pos < repo->index->cache_nr) {
+                       ce = repo->index->cache[pos];
                        if (ce_namelen(ce) != namelen ||
                            memcmp(ce->name, cp, namelen))
                                break;
@@ -1691,7 +1864,7 @@ static int get_oid_with_context_1(const char *name,
                        pos++;
                }
                if (only_to_die && name[1] && name[1] != '/')
-                       diagnose_invalid_index_path(stage, prefix, cp);
+                       diagnose_invalid_index_path(repo, stage, prefix, cp);
                free(new_path);
                return -1;
        }
@@ -1711,22 +1884,22 @@ static int get_oid_with_context_1(const char *name,
                sub_flags &= ~GET_OID_DISAMBIGUATORS;
                sub_flags |= GET_OID_TREEISH;
 
-               if (!get_oid_1(name, len, &tree_oid, sub_flags)) {
+               if (!get_oid_1(repo, name, len, &tree_oid, sub_flags)) {
                        const char *filename = cp+1;
                        char *new_filename = NULL;
 
-                       new_filename = resolve_relative_path(filename);
+                       new_filename = resolve_relative_path(repo, filename);
                        if (new_filename)
                                filename = new_filename;
                        if (flags & GET_OID_FOLLOW_SYMLINKS) {
-                               ret = get_tree_entry_follow_symlinks(&tree_oid,
+                               ret = get_tree_entry_follow_symlinks(repo, &tree_oid,
                                        filename, oid, &oc->symlink_path,
                                        &oc->mode);
                        } else {
-                               ret = get_tree_entry(&tree_oid, filename, oid,
+                               ret = get_tree_entry(repo, &tree_oid, filename, oid,
                                                     &oc->mode);
                                if (ret && only_to_die) {
-                                       diagnose_invalid_oid_path(prefix,
+                                       diagnose_invalid_oid_path(repo, prefix,
                                                                   filename,
                                                                   &tree_oid,
                                                                   name, len);
@@ -1752,16 +1925,23 @@ static int get_oid_with_context_1(const char *name,
  * exist in 'HEAD'" when given "HEAD:doc", or it may return in which case
  * you have a chance to diagnose the error further.
  */
-void maybe_die_on_misspelt_object_name(const char *name, const char *prefix)
+void maybe_die_on_misspelt_object_name(struct repository *r,
+                                      const char *name,
+                                      const char *prefix)
 {
        struct object_context oc;
        struct object_id oid;
-       get_oid_with_context_1(name, GET_OID_ONLY_TO_DIE, prefix, &oid, &oc);
+       get_oid_with_context_1(r, name, GET_OID_ONLY_TO_DIE,
+                              prefix, &oid, &oc);
 }
 
-int get_oid_with_context(const char *str, unsigned flags, struct object_id *oid, struct object_context *oc)
+enum get_oid_result get_oid_with_context(struct repository *repo,
+                                        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)
                BUG("incompatible flags for get_sha1_with_context");
-       return get_oid_with_context_1(str, flags, NULL, oid, oc);
+       return get_oid_with_context_1(repo, str, flags, NULL, oid, oc);
 }