Skip to content

Commit 5bea7cf

Browse files
committed
Merge branch 'dev'
2 parents 724deb9 + cacc1b7 commit 5bea7cf

File tree

8 files changed

+224
-59
lines changed

8 files changed

+224
-59
lines changed

DESCRIPTION

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ Description: The goal of checkpoint is to solve the problem of package
1616
Immediately after completion of the rsync mirror process, the process takes a
1717
snapshot, thus creating the archive. Snapshot archives exist starting from
1818
2014-09-17.
19-
Version: 0.3.13
20-
Date: 2015-09-01
19+
Version: 0.3.14
20+
Date: 2015-09-12
2121
Author: Revolution Analytics
2222
Maintainer: Andrie de Vries <[email protected]>
2323
Copyright: Revolution Analytics
@@ -27,7 +27,7 @@ BugReports: http://www.github.com/RevolutionAnalytics/checkpoint/issues
2727
Imports:
2828
utils
2929
Depends:
30-
R(>= 3.1.1)
30+
R(>= 3.0.0)
3131
Suggests:
3232
knitr,
3333
testthat(>= 0.9),

R/checkpoint.R

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,19 @@
1313
#' \itemize{
1414
#' \item{Create a new local snapshot library to install packages. By default this library folder is at \code{~/.checkpoint}} but you can modify the path using the \code{checkpointLocation} argument.
1515
#' \item{Update the options for your CRAN mirror and point to an MRAN snapshot using \code{\link[base]{options}(repos)}}
16-
#' \item{Scan your project folder for all required packages and install them from the snapshot using \code{\link[utils]{install.packages}}}
16+
#' \item{Scan your project folder for all required packages and install them from the snapshot using \code{\link[utils]{install.packages}()}}
1717
#' }
1818
#'
1919
#' @section Resetting the checkpoint:
2020
#' To reset the checkpoint, simply restart your R session.
21+
#'
22+
#' @section Changing the default MRAN url:
23+
#'
24+
#' \code{checkpoint} uses https by default to download packages (see \link{https://www.r-consortium.org/news/blogs/2015/08/best-practices-using-r-securely}).
25+
#' \code{checkpoint} Defaults to \link{https://mran.revolutionanalytics.com/snapshot} by default in R versions 3.2.0 and later, if https support is enabled.
26+
#'
27+
#' You can modify the default URL. To change the URL, use \code{options(checkpoint.mranUrl = ...)}
28+
#'
2129
#'
2230
#' @param 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.
2331
#'
@@ -29,12 +37,22 @@
2937
#'
3038
#' @param checkpointLocation File path where the checkpoint library is stored. Default is \code{"~/"}, i.e. the user's home directory. A use case for changing this is to create a checkpoint library on a portable drive (e.g. USB drive).
3139
#'
32-
#' @param use.knitr If TRUE, uses parses all \code{Rmarkdown} files using the \code{knitr} package.
40+
#' @param use.knitr If TRUE, parses all \code{Rmarkdown} files using the \code{knitr} package.
41+
#'
42+
#' @param auto.install.knitr If TRUE and the project contains rmarkdown files, then automatically included the packages \code{knitr} and \code{rmarkdown} in packages to install.
43+
#'
44+
#' @param scan.rnw.with.knitr If TRUE, uses \code{\link[knitr]{knit}} to parse \code{.Rnw} files, otherwise use \code{\link[utils]{Sweave}}
3345
#'
3446
#' @param verbose If TRUE, displays progress messages.
3547
#'
3648
#'
37-
#' @return NULL. See the \code{Details} section for side effects.
49+
#' @return Checkpoint is called for its side-effects (see the details section), but invisibly returns a list with elements:
50+
#' \itemize{
51+
#' \item{files_not_scanned}
52+
#' \item{pkgs_found}
53+
#' \item{pkgs_not_on_mran}
54+
#' \item{pkgs_installed}
55+
#' }
3856
#'
3957
#' @export
4058
#'
@@ -45,7 +63,9 @@
4563
checkpoint <- function(snapshotDate, project = getwd(), R.version, scanForPackages = TRUE,
4664
checkpointLocation = "~/",
4765
verbose=TRUE,
48-
use.knitr = system.file(package="knitr") != "") {
66+
use.knitr = system.file(package="knitr") != "",
67+
auto.install.knitr = TRUE,
68+
scan.rnw.with.knitr = FALSE) {
4969

5070
stopIfInvalidDate(snapshotDate)
5171

@@ -63,7 +83,7 @@ checkpoint <- function(snapshotDate, project = getwd(), R.version, scanForPackag
6383
checkpointLocation = authorizeFileSystemUse(checkpointLocation)
6484

6585
fixRstudioBug()
66-
86+
6787
if(!createFolders(snapshotDate = snapshotDate, checkpointLocation = checkpointLocation))
6888
stop("Unable to create checkpoint folders at checkpointLocation = \"", checkpointLocation, "\"")
6989

@@ -89,7 +109,7 @@ checkpoint <- function(snapshotDate, project = getwd(), R.version, scanForPackag
89109

90110
if(isTRUE(scanForPackages)){
91111
mssg(verbose, "Scanning for packages used in this project")
92-
pkgs <- projectScanPackages(project, use.knitr = use.knitr)
112+
pkgs <- projectScanPackages(project, use.knitr = use.knitr, scan.rnw.with.knitr = scan.rnw.with.knitr)
93113
packages.detected <- pkgs[["pkgs"]]
94114
mssg(verbose, "- Discovered ", length(packages.detected), " packages")
95115

R/mranUrl.R

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

2-
stopIfInvalidDate <- function(snapshotDate){
2+
stopIfInvalidDate <- function(snapshotDate, verbose = TRUE){
33
if(missing(snapshotDate) || is.null(snapshotDate))
44
stop("You have to specify a snapshotDate", call. = FALSE)
55
if(!grepl("^\\d{4}-\\d{2}-\\d{2}$", snapshotDate))
@@ -9,6 +9,19 @@ stopIfInvalidDate <- function(snapshotDate){
99
if(as.Date(snapshotDate) > Sys.Date())
1010
stop("snapshotDate can not be in the future!", call. = FALSE)
1111

12+
13+
validSnapshots <- tryCatch(as.Date(getValidSnapshots()), error=function(e)e)
14+
if(inherits(validSnapshots, "error")){
15+
mssg(verbose, "Unable to connect to MRAN. Skipping some date validations.")
16+
} else {
17+
if(!as.Date(snapshotDate) %in% validSnapshots) {
18+
i <- findInterval(as.Date(snapshotDate), validSnapshots)
19+
suggestions <- validSnapshots[c(i, i+1)]
20+
stop(sprintf("Snapshot does not exist on MRAN. Try %s or %s.", validSnapshots[i], validSnapshots[i+1]))
21+
}
22+
}
23+
24+
1225
}
1326

1427
# testHttps <- function(https){
@@ -34,8 +47,8 @@ mranUrlDefault <- function(){
3447
https = gsub("http://", replacement = "https://", http)
3548
if(getRversion() >= "3.2.0" && httpsSupported()) {
3649
https
37-
# Attempt to connect
38-
# if unable to connect, stop with warning
50+
# Attempt to connect
51+
# if unable to connect, stop with warning
3952
} else {
4053
http
4154
}
@@ -117,23 +130,28 @@ libcurl <- function() isTRUE(unname(capabilities("libcurl")))
117130
url <- function(url){
118131
if(getRversion() >= "3.2.0"){
119132
method <- switch(.Platform$OS.type,
120-
"unix" = if(libcurl()) "libcurl" else "default",
121-
"windows" = "wininet",
122-
"default"
133+
"unix" = if(libcurl()) "libcurl" else "default",
134+
"windows" = "wininet",
135+
"default"
123136
)
124137
base::url(url, method = method)
125138
} else {
126139
base::url(url)
127140
}
128141
}
129142

130-
httpsSupported <- function(mran = "https://mran.revolutionanalytics.com/snapshot/"){
143+
httpsSupported <- function(mran = "https://mran.revolutionanalytics.com/snapshot"){
131144
tf <- tempfile()
132145
on.exit(unlink(tf))
133146
pdb <- suppressWarnings({
134-
tryCatch(download.file(url = paste0(mran, "PACKAGES"), destfile = tf,
135-
cacheOK = FALSE, quiet = TRUE,
136-
mode = "wb"), error = function(e)e)
147+
testfile <- paste0(mran, if(grepl("snapshot$", mran))
148+
"/2015-09-01/src/contrib/checkTimings.html" else
149+
"/src/contrib/checkTimings.html"
150+
)
151+
try(download.file(url = testfile, destfile = tf, mode = "w",
152+
cacheOK = FALSE, quiet = TRUE),
153+
silent = TRUE
154+
)
137155
})
138156
if(inherits(pdb, "error")) return(FALSE)
139157
con <- suppressWarnings({
@@ -162,7 +180,7 @@ is.404 <- function(mran){
162180
on.exit(close(con))
163181
x <- suppressWarnings(
164182
tryCatch(readLines(con, warn = FALSE),
165-
error = function(e)e)
183+
error = function(e)e)
166184
)
167185
if(inherits(x, "error")) return(TRUE)
168186
ptn <- "404.*Not Found"

R/scanRepoPackages.R

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
11

2-
projectScanPackages <- function(project = getwd(), verbose = TRUE, use.knitr = FALSE){
2+
projectScanPackages <- function(project = getwd(), verbose = TRUE, use.knitr = FALSE,
3+
auto.install.knitr = FALSE, scan.rnw.with.knitr = FALSE){
34
# detect all package dependencies for a project
45
dir <- normalizePath(project, winslash='/', mustWork=FALSE)
56
pattern <- if(!use.knitr) "\\.[rR]$|\\.[rR]nw$" else
67
"\\.[rR]$|\\.[rR]nw$|\\.[rR]md$|\\.[rR]pres$"
78

8-
ext_r <- c("R", "Rnw")
9-
ext_k <- c("Rmd", "Rpres", "Rhmtl") # knitr / rmarkdown extensions
9+
if(scan.rnw.with.knitr){
10+
ext_r <- c("R")
11+
ext_k <- c("Rmd", "Rpres", "Rhmtl", "Rnw") # knitr / rmarkdown extensions
12+
} else {
13+
ext_r <- c("R", "Rnw")
14+
ext_k <- c("Rmd", "Rpres", "Rhmtl") # knitr / rmarkdown extensions
15+
}
1016

1117
makePtn <- function(x)sprintf("\\.(%s)$", paste(c(x, tolower(x)), collapse="|"))
1218

@@ -31,12 +37,13 @@ projectScanPackages <- function(project = getwd(), verbose = TRUE, use.knitr = F
3137
list(pkgs = character(), error = character())
3238
} else {
3339
if(interactive()){
34-
z <- lapplyProgressBar(R_files, deps_by_ext, dir=dir, verbose=verbose)
40+
z <- lapplyProgressBar(R_files, deps_by_ext, dir=dir, verbose=verbose, scan.rnw.with.knitr = scan.rnw.with.knitr)
3541
} else {
36-
z <- lapply(R_files, deps_by_ext, dir=dir, verbose=verbose)
42+
z <- lapply(R_files, deps_by_ext, dir=dir, verbose=verbose, scan.rnw.with.knitr = scan.rnw.with.knitr)
3743
}
3844

3945
pkgs <- sort(unique(do.call(c, lapply(z, "[[", "pkgs"))))
46+
if(length(files_k) > 0 && auto.install.knitr) pkgs <- unique(c(pkgs, "knitr", "rmarkdown"))
4047
error <- sort(unique(do.call(c, lapply(z, "[[", "error"))))
4148
error <- gsub(sprintf("%s[//|\\]*", dir), "", error)
4249
list(pkgs = pkgs, error = error)
@@ -65,13 +72,17 @@ getFileExtension <- function(filename)tolower(gsub(".*\\.", "", filename))
6572

6673

6774
# ad-hoc dispatch based on the file extension
68-
deps_by_ext <- function(file, dir, verbose = TRUE) {
75+
deps_by_ext <- function(file, dir, verbose = TRUE, scan.rnw.with.knitr = FALSE) {
6976
file <- file.path(dir, file)
7077
fileext <- getFileExtension(file)
7178
switch(fileext,
7279
r = deps.R(file, verbose = verbose),
80+
rnw = if(scan.rnw.with.knitr){
81+
deps.Rmd(file, verbose = verbose)
82+
} else {
83+
deps.Rnw(file, verbose = verbose)
84+
},
7385
rmd = deps.Rmd(file, verbose = verbose),
74-
rnw = deps.Rnw(file, verbose = verbose),
7586
rpres = deps.Rpres(file, verbose = verbose),
7687
txt = deps.txt(file, verbose = verbose),
7788
stop("Unrecognized file type '", file, "'")
@@ -80,13 +91,13 @@ deps_by_ext <- function(file, dir, verbose = TRUE) {
8091

8192
deps.Rmd <- deps.Rpres <- function(file, verbose=TRUE) {
8293
tempfile <- tempfile(fileext = ".Rmd")
83-
on.exit(unlink(tempfile))
94+
showErrors <- getOption("show.error.messages")
95+
options("show.error.messages" = FALSE)
96+
on.exit({unlink(tempfile); options("show.error.messages" = showErrors)})
8497
stopifnot(requireNamespace("knitr"))
85-
p <- tryCatch(
86-
suppressWarnings(suppressMessages(
87-
knitr::knit(file, output = tempfile, tangle = TRUE, quiet = TRUE)
88-
)),
89-
error = function(e) e
98+
p <- try(
99+
knitr::knit(file, output = tempfile, tangle = TRUE, quiet = TRUE),
100+
silent = TRUE
90101
)
91102

92103
if(inherits(p, "error")) {
@@ -102,12 +113,12 @@ deps.Rmd <- deps.Rpres <- function(file, verbose=TRUE) {
102113

103114
deps.Rnw <- function(file, verbose=TRUE) {
104115
tempfile <- tempfile(fileext = ".Rnw")
105-
on.exit(unlink(tempfile))
106-
p <- tryCatch(
107-
suppressWarnings(suppressMessages(
108-
Stangle(file, output = tempfile, quiet = TRUE)
109-
)),
110-
error = function(e) e
116+
showErrors <- getOption("show.error.messages")
117+
options("show.error.messages" = FALSE)
118+
on.exit({unlink(tempfile); options("show.error.messages" = showErrors)})
119+
p <- try(
120+
Stangle(file, output = tempfile, quiet = TRUE),
121+
silent = TRUE
111122
)
112123
if(inherits(p, "error")) {
113124
return(list(pkgs=character(), error=file))
@@ -121,7 +132,6 @@ deps.Rnw <- function(file, verbose=TRUE) {
121132
}
122133

123134
deps.R <- deps.txt <- function(file, verbose=TRUE) {
124-
125135
if (!file.exists(file)) {
126136
warning("No file at path '", file, "'.")
127137
return(list(pkgs=character(), error=file))

man/checkpoint.Rd

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
\usage{
77
checkpoint(snapshotDate, project = getwd(), R.version,
88
scanForPackages = TRUE, checkpointLocation = "~/", verbose = TRUE,
9-
use.knitr = system.file(package = "knitr") != "")
9+
use.knitr = system.file(package = "knitr") != "",
10+
auto.install.knitr = TRUE, scan.rnw.with.knitr = FALSE)
1011
}
1112
\arguments{
1213
\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.}
@@ -21,10 +22,20 @@ checkpoint(snapshotDate, project = getwd(), R.version,
2122
2223
\item{verbose}{If TRUE, displays progress messages.}
2324
24-
\item{use.knitr}{If TRUE, uses parses all \code{Rmarkdown} files using the \code{knitr} package.}
25+
\item{use.knitr}{If TRUE, parses all \code{Rmarkdown} files using the \code{knitr} package.}
26+
27+
\item{auto.install.knitr}{If TRUE and the project contains rmarkdown files, then automatically included the packages \code{knitr} and \code{rmarkdown} in packages to install.}
28+
29+
\item{scan.rnw.with.knitr}{If TRUE, uses \code{\link[knitr]{knit}} to parse \code{.Rnw} files, otherwise use \code{\link[utils]{Sweave}}}
2530
}
2631
\value{
27-
NULL. See the \code{Details} section for side effects.
32+
Checkpoint is called for its side-effects (see the details section), but invisibly returns a list with elements:
33+
\itemize{
34+
\item{files_not_scanned}
35+
\item{pkgs_found}
36+
\item{pkgs_not_on_mran}
37+
\item{pkgs_installed}
38+
}
2839
}
2940
\description{
3041
Together, the checkpoint package and the checkpoint server act as a CRAN time machine. The \code{checkpoint()} function installs the packages referenced in the specified project to a local library exactly as they existed at the specified point in time. Only those packages are available to your session, thereby avoiding any package updates that came later and may have altered your results. In this way, anyone using the checkpoint \code{checkpoint()} function can ensure the reproducibility of your scripts or projects at any time.
@@ -41,14 +52,23 @@ Specifically, the function will:
4152
\itemize{
4253
\item{Create a new local snapshot library to install packages. By default this library folder is at \code{~/.checkpoint}} but you can modify the path using the \code{checkpointLocation} argument.
4354
\item{Update the options for your CRAN mirror and point to an MRAN snapshot using \code{\link[base]{options}(repos)}}
44-
\item{Scan your project folder for all required packages and install them from the snapshot using \code{\link[utils]{install.packages}}}
55+
\item{Scan your project folder for all required packages and install them from the snapshot using \code{\link[utils]{install.packages}()}}
4556
}
4657
}
4758
4859
\section{Resetting the checkpoint}{
4960
5061
To reset the checkpoint, simply restart your R session.
5162
}
63+
64+
\section{Changing the default MRAN url}{
65+
66+
67+
\code{checkpoint} uses https by default to download packages (see \link{https://www.r-consortium.org/news/blogs/2015/08/best-practices-using-r-securely}).
68+
\code{checkpoint} Defaults to \link{https://mran.revolutionanalytics.com/snapshot} by default in R versions 3.2.0 and later, if https support is enabled.
69+
70+
You can modify the default URL. To change the URL, use \code{options(checkpoint.mranUrl = ...)}
71+
}
5272
\examples{
5373
\dontrun{
5474

0 commit comments

Comments
 (0)