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>
This commit is contained in:
Michael Haggerty 2017-01-06 17:22:28 +01:00 committed by Junio C Hamano
parent e5007a6820
commit 3b5d3c9848

View file

@ -1985,6 +1985,13 @@ static int remove_empty_directories(struct strbuf *path)
return remove_dir_recursively(path, REMOVE_DIR_EMPTY_ONLY);
}
static int create_reflock(const char *path, void *cb)
{
struct lock_file *lk = cb;
return hold_lock_file_for_update(lk, path, LOCK_NO_DEREF) < 0 ? -1 : 0;
}
/*
* Locks a ref returning the lock on success and NULL on failure.
* 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,
int last_errno = 0;
int mustexist = (old_sha1 && !is_null_sha1(old_sha1));
int resolve_flags = RESOLVE_REF_NO_RECURSE;
int attempts_remaining = 3;
int resolved;
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,
lock->ref_name = xstrdup(refname);
retry:
switch (safe_create_leading_directories_const(ref_file.buf)) {
case SCLD_OK:
break; /* success */
case SCLD_VANISHED:
if (--attempts_remaining > 0)
goto retry;
/* fall through */
default:
if (raceproof_create_file(ref_file.buf, create_reflock, lock->lk)) {
last_errno = errno;
strbuf_addf(err, "unable to create directory for '%s'",
ref_file.buf);
unable_to_lock_message(ref_file.buf, errno, err);
goto error_return;
}
if (hold_lock_file_for_update(lock->lk, ref_file.buf, LOCK_NO_DEREF) < 0) {
last_errno = errno;
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_message(ref_file.buf, errno, err);
goto error_return;
}
}
if (verify_lock(lock, old_sha1, mustexist, err)) {
last_errno = errno;
goto error_return;