implement fetching of moved submodules
[gitweb.git] / refs.c
diff --git a/refs.c b/refs.c
index a0c5078901294b36856644c5d5d96980b6735df2..df075fcd06b0826982c94f27ab38395ac7ce30a6 100644 (file)
--- a/refs.c
+++ b/refs.c
@@ -239,8 +239,7 @@ int read_ref(const char *refname, unsigned char *sha1)
 
 int ref_exists(const char *refname)
 {
-       unsigned char sha1[20];
-       return !!resolve_ref_unsafe(refname, RESOLVE_REF_READING, sha1, NULL);
+       return !!resolve_ref_unsafe(refname, RESOLVE_REF_READING, NULL, NULL);
 }
 
 static int filter_refs(const char *refname, const struct object_id *oid,
@@ -286,12 +285,11 @@ static int warn_if_dangling_symref(const char *refname, const struct object_id *
 {
        struct warn_if_dangling_data *d = cb_data;
        const char *resolves_to;
-       struct object_id junk;
 
        if (!(flags & REF_ISSYMREF))
                return 0;
 
-       resolves_to = resolve_ref_unsafe(refname, 0, junk.hash, NULL);
+       resolves_to = resolve_ref_unsafe(refname, 0, NULL, NULL);
        if (!resolves_to
            || (d->refname
                ? strcmp(resolves_to, d->refname)
@@ -561,6 +559,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,11 +586,13 @@ 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));
-               return -1;
+               goto done;
        }
 
        if (old_sha1) {
@@ -592,7 +607,7 @@ static int write_pseudoref(const char *pseudoref, const unsigned char *sha1,
                }
        }
 
-       if (write_in_full(fd, buf.buf, buf.len) != buf.len) {
+       if (write_in_full(fd, buf.buf, buf.len) < 0) {
                strbuf_addf(err, "could not write to '%s'", filename);
                rollback_lock_file(&lock);
                goto done;
@@ -616,8 +631,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))
@@ -921,6 +937,8 @@ int ref_transaction_update(struct ref_transaction *transaction,
                return -1;
        }
 
+       flags &= REF_TRANSACTION_UPDATE_ALLOWED_FLAGS;
+
        flags |= (new_sha1 ? REF_HAVE_NEW : 0) | (old_sha1 ? REF_HAVE_OLD : 0);
 
        ref_transaction_add_update(transaction, refname, flags,
@@ -1267,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;
 }
 
@@ -1339,7 +1361,7 @@ int for_each_replace_ref(each_ref_fn fn, void *cb_data)
        return do_for_each_ref(get_main_ref_store(),
                               git_replace_ref_base, fn,
                               strlen(git_replace_ref_base),
-                              0, cb_data);
+                              DO_FOR_EACH_INCLUDE_BROKEN, cb_data);
 }
 
 int for_each_namespaced_ref(each_ref_fn fn, void *cb_data)
@@ -1378,9 +1400,12 @@ const char *refs_resolve_ref_unsafe(struct ref_store *refs,
                                    unsigned char *sha1, int *flags)
 {
        static struct strbuf sb_refname = STRBUF_INIT;
+       struct object_id unused_oid;
        int unused_flags;
        int symref_count;
 
+       if (!sha1)
+               sha1 = unused_oid.hash;
        if (!flags)
                flags = &unused_flags;
 
@@ -1590,13 +1615,11 @@ struct ref_store *get_submodule_ref_store(const char *submodule)
        if (!submodule)
                return NULL;
 
-       if (submodule) {
-               len = strlen(submodule);
-               while (len && is_dir_sep(submodule[len - 1]))
-                       len--;
-               if (!len)
-                       return NULL;
-       }
+       len = strlen(submodule);
+       while (len && is_dir_sep(submodule[len - 1]))
+               len--;
+       if (!len)
+               return NULL;
 
        if (submodule[len])
                /* We need to strip off one or more trailing slashes */
@@ -1667,7 +1690,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)
@@ -2017,3 +2056,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);
+}