packed_ref_store: get rid of the `ref_cache` entirely
[gitweb.git] / refs.c
diff --git a/refs.c b/refs.c
index fe4c59aa8b681e15abb75032d36605abce1940b4..c5e6f79c77d33eb00ef05a373bb35e910e3b7820 100644 (file)
--- a/refs.c
+++ b/refs.c
@@ -174,6 +174,24 @@ int refname_is_safe(const char *refname)
        return 1;
 }
 
+/*
+ * Return true if refname, which has the specified oid and flags, can
+ * be resolved to an object in the database. If the referred-to object
+ * does not exist, emit a warning and return false.
+ */
+int ref_resolves_to_object(const char *refname,
+                          const struct object_id *oid,
+                          unsigned int flags)
+{
+       if (flags & REF_ISBROKEN)
+               return 0;
+       if (!has_sha1_file(oid->hash)) {
+               error("%s does not point to a valid object!", refname);
+               return 0;
+       }
+       return 1;
+}
+
 char *refs_resolve_refdup(struct ref_store *refs,
                          const char *refname, int resolve_flags,
                          unsigned char *sha1, int *flags)
@@ -561,6 +579,21 @@ enum ref_type ref_type(const char *refname)
        return REF_TYPE_NORMAL;
 }
 
+long get_files_ref_lock_timeout_ms(void)
+{
+       static int configured = 0;
+
+       /* The default timeout is 100 ms: */
+       static int timeout_ms = 100;
+
+       if (!configured) {
+               git_config_get_int("core.filesreflocktimeout", &timeout_ms);
+               configured = 1;
+       }
+
+       return timeout_ms;
+}
+
 static int write_pseudoref(const char *pseudoref, const unsigned char *sha1,
                           const unsigned char *old_sha1, struct strbuf *err)
 {
@@ -573,7 +606,9 @@ static int write_pseudoref(const char *pseudoref, const unsigned char *sha1,
        strbuf_addf(&buf, "%s\n", sha1_to_hex(sha1));
 
        filename = git_path("%s", pseudoref);
-       fd = hold_lock_file_for_update(&lock, filename, LOCK_DIE_ON_ERROR);
+       fd = hold_lock_file_for_update_timeout(&lock, filename,
+                                              LOCK_DIE_ON_ERROR,
+                                              get_files_ref_lock_timeout_ms());
        if (fd < 0) {
                strbuf_addf(err, "could not open '%s' for writing: %s",
                            filename, strerror(errno));
@@ -616,8 +651,9 @@ static int delete_pseudoref(const char *pseudoref, const unsigned char *old_sha1
                int fd;
                unsigned char actual_old_sha1[20];
 
-               fd = hold_lock_file_for_update(&lock, filename,
-                                              LOCK_DIE_ON_ERROR);
+               fd = hold_lock_file_for_update_timeout(
+                               &lock, filename, LOCK_DIE_ON_ERROR,
+                               get_files_ref_lock_timeout_ms());
                if (fd < 0)
                        die_errno(_("Could not open '%s' for writing"), filename);
                if (read_ref(pseudoref, actual_old_sha1))
@@ -1273,6 +1309,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;
 }
 
@@ -1695,7 +1735,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)