diff --git a/NEWS.md b/NEWS.md index 69719c4c4..b3a073ad6 100644 --- a/NEWS.md +++ b/NEWS.md @@ -23,6 +23,7 @@ * Add a new "progress" display to the `tar_watch()` app to show verbose progress info and metadata. * Add a new `workspace_on_error` argument of `tar_option_set()` to supersede `error = "workspace"`. Helps control workspace behavior independently of the `error` argument of `tar_target()` (#405, #533, #534, @mattwarkentin, @xinstein). * Implement `error = "abridge"` in `tar_target()` and related functions. If a target errors out with this option, the target itself stops, any currently running targets keeps, and no new targets launch after that (#533, #534, @xinstein). +* Add a menu prompt to `tar_destroy()` which can be suppressed with `TAR_ASK = "false"` (#542, @gofford). ## Deprecations diff --git a/R/tar_destroy.R b/R/tar_destroy.R index ac8cbe8ad..b648bff0f 100644 --- a/R/tar_destroy.R +++ b/R/tar_destroy.R @@ -23,6 +23,10 @@ #' automatically get deleted except if R crashed. #' * `"workspaces"`: compressed files in `workspaces/` in the data store with #' the saved workspaces of targets. See [tar_workspace()] for details. +#' @param ask Logical of length 1, whether to pause with a menu prompt +#' before deleting files. To disable this menu, set the `TAR_ASK` +#' environment variable to `"false"`. `usethis::edit_r_environ()` +#' can help set environment variables. #' @examples #' if (identical(Sys.getenv("TAR_EXAMPLES"), "true")) { #' tar_dir({ # tar_dir() runs code from a temporary directory. @@ -42,17 +46,21 @@ tar_destroy <- function( "scratch", "workspaces" ), + ask = NULL, store = targets::tar_config_get("store") ) { - switch( + path <- switch( match.arg(destroy), - all = unlink(store, recursive = TRUE), - meta = unlink(path_meta(store)), - process = unlink(path_process(store)), - progress = unlink(path_progress(store)), - objects = unlink(path_objects_dir(store), recursive = TRUE), - scratch = unlink(path_scratch_dir(store), recursive = TRUE), - workspaces = unlink(path_workspaces_dir(store), recursive = TRUE) + all = store, + meta = path_meta(store), + process = path_process(store), + progress = path_progress(store), + objects = path_objects_dir(store), + scratch = path_scratch_dir(store), + workspaces = path_workspaces_dir(store) ) + if (tar_should_delete(path = path, ask = ask)) { + unlink(path, recursive = TRUE) + } invisible() } diff --git a/R/tar_github_actions.R b/R/tar_github_actions.R index 20329d04b..9273a3792 100644 --- a/R/tar_github_actions.R +++ b/R/tar_github_actions.R @@ -41,7 +41,7 @@ tar_github_actions <- function( ) { tar_assert_chr(path, "path must be a character") tar_assert_scalar(path, "path must have length 1") - if (!tar_should_overwrite(ask, path)) { + if (!tar_should_overwrite(path = path, ask = ask)) { # covered in tests/interactive/test-tar_github_actions.R # nolint return(invisible()) # nocov } diff --git a/R/tar_script.R b/R/tar_script.R index 40fbc1302..289eeb906 100644 --- a/R/tar_script.R +++ b/R/tar_script.R @@ -66,7 +66,7 @@ tar_script <- function( ask = NULL, script = targets::tar_config_get("script") ) { - if (!tar_should_overwrite(ask, script)) { + if (!tar_should_overwrite(path = script, ask = ask)) { # covered in tests/interactive/test-tar_script.R # nolint return(invisible()) # nocov } diff --git a/R/utils_ask.R b/R/utils_ask.R index 547763d22..13a7a06e5 100644 --- a/R/utils_ask.R +++ b/R/utils_ask.R @@ -1,8 +1,27 @@ -tar_should_overwrite <- function(ask = NULL, file = character(0)) { +tar_should_delete <- function(path, ask) { + prompt <- paste0("Delete ", path, "?") + tar_should_modify_path(path = path, ask = ask, prompt = prompt) +} + +tar_should_overwrite <- function(path, ask) { + prompt <- paste0("Overwrite ", path, "?") + tar_should_modify_path(path = path, ask = ask, prompt = prompt) +} + +tar_should_modify_path <- function( + path = character(0), + ask = NULL, + prompt = character(0) +) { ask <- ask %|||% tar_ask_env() %|||% interactive() tar_assert_lgl(ask) tar_assert_scalar(ask) - if (!file.exists(file) || !ask) { + prompt <- paste( + prompt, + "(Set the TAR_ASK environment variable to \"false\"", + "to disable this menu, e.g. usethis::edit_r_environ().)" + ) + if (!file.exists(path) || !ask) { return(TRUE) } # This part is intrinsically interactive and cannot be covered @@ -10,7 +29,7 @@ tar_should_overwrite <- function(ask = NULL, file = character(0)) { # tests/interactive/test-tar_script.R is an example of a semi-automated test # that coveres this. # nocov start - out <- utils::menu(c("yes", "no"), title = paste0("Overwrite ", file, "?")) + out <- utils::menu(c("yes", "no"), title = prompt) identical(as.integer(out), 1L) # nocov end } diff --git a/inst/WORDLIST b/inst/WORDLIST index 979586ecd..69f92c147 100644 --- a/inst/WORDLIST +++ b/inst/WORDLIST @@ -246,6 +246,7 @@ reproducibly rerender RL rmarkdown +rmedicine Rmd RMSPE roadmap @@ -267,6 +268,8 @@ skippable SLURM SSP Stallman +Stan +stan Stawitz storr Storr diff --git a/man/tar_destroy.Rd b/man/tar_destroy.Rd index e6d73c7a6..676924ad6 100644 --- a/man/tar_destroy.Rd +++ b/man/tar_destroy.Rd @@ -6,6 +6,7 @@ \usage{ tar_destroy( destroy = c("all", "meta", "process", "progress", "objects", "scratch", "workspaces"), + ask = NULL, store = targets::tar_config_get("store") ) } @@ -31,6 +32,11 @@ automatically get deleted except if R crashed. the saved workspaces of targets. See \code{\link[=tar_workspace]{tar_workspace()}} for details. }} +\item{ask}{Logical of length 1, whether to pause with a menu prompt +before deleting files. To disable this menu, set the \code{TAR_ASK} +environment variable to \code{"false"}. \code{usethis::edit_r_environ()} +can help set environment variables.} + \item{store}{Character of length 1, path to the \code{targets} data store. Defaults to \code{tar_config_get("store")}, which in turn defaults to \verb{_targets/}. diff --git a/tests/interactive/test-tar_destroy.R b/tests/interactive/test-tar_destroy.R new file mode 100644 index 000000000..2456f85d8 --- /dev/null +++ b/tests/interactive/test-tar_destroy.R @@ -0,0 +1,14 @@ +tar_test("Run tar_destroy() interactively.", { + tar_script() + tar_make() + old_tar_ask <- Sys.getenv("TAR_ASK") + Sys.setenv(TAR_ASK = "true") + expect_true(file.exists("_targets")) + tar_destroy() # See a menu and choose 2. + expect_true(file.exists("_targets")) + tar_destroy() # See a menu and choose 0. + expect_true(file.exists("_targets")) + tar_destroy() # See a menu and choose 1. + expect_false(file.exists("_targets")) + Sys.setenv(TAR_ASK = old_tar_ask) +}) diff --git a/tests/testthat/test-utils_ask.R b/tests/testthat/test-utils_ask.R index 415a1525c..835f9b411 100644 --- a/tests/testthat/test-utils_ask.R +++ b/tests/testthat/test-utils_ask.R @@ -9,9 +9,9 @@ tar_test("tar_ask_env()", { tar_test("tar_should_overwrite", { tmp <- tempfile() - expect_true(tar_should_overwrite(ask = TRUE, file = tmp)) - expect_true(tar_should_overwrite(ask = FALSE, file = tmp)) + expect_true(tar_should_overwrite(path = tmp, ask = TRUE)) + expect_true(tar_should_overwrite(path = tmp, ask = FALSE)) file.create(tmp) - expect_true(tar_should_overwrite(ask = FALSE, file = tmp)) + expect_true(tar_should_overwrite(path = tmp, ask = FALSE)) # More testing is in tests/interactive/test-tar_script.R # nolint. })