From 774c8d0366660331d1e9ce5e69e2548d11ab88f8 Mon Sep 17 00:00:00 2001 From: Andrie de Vries Date: Fri, 28 Oct 2016 16:33:23 +0100 Subject: [PATCH] Checks if the project looks like an R project and asks for confirmation. #227 --- R/checkpoint.R | 34 ++++++++++++++++++++++++++++++++-- R/checkpoint_paths.R | 3 ++- man/checkpoint.Rd | 6 ++++-- 3 files changed, 38 insertions(+), 5 deletions(-) diff --git a/R/checkpoint.R b/R/checkpoint.R index 38d010a..8778130 100644 --- a/R/checkpoint.R +++ b/R/checkpoint.R @@ -54,8 +54,10 @@ #' #' @param verbose If TRUE, displays progress messages. #' -#' @param forceInstall If TRUE. forces the re-installation of all discovered packages and their dependencies. This is useful if, for some reason, the checkpoint archive becomes corrupted. +#' @param forceInstall If TRUE, forces the re-installation of all discovered packages and their dependencies. This is useful if, for some reason, the checkpoint archive becomes corrupted. #' +#' @param forceProject If TRUE, forces the checkpoint process, even if the provided project folder doesn't look like an R project. A commonly reported user problem is that they accidentally trigger the checkpoint process from their home folder, resulting in scanning many R files and downloading many packages. To prevent this, we use a heuristic to determine if the project folder looks like an R project. If the project folder is the home folder, and also contains no R files, then \code{checkpoint()} asks for confirmation to continue. + #' #' @return Checkpoint is called for its side-effects (see the details section), but invisibly returns a list with elements: #' \itemize{ @@ -78,7 +80,10 @@ checkpoint <- function(snapshotDate, project = getwd(), R.version, scanForPackag use.knitr = system.file(package="knitr") != "", auto.install.knitr = TRUE, scan.rnw.with.knitr = FALSE, - forceInstall = FALSE) { + forceInstall = FALSE, + forceProject = FALSE) { + + if(interactive()) validateProjectFolder(project) stopIfInvalidDate(snapshotDate) @@ -240,3 +245,28 @@ mssg <- function(x, ...) if(x) message(...) correctR <- function(x) compareVersion(as.character(utils::packageVersion("base")), x) == 0 + +# Scans for R files in a folder and the first level subfolders. +# +anyRfiles <- function(path = "."){ + findRfiles <- function(path = "."){ + pattern <- "\\.[rR]$|\\.[rR]nw$|\\.[rR]md$|\\.[rR]pres$|\\.[rR]proj$" + z <- list.files(path = path, pattern = pattern, full.names = TRUE) + normalizePath(z, winslash = "/") + } + dirs <- list.dirs(path = path, recursive = FALSE) + rfiles <- as.vector(unlist(sapply(dirs, findRfiles))) + length(rfiles) > 0 +} + +validateProjectFolder <- function(project) { + if(normalizePath(project) == normalizePath("~/") && !anyRfiles(project)){ + message("This doesn't look like an R project directory.\n", + "Use forceProject = TRUE to force scanning" + ) + answer = readline("Continue (y/n)? ") + if(tolower(answer) != "y"){ + stop("Scanning stopped.", call. = FALSE) + } + } +} diff --git a/R/checkpoint_paths.R b/R/checkpoint_paths.R index 620fef6..62ba49d 100644 --- a/R/checkpoint_paths.R +++ b/R/checkpoint_paths.R @@ -44,7 +44,8 @@ authorizeFileSystemUse = stop("Can't use a non-directory as checkpoint root")} else { if(interactive()) { - answer = readline(paste("Can I create directory", checkpointRoot, "for internal checkpoint use?(y/n)\n")) + message(paste("Can I create directory", checkpointRoot, "for internal checkpoint use?\n")) + answer = readline("Continue (y/n)? ") if(tolower(answer) != "y") stop("Cannot proceed without access to checkpoint directory")} else { diff --git a/man/checkpoint.Rd b/man/checkpoint.Rd index 3d305de..9b522cf 100644 --- a/man/checkpoint.Rd +++ b/man/checkpoint.Rd @@ -8,7 +8,7 @@ checkpoint(snapshotDate, project = getwd(), R.version, scanForPackages = TRUE, checkpointLocation = "~/", verbose = TRUE, use.knitr = system.file(package = "knitr") != "", auto.install.knitr = TRUE, scan.rnw.with.knitr = FALSE, - forceInstall = FALSE) + forceInstall = FALSE, forceProject = FALSE) } \arguments{ \item{snapshotDate}{Date of snapshot to use in \code{YYYY-MM-DD} format,e.g. \code{"2014-09-17"}. Specify a date on or after \code{"2014-09-17"}. MRAN takes one snapshot per day.} @@ -29,7 +29,9 @@ checkpoint(snapshotDate, project = getwd(), R.version, \item{scan.rnw.with.knitr}{If TRUE, uses \code{\link[knitr]{knit}} to parse \code{.Rnw} files, otherwise use \code{\link[utils]{Sweave}}} -\item{forceInstall}{If TRUE. forces the re-installation of all discovered packages and their dependencies. This is useful if, for some reason, the checkpoint archive becomes corrupted.} +\item{forceInstall}{If TRUE, forces the re-installation of all discovered packages and their dependencies. This is useful if, for some reason, the checkpoint archive becomes corrupted.} + +\item{forceProject}{If TRUE, forces the checkpoint process, even if the provided project folder doesn't look like an R project. A commonly reported user problem is that they accidentally trigger the checkpoint process from their home folder, resulting in scanning many R files and downloading many packages. To prevent this, we use a heuristic to determine if the project folder looks like an R project. If the project folder is the home folder, and also contains no R files, then \code{checkpoint()} asks for confirmation to continue.} } \value{ Checkpoint is called for its side-effects (see the details section), but invisibly returns a list with elements: