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>

Michael Haggerty committed Jan 6, 2017 at 17:22 UTC 6a7f3631709cb68cdea4403c480a1a5d93100c47
1 file changed +30 -43
refs/files-backend.c
+30 -43
@@ -2489,55 +2489,42 @@ out:
2489 */
2490 #define TMP_RENAMED_LOG "logs/refs/.tmp-renamed-log"
2491
2492 -static int rename_tmp_log(const char *newrefname)
2492 +static int rename_tmp_log_callback(const char *path, void *cb)
2493 {
2494 - int attempts_remaining = 4;
2495 - struct strbuf path = STRBUF_INIT;
2496 - int ret = -1;
2494 + int *true_errno = cb;
2495
2498 - retry:
2499 - strbuf_reset(&path);
2500 - strbuf_git_path(&path, "logs/%s", newrefname);
2501 - switch (safe_create_leading_directories_const(path.buf)) {
2502 - case SCLD_OK:
2503 - break; /* success */
2504 - case SCLD_VANISHED:
2505 - if (--attempts_remaining > 0)
2506 - goto retry;
2507 - /* fall through */
2508 - default:
2509 - error("unable to create directory for %s", newrefname);
2510 - goto out;
2496 + if (rename(git_path(TMP_RENAMED_LOG), path)) {
2497 + /*
2498 + * rename(a, b) when b is an existing directory ought
2499 + * to result in ISDIR, but Solaris 5.8 gives ENOTDIR.
2500 + * Sheesh. Record the true errno for error reporting,
2501 + * but report EISDIR to raceproof_create_file() so
2502 + * that it knows to retry.
2503 + */
2504 + *true_errno = errno;
2505 + if (errno == ENOTDIR)
2506 + errno = EISDIR;
2507 + return -1;
2508 + } else {
2509 + return 0;
2510 }
2511 +}
2512
2513 - if (rename(git_path(TMP_RENAMED_LOG), path.buf)) {
2514 - if ((errno==EISDIR || errno==ENOTDIR) && --attempts_remaining > 0) {
2515 - /*
2516 - * rename(a, b) when b is an existing
2517 - * directory ought to result in ISDIR, but
2518 - * Solaris 5.8 gives ENOTDIR. Sheesh.
2519 - */
2520 - if (remove_empty_directories(&path)) {
2521 - error("Directory not empty: logs/%s", newrefname);
2522 - goto out;
2523 - }
2524 - goto retry;
2525 - } else if (errno == ENOENT && --attempts_remaining > 0) {
2526 - /*
2527 - * Maybe another process just deleted one of
2528 - * the directories in the path to newrefname.
2529 - * Try again from the beginning.
2530 - */
2531 - goto retry;
2532 - } else {
2513 +static int rename_tmp_log(const char *newrefname)
2514 +{
2515 + char *path = git_pathdup("logs/%s", newrefname);
2516 + int ret, true_errno;
2517 +
2518 + ret = raceproof_create_file(path, rename_tmp_log_callback, &true_errno);
2519 + if (ret) {
2520 + if (errno == EISDIR)
2521 + error("Directory not empty: %s", path);
2522 + else
2523 error("unable to move logfile "TMP_RENAMED_LOG" to logs/%s: %s",
2534 - newrefname, strerror(errno));
2535 - goto out;
2536 - }
2524 + newrefname, strerror(true_errno));
2525 }
2538 - ret = 0;
2539 -out:
2540 - strbuf_release(&path);
2526 +
2527 + free(path);
2528 return ret;
2529 }
2530