lock_ref_sha1_basic(): use raceproof_create_file()

Instead of coding the retry loop inline, use raceproof_create_file() to make lock acquisition safe against directory creation/deletion races. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Reviewed-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Michael Haggerty committed Jan 6, 2017 at 17:22 UTC 3b5d3c9848aaa6e15d814730cfac0efe3257eb46
1 file changed +9 -26
refs/files-backend.c
+9 -26
@@ -1985,6 +1985,13 @@ static int remove_empty_directories(struct strbuf *path)
1985 return remove_dir_recursively(path, REMOVE_DIR_EMPTY_ONLY);
1986 }
1987
1988 +static int create_reflock(const char *path, void *cb)
1989 +{
1990 + struct lock_file *lk = cb;
1991 +
1992 + return hold_lock_file_for_update(lk, path, LOCK_NO_DEREF) < 0 ? -1 : 0;
1993 +}
1994 +
1995 /*
1996 * Locks a ref returning the lock on success and NULL on failure.
1997 * On failure errno is set to something meaningful.
@@ -2002,7 +2009,6 @@ static struct ref_lock *lock_ref_sha1_basic(struct files_ref_store *refs,
2009 int last_errno = 0;
2010 int mustexist = (old_sha1 && !is_null_sha1(old_sha1));
2011 int resolve_flags = RESOLVE_REF_NO_RECURSE;
2005 - int attempts_remaining = 3;
2012 int resolved;
2013
2014 assert_main_repository(&refs->base, "lock_ref_sha1_basic");
@@ -2067,35 +2073,12 @@ static struct ref_lock *lock_ref_sha1_basic(struct files_ref_store *refs,
2073
2074 lock->ref_name = xstrdup(refname);
2075
2070 - retry:
2071 - switch (safe_create_leading_directories_const(ref_file.buf)) {
2072 - case SCLD_OK:
2073 - break; /* success */
2074 - case SCLD_VANISHED:
2075 - if (--attempts_remaining > 0)
2076 - goto retry;
2077 - /* fall through */
2078 - default:
2076 + if (raceproof_create_file(ref_file.buf, create_reflock, lock->lk)) {
2077 last_errno = errno;
2080 - strbuf_addf(err, "unable to create directory for '%s'",
2081 - ref_file.buf);
2078 + unable_to_lock_message(ref_file.buf, errno, err);
2079 goto error_return;
2080 }
2081
2085 - if (hold_lock_file_for_update(lock->lk, ref_file.buf, LOCK_NO_DEREF) < 0) {
2086 - last_errno = errno;
2087 - if (errno == ENOENT && --attempts_remaining > 0)
2088 - /*
2089 - * Maybe somebody just deleted one of the
2090 - * directories leading to ref_file. Try
2091 - * again:
2092 - */
2093 - goto retry;
2094 - else {
2095 - unable_to_lock_message(ref_file.buf, errno, err);
2096 - goto error_return;
2097 - }
2098 - }
2082 if (verify_lock(lock, old_sha1, mustexist, err)) {
2083 last_errno = errno;
2084 goto error_return;