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:
parent
e5007a6820
commit
3b5d3c9848
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user