lock_ref_sha1_basic(): if locking fails with ENOENT, retry

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>

Michael Haggerty committed Jan 18, 2014 at 23:48 UTC e5c223e98b985d9faa274039aefa4391d2da25a6
1 file changed +12 -1
refs.c
+12 -1
@@ -2081,7 +2081,7 @@ static struct ref_lock *lock_ref_sha1_basic(const char *refname,
2081
2082 lock->lk = xcalloc(1, sizeof(struct lock_file));
2083
2084 - lflags = LOCK_DIE_ON_ERROR;
2084 + lflags = 0;
2085 if (flags & REF_NODEREF) {
2086 refname = orig_refname;
2087 lflags |= LOCK_NODEREF;
@@ -2109,6 +2109,17 @@ static struct ref_lock *lock_ref_sha1_basic(const char *refname,
2109 }
2110
2111 lock->lock_fd = hold_lock_file_for_update(lock->lk, ref_file, lflags);
2112 + if (lock->lock_fd < 0) {
2113 + if (errno == ENOENT && --attempts_remaining > 0)
2114 + /*
2115 + * Maybe somebody just deleted one of the
2116 + * directories leading to ref_file. Try
2117 + * again:
2118 + */
2119 + goto retry;
2120 + else
2121 + unable_to_lock_index_die(ref_file, errno);
2122 + }
2123 return old_sha1 ? verify_lock(lock, old_sha1, mustexist) : lock;
2124
2125 error_return: