oidmap: ensure map is initialized
[gitweb.git] / refs.c
diff --git a/refs.c b/refs.c
index 6042645c40614992bbd8ea0b06c53a350449f413..c590a992fb19ce92dcf0932b58f83b65028f8316 100644 (file)
--- a/refs.c
+++ b/refs.c
@@ -1285,6 +1285,10 @@ struct ref_iterator *refs_ref_iterator_begin(
        if (trim)
                iter = prefix_ref_iterator_begin(iter, "", trim);
 
+       /* Sanity check for subclasses: */
+       if (!iter->ordered)
+               BUG("reference iterator is not ordered");
+
        return iter;
 }
 
@@ -1431,8 +1435,21 @@ const char *refs_resolve_ref_unsafe(struct ref_store *refs,
                if (refs_read_raw_ref(refs, refname,
                                      sha1, &sb_refname, &read_flags)) {
                        *flags |= read_flags;
-                       if (errno != ENOENT || (resolve_flags & RESOLVE_REF_READING))
+
+                       /* In reading mode, refs must eventually resolve */
+                       if (resolve_flags & RESOLVE_REF_READING)
+                               return NULL;
+
+                       /*
+                        * Otherwise a missing ref is OK. But the files backend
+                        * may show errors besides ENOENT if there are
+                        * similarly-named refs.
+                        */
+                       if (errno != ENOENT &&
+                           errno != EISDIR &&
+                           errno != ENOTDIR)
                                return NULL;
+
                        hashclr(sha1);
                        if (*flags & REF_BAD_NAME)
                                *flags |= REF_ISBROKEN;
@@ -1686,7 +1703,23 @@ int refs_pack_refs(struct ref_store *refs, unsigned int flags)
 int refs_peel_ref(struct ref_store *refs, const char *refname,
                  unsigned char *sha1)
 {
-       return refs->be->peel_ref(refs, refname, sha1);
+       int flag;
+       unsigned char base[20];
+
+       if (current_ref_iter && current_ref_iter->refname == refname) {
+               struct object_id peeled;
+
+               if (ref_iterator_peel(current_ref_iter, &peeled))
+                       return -1;
+               hashcpy(sha1, peeled.hash);
+               return 0;
+       }
+
+       if (refs_read_ref_full(refs, refname,
+                              RESOLVE_REF_READING, base, &flag))
+               return -1;
+
+       return peel_object(base, sha1);
 }
 
 int peel_ref(const char *refname, unsigned char *sha1)
@@ -2036,3 +2069,14 @@ int rename_ref(const char *oldref, const char *newref, const char *logmsg)
 {
        return refs_rename_ref(get_main_ref_store(), oldref, newref, logmsg);
 }
+
+int refs_copy_existing_ref(struct ref_store *refs, const char *oldref,
+                   const char *newref, const char *logmsg)
+{
+       return refs->be->copy_ref(refs, oldref, newref, logmsg);
+}
+
+int copy_existing_ref(const char *oldref, const char *newref, const char *logmsg)
+{
+       return refs_copy_existing_ref(get_main_ref_store(), oldref, newref, logmsg);
+}