lock_ref_sha1_basic(): if locking fails with ENOENT, retry
[gitweb.git] / refs.c
diff --git a/refs.c b/refs.c
index 3710748ab88d8fa4639c3a0a436ca0e2b0c25552..a09bbb768d5412573a3bd42364e769f7bb3c63a8 100644 (file)
--- a/refs.c
+++ b/refs.c
@@ -947,13 +947,6 @@ static struct ref_cache *get_ref_cache(const char *submodule)
        return refs;
 }
 
-void invalidate_ref_cache(const char *submodule)
-{
-       struct ref_cache *refs = get_ref_cache(submodule);
-       clear_packed_ref_cache(refs);
-       clear_loose_ref_cache(refs);
-}
-
 /* The length of a peeled reference line in packed-refs, including EOL: */
 #define PEELED_LINE_LENGTH 42
 
@@ -2046,6 +2039,7 @@ static struct ref_lock *lock_ref_sha1_basic(const char *refname,
        int type, lflags;
        int mustexist = (old_sha1 && !is_null_sha1(old_sha1));
        int missing = 0;
+       int attempts_remaining = 3;
 
        lock = xcalloc(1, sizeof(struct ref_lock));
        lock->lock_fd = -1;
@@ -2087,7 +2081,7 @@ static struct ref_lock *lock_ref_sha1_basic(const char *refname,
 
        lock->lk = xcalloc(1, sizeof(struct lock_file));
 
-       lflags = LOCK_DIE_ON_ERROR;
+       lflags = 0;
        if (flags & REF_NODEREF) {
                refname = orig_refname;
                lflags |= LOCK_NODEREF;
@@ -2100,13 +2094,32 @@ static struct ref_lock *lock_ref_sha1_basic(const char *refname,
        if ((flags & REF_NODEREF) && (type & REF_ISSYMREF))
                lock->force_write = 1;
 
-       if (safe_create_leading_directories(ref_file)) {
+ retry:
+       switch (safe_create_leading_directories(ref_file)) {
+       case SCLD_OK:
+               break; /* success */
+       case SCLD_VANISHED:
+               if (--attempts_remaining > 0)
+                       goto retry;
+               /* fall through */
+       default:
                last_errno = errno;
                error("unable to create directory for %s", ref_file);
                goto error_return;
        }
 
        lock->lock_fd = hold_lock_file_for_update(lock->lk, ref_file, lflags);
+       if (lock->lock_fd < 0) {
+               if (errno == ENOENT && --attempts_remaining > 0)
+                       /*
+                        * Maybe somebody just deleted one of the
+                        * directories leading to ref_file.  Try
+                        * again:
+                        */
+                       goto retry;
+               else
+                       unable_to_lock_index_die(ref_file, errno);
+       }
        return old_sha1 ? verify_lock(lock, old_sha1, mustexist) : lock;
 
  error_return:
@@ -3376,7 +3389,7 @@ char *shorten_unambiguous_ref(const char *refname, int strict)
                size_t total_len = 0;
 
                /* the rule list is NULL terminated, count them first */
-               for (; ref_rev_parse_rules[nr_rules]; nr_rules++)
+               for (nr_rules = 0; ref_rev_parse_rules[nr_rules]; nr_rules++)
                        /* no +1 because strlen("%s") < strlen("%.*s") */
                        total_len += strlen(ref_rev_parse_rules[nr_rules]);