rename_tmp_log(): use raceproof_create_file()
Besides shortening the code, this saves an unnecessary call to safe_create_leading_directories_const() in almost all cases. 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
3b5d3c9848
commit
6a7f363170
@ -2489,55 +2489,42 @@ out:
|
|||||||
*/
|
*/
|
||||||
#define TMP_RENAMED_LOG "logs/refs/.tmp-renamed-log"
|
#define TMP_RENAMED_LOG "logs/refs/.tmp-renamed-log"
|
||||||
|
|
||||||
|
static int rename_tmp_log_callback(const char *path, void *cb)
|
||||||
|
{
|
||||||
|
int *true_errno = cb;
|
||||||
|
|
||||||
|
if (rename(git_path(TMP_RENAMED_LOG), path)) {
|
||||||
|
/*
|
||||||
|
* rename(a, b) when b is an existing directory ought
|
||||||
|
* to result in ISDIR, but Solaris 5.8 gives ENOTDIR.
|
||||||
|
* Sheesh. Record the true errno for error reporting,
|
||||||
|
* but report EISDIR to raceproof_create_file() so
|
||||||
|
* that it knows to retry.
|
||||||
|
*/
|
||||||
|
*true_errno = errno;
|
||||||
|
if (errno == ENOTDIR)
|
||||||
|
errno = EISDIR;
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int rename_tmp_log(const char *newrefname)
|
static int rename_tmp_log(const char *newrefname)
|
||||||
{
|
{
|
||||||
int attempts_remaining = 4;
|
char *path = git_pathdup("logs/%s", newrefname);
|
||||||
struct strbuf path = STRBUF_INIT;
|
int ret, true_errno;
|
||||||
int ret = -1;
|
|
||||||
|
|
||||||
retry:
|
ret = raceproof_create_file(path, rename_tmp_log_callback, &true_errno);
|
||||||
strbuf_reset(&path);
|
if (ret) {
|
||||||
strbuf_git_path(&path, "logs/%s", newrefname);
|
if (errno == EISDIR)
|
||||||
switch (safe_create_leading_directories_const(path.buf)) {
|
error("Directory not empty: %s", path);
|
||||||
case SCLD_OK:
|
else
|
||||||
break; /* success */
|
|
||||||
case SCLD_VANISHED:
|
|
||||||
if (--attempts_remaining > 0)
|
|
||||||
goto retry;
|
|
||||||
/* fall through */
|
|
||||||
default:
|
|
||||||
error("unable to create directory for %s", newrefname);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rename(git_path(TMP_RENAMED_LOG), path.buf)) {
|
|
||||||
if ((errno==EISDIR || errno==ENOTDIR) && --attempts_remaining > 0) {
|
|
||||||
/*
|
|
||||||
* rename(a, b) when b is an existing
|
|
||||||
* directory ought to result in ISDIR, but
|
|
||||||
* Solaris 5.8 gives ENOTDIR. Sheesh.
|
|
||||||
*/
|
|
||||||
if (remove_empty_directories(&path)) {
|
|
||||||
error("Directory not empty: logs/%s", newrefname);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
goto retry;
|
|
||||||
} else if (errno == ENOENT && --attempts_remaining > 0) {
|
|
||||||
/*
|
|
||||||
* Maybe another process just deleted one of
|
|
||||||
* the directories in the path to newrefname.
|
|
||||||
* Try again from the beginning.
|
|
||||||
*/
|
|
||||||
goto retry;
|
|
||||||
} else {
|
|
||||||
error("unable to move logfile "TMP_RENAMED_LOG" to logs/%s: %s",
|
error("unable to move logfile "TMP_RENAMED_LOG" to logs/%s: %s",
|
||||||
newrefname, strerror(errno));
|
newrefname, strerror(true_errno));
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
ret = 0;
|
free(path);
|
||||||
out:
|
|
||||||
strbuf_release(&path);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user