lock_ref_sha1_basic(): if locking fails with ENOENT, retry
authorMichael Haggerty <mhagger@alum.mit.edu>
Sat, 18 Jan 2014 22:48:55 +0000 (23:48 +0100)
committerJunio C Hamano <gitster@pobox.com>
Tue, 21 Jan 2014 21:46:30 +0000 (13:46 -0800)
If hold_lock_file_for_update() fails with errno==ENOENT, it might be
because somebody else (for example, a pack-refs process) has just
deleted one of the lockfile's ancestor directories. So if this
condition is detected, try again (up to 3 times).

Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
refs.c
diff --git a/refs.c b/refs.c
index 2d0faf23262b79a1627238e996a1852f0e87ecd1..a09bbb768d5412573a3bd42364e769f7bb3c63a8 100644 (file)
--- a/refs.c
+++ b/refs.c
@@ -2081,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;
@@ -2109,6 +2109,17 @@ static struct ref_lock *lock_ref_sha1_basic(const char *refname,
        }
 
        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: