diff --git a/R/outpack_index.R b/R/outpack_index.R index 1308ae34..f17d91ac 100644 --- a/R/outpack_index.R +++ b/R/outpack_index.R @@ -74,7 +74,7 @@ index_update <- function(root_path, prev, skip_cache, progress) { if (!identical(data, prev)) { fs::dir_create(dirname(path_index)) - saverds_atomic(data, path_index) + saverds_atomic(data, path_index, allow_fail = TRUE) } data diff --git a/R/util.R b/R/util.R index a28922f6..0c9bdcdc 100644 --- a/R/util.R +++ b/R/util.R @@ -617,10 +617,18 @@ file_canonical_case <- function(path, workdir) { } -saverds_atomic <- function(data, path) { +saverds_atomic <- function(data, path, allow_fail = FALSE) { tmp <- tempfile(pattern = sub("\\.rds", "", basename(path)), tmpdir = dirname(path), fileext = ".rds") saveRDS(data, tmp) - fs::file_move(tmp, path) + if (allow_fail) { + tryCatch( + fs::file_move(tmp, path), + error = function(e) unlink(tmp)) + } else { + tryCatch( + fs::file_move(tmp, path), + finally = unlink(tmp)) + } } diff --git a/tests/testthat/test-util.R b/tests/testthat/test-util.R index 3ea032e8..f06bc747 100644 --- a/tests/testthat/test-util.R +++ b/tests/testthat/test-util.R @@ -306,3 +306,18 @@ test_that("can convert files to canonical case", { expect_equal(file_canonical_case("A/win~1/C", tmp), NA_character_) expect_equal(file_canonical_case(c("a/b/c", "a/b/d"), tmp), c("a/b/c", NA)) }) + + +test_that("can gracefully cope with rds save failure", { + mock_move <- mockery::mock(stop("some error"), cycle = TRUE) + mockery::stub(saverds_atomic, "fs::file_move", mock_move) + tmp <- withr::local_tempdir() + path <- file.path(tmp, "file.rds") + expect_silent( + saverds_atomic(NULL, path, allow_fail = TRUE)) + expect_equal(dir(tmp), character()) + expect_error( + saverds_atomic(NULL, path, allow_fail = FALSE), + "some error") + expect_equal(dir(tmp), character()) +})