Skip to content

Commit 146533c

Browse files
committed
Merge branch 'dev' into release
2 parents 88171fe + fd5b724 commit 146533c

13 files changed

+301
-69
lines changed

.travis.yml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
language: c
22

3+
env: NOT_CRAN="true"
4+
35
before_install:
46
- curl -OL http://raw.github.com/craigcitro/r-travis/master/scripts/travis-tool.sh
57
- chmod 755 ./travis-tool.sh
@@ -13,6 +15,9 @@ script: ./travis-tool.sh run_tests
1315
on_failure:
1416
- ./travis-tool.sh dump_logs
1517

18+
after_script:
19+
- ./travis-tool.sh dump_logs
20+
1621
branches:
1722
only:
1823
- master
@@ -22,4 +27,5 @@ branches:
2227
notifications:
2328
email:
2429
on_success: change
25-
on_failure: change
30+
on_failure: change
31+

DESCRIPTION

Lines changed: 4 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, we take a
1717
snapshot, thus creating the archive. Snapshot archives exist starting from
1818
2014-09-17.
19-
Version: 0.3.7
20-
Date: 2015-02-02
19+
Version: 0.3.8
20+
Date: 2015-02-12
2121
Author: Revolution Analytics
2222
Maintainer: Andrie de Vries <[email protected]>
2323
Copyright: Revolution Analytics
@@ -30,5 +30,6 @@ Depends:
3030
R(>= 3.1.1)
3131
Suggests:
3232
knitr,
33-
testthat(>= 0.9)
33+
testthat(>= 0.9),
34+
MASS
3435
VignetteBuilder: knitr

NAMESPACE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Generated by roxygen2 (4.1.0): do not edit by hand
1+
# Generated by roxygen2 (4.0.2): do not edit by hand
22

33
export(checkpoint)
44
importFrom(utils,install.packages)

R/checkpoint.R

Lines changed: 62 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@
66
#'
77
#' \code{checkpoint()} creates a local library into which it installs a copy of the packages required by your project as they existed on CRAN on the specified snapshot date. Your R session is updated to use only these packages.
88
#'
9-
#' To automatically determine all packages used in your project, the function scans all R code (\code{.R}, \code{.Rmd}, and \code{.Rpres} files) for \code{library()} and \code{requires()} statements.
9+
#' To automatically determine all packages used in your project, the function scans all R code (\code{.R}, \code{.Rmd}, and \code{.Rpres} files) for \code{\link{library}()} and \code{\link{require}()} statements. In addition, scans for occurrences of code that accesses functions in namespaces using \code{package}\code{\link[base]{::}}\code{foo()} and \code{package}\code{\link[base]{:::}}\code{foo()}. Finally, any occurrences of the functions \code{\link[methods]{setClass}}, \code{\link[methods]{setRefClass}}, \code{\link[methods]{setMethod}} or \code{\link[methods]{setGeneric}} will also identify the \code{methods} package as a dependency.
1010
#'
1111
#' Specifically, the function will:
1212
#'
1313
#' \itemize{
14-
#' \item{Create a new local snapshot library to install packages. This library folder is at \code{~/.checkpoint}}
15-
#' \item{Update the options for your CRAN mirror and point to an MRAN snapshot using \code{options(repos)}}
14+
#' \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.
15+
#' \item{Update the options for your CRAN mirror and point to an MRAN snapshot using \code{\link[base]{options}(repos)}}
1616
#' \item{Scan your project folder for all required packages and install them from the snapshot using \code{\link[utils]{install.packages}}}
1717
#' }
1818
#'
@@ -23,8 +23,12 @@
2323
#'
2424
#' @param project A project path. This is the path to the root of the project that references the packages to be installed from the MRAN snapshot for the date specified for \code{snapshotDate}. Defaults to current working directory using \code{\link{getwd}()}.
2525
#'
26-
#' @param R.version Optional character string, e.g. "3.1.2". If specified, compares the current R.version to the specified R.version, and warns if these are different. This argument allows the original script author to specify a specific version of R to obtain the desired results.
26+
#' @param R.version Optional character string, e.g. "3.1.2". If specified, compares the current \code{\link[base]{R.version}} to the specified R.version. If these differ, stops processing with an error, making no changes to the system. Specifically, if the check fails, the library path is NOT modified. This argument allows the original script author to specify a specific version of R to obtain the desired results.
2727
#'
28+
#' @param scanForPackages If TRUE, scans for packages in project folder (see details). If FALSE, skips the scanning process. A use case for \code{scanForPackages = FALSE} is to skip the scanning and installation process, e.g. in production environments with a large number of R scripts in the project. Only set \code{scanForPackages = FALSE} if you are certain that all package dependencies are already in the checkpoint folder.
29+
#'
30+
#' @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).
31+
#'
2832
#' @param use.knitr If TRUE, uses parses all \code{Rmarkdown} files using the \code{knitr} package.
2933
#'
3034
#' @param verbose If TRUE, displays progress messages.
@@ -38,7 +42,8 @@
3842
#'
3943
#' @importFrom utils install.packages
4044

41-
checkpoint <- function(snapshotDate, project = getwd(), R.version,
45+
checkpoint <- function(snapshotDate, project = getwd(), R.version, scanForPackages = TRUE,
46+
checkpointLocation = "~/",
4247
verbose=TRUE,
4348
use.knitr = system.file(package="knitr") != "") {
4449

@@ -53,51 +58,71 @@ checkpoint <- function(snapshotDate, project = getwd(), R.version,
5358
}
5459
}
5560

56-
createFolders(snapshotDate)
61+
fixRstudioBug()
62+
63+
if(!createFolders(snapshotDate = snapshotDate, checkpointLocation = checkpointLocation))
64+
stop("Unable to create checkpoint folders at checkpointLocation = \"", checkpointLocation, "\"")
65+
66+
5767
snapshoturl <- getSnapshotUrl(snapshotDate=snapshotDate)
5868

5969

6070
compiler.path <- system.file(package = "compiler", lib.loc = .Library[1])
6171
# set repos
6272
setMranMirror(snapshotUrl = snapshoturl)
6373

64-
# Set lib path
65-
setLibPaths(snapshotDate)
66-
67-
if(.Platform$OS.type == "windows"){
68-
dir.create(file.path(.libPaths(), "compiler"), showWarnings = FALSE)
69-
file.copy(to = .libPaths(), from = compiler.path, recursive = TRUE)
70-
} else {
71-
if(! "compiler" %in% installed.packages()[, "Package"]) {
72-
install.packages(repos = NULL, pkgs = compiler.path, type = "source")
73-
}
74-
}
74+
libPath <- checkpointPath(snapshotDate, type = "lib", checkpointLocation = checkpointLocation)
75+
installMissingBasePackages()
7576

77+
# Set lib path
78+
setLibPaths(libPath = libPath)
79+
7680
# Scan for packages used
77-
mssg(verbose, "Scanning for packages used in this project")
7881
exclude.packages = c("checkpoint", # this very package
7982
c("base", "compiler", "datasets", "graphics", "grDevices", "grid",
8083
"methods", "parallel", "splines", "stats", "stats4", "tcltk",
8184
"tools", "utils")) # all base priority packages, not on CRAN or MRAN
8285
packages.installed <- unname(installed.packages()[, "Package"])
8386

84-
pkgs <- projectScanPackages(project, use.knitr = use.knitr)
85-
packages.detected <- pkgs[["pkgs"]]
86-
87-
mssg(verbose, "- Discovered ", length(packages.detected), " packages")
88-
89-
if(length(pkgs[["error"]]) > 0){
90-
mssg(verbose, "Unable to parse ", length(pkgs[["error"]]), " files:")
91-
for(file in pkgs[["error"]]) mssg(verbose, "- ", file)
87+
if(isTRUE(scanForPackages)){
88+
mssg(verbose, "Scanning for packages used in this project")
89+
pkgs <- projectScanPackages(project, use.knitr = use.knitr)
90+
packages.detected <- pkgs[["pkgs"]]
91+
mssg(verbose, "- Discovered ", length(packages.detected), " packages")
92+
93+
if(length(pkgs[["error"]]) > 0){
94+
files.not.parsed <- pkgs[["error"]]
95+
mssg(verbose, "Unable to parse ", length(pkgs[["error"]]), " files:")
96+
for(file in files.not.parsed) mssg(verbose, "- ", file)
97+
} else {
98+
files.not.parsed <- character(0)
99+
}
100+
} else {
101+
packages.detected <- character(0)
102+
files.not.parsed <- character(0)
92103
}
93104

105+
94106
packages.to.install <- setdiff(packages.detected, c(packages.installed, exclude.packages))
95107

96108
# detach checkpointed pkgs already loaded
97109

98110
packages.in.search <- findInSearchPath(packages.to.install)
99111
detachFromSearchPath(packages.in.search)
100112

113+
# check if packages are available in snapshot
114+
115+
if(length(packages.to.install) > 0) {
116+
not.available <- !packages.to.install %in% available.packages()[, "Package"]
117+
if(sum(not.available > 0)){
118+
mssg(verbose, "Packages not available in repository and won't be installed:")
119+
for(pkg in packages.to.install[not.available]) mssg(verbose, " - ", pkg)
120+
packages.to.install <- packages.to.install[!not.available]
121+
}
122+
} else {
123+
not.available <- character(0)
124+
}
125+
101126
# install missing packages
102127

103128
if(length(packages.to.install) > 0) {
@@ -115,7 +140,7 @@ checkpoint <- function(snapshotDate, project = getwd(), R.version,
115140
} else if(length(packages.detected > 0)){
116141
mssg(verbose, "All detected packages already installed")
117142
} else {
118-
mssg(verbose, "No packages found to install")
143+
if(isTRUE(scanForPackages)) mssg(verbose, "No packages found to install")
119144
}
120145

121146
# Reload detached packages
@@ -125,13 +150,20 @@ checkpoint <- function(snapshotDate, project = getwd(), R.version,
125150

126151
mssg(verbose, "checkpoint process complete")
127152
mssg(verbose, "---")
128-
invisible(NULL)}
153+
154+
z <- list(
155+
files_not_scanned = files.not.parsed,
156+
pkgs_found = packages.detected,
157+
pkgs_not_on_mran = names(not.available)[not.available],
158+
pkgs_installed = packages.to.install
159+
)
160+
invisible(z)}
129161

130162
setMranMirror <- function(snapshotDate, snapshotUrl = checkpoint:::getSnapShotUrl(snapshotDate)){
131163
options(repos = snapshotUrl)}
132164

133-
setLibPaths <- function(snapshotDate, libPath=checkpointPath(snapshotDate, "lib")){
134-
assign(".lib.loc", libPath, envir = environment(.libPaths))}
165+
setLibPaths <- function(snapshotDate, libPath=checkpointPath(snapshotDate, type = "lib")){
166+
assign(".lib.loc", c(libPath, checkpointBasePkgs()), envir = environment(.libPaths))}
135167

136168
mranUrl <- function()"http://mran.revolutionanalytics.com/snapshot/"
137169

R/checkpoint_paths.R

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,33 @@
1-
checkpointPath <- function(snapshotDate, type = c("lib", "src", "snapshotDir", "rootDir", "rootfile")){
2-
rootDir <- normalizePath(
3-
file.path("~", ".checkpoint"),
1+
2+
checkpointPath <- function(snapshotDate, checkpointLocation = "~/",
3+
type = c("lib", "src", "snapshot", "root", "base")){
4+
rootPath <- normalizePath(
5+
file.path(checkpointLocation, ".checkpoint"),
46
mustWork = FALSE)
57
type <- match.arg(type)
6-
snapshotDir = file.path(rootDir, snapshotDate)
7-
libPath <-file.path(snapshotDir, "lib", R.version$platform, base::getRversion())
8-
srcPath <- file.path(libPath, "src/contrib")
9-
rootFile <- file.path(rootDir, "checkpoint.txt")
8+
if(type == "base") return(
9+
normalizePath(
10+
file.path(rootPath, paste0("R-", getRversion())),
11+
winslash = "/", mustWork = FALSE)
12+
)
13+
snapshotPath <- file.path(rootPath, snapshotDate)
14+
libPath <- file.path(snapshotPath, "lib", R.version$platform, base::getRversion())
15+
srcPath <- file.path(libPath, "src/contrib")
1016
normalizePath(
1117
switch(
1218
type,
13-
lib = libPath,
14-
src = srcPath,
15-
rootDir = rootDir,
16-
snapshotDir = snapshotDir,
17-
rootFile = rootFile),
19+
root = rootPath,
20+
lib = libPath,
21+
src = srcPath,
22+
snapshot = snapshotPath
23+
),
24+
winslash = "/",
1825
mustWork = FALSE)}
1926

20-
createFolders <- function(snapshotDate){
21-
paths =
22-
sapply(c("rootDir", "lib", "src"), checkpointPath, snapshotDate = snapshotDate)
23-
sapply(paths, function(x) if(!file.exists(x)) dir.create(x, recursive=TRUE))}
27+
createFolders <- function(snapshotDate, checkpointLocation = "~/"){
28+
paths <- sapply(c("root", "lib", "src"), checkpointPath,
29+
snapshotDate = snapshotDate,
30+
checkpointLocation = checkpointLocation)
31+
sapply(paths, function(x) if(!file.exists(x)) dir.create(x, recursive=TRUE, showWarnings = FALSE))
32+
all(file.exists(paths))
33+
}

R/fixRstudioBug.R

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
# Temporary fix for rstudio bug reported at https://support.rstudio.com/hc/communities/public/questions/203052576-setting-libpath-in-Rstudio
2+
3+
fixRstudioBug <- function(){
4+
.rs.uniqueLibraryPaths <- .rs.pathPackage <- .rs.packageVersion <- .rs.createAliasedPath <- .rs.addFunction <- NULL
5+
rm(.rs.uniqueLibraryPaths, .rs.pathPackage, .rs.packageVersion, .rs.createAliasedPath, .rs.addFunction)
6+
7+
if("tools:rstudio" %in% search()){
8+
9+
expected <- function (){
10+
uniqueLibPaths <- .rs.uniqueLibraryPaths()
11+
x <- suppressWarnings(library(lib.loc = uniqueLibPaths))
12+
x <- x$results[x$results[, 1] != "base", ]
13+
pkgs.name <- x[, 1]
14+
pkgs.library <- x[, 2]
15+
pkgs.desc <- x[, 3]
16+
pkgs.url <- file.path("help/library", pkgs.name, "html",
17+
"00Index.html")
18+
loaded.pkgs <- .rs.pathPackage()
19+
pkgs.loaded <- !is.na(match(normalizePath(paste(pkgs.library,
20+
pkgs.name, sep = "/")), loaded.pkgs))
21+
instPkgs <- as.data.frame(installed.packages(), stringsAsFactors = F)
22+
pkgs.version <- character(length = length(pkgs.name))
23+
for (i in 1:length(pkgs.name)) {
24+
pkgs.version[[i]] <- .rs.packageVersion(pkgs.name[[i]],
25+
pkgs.library[[i]], instPkgs)
26+
}
27+
pkgs.library <- .rs.createAliasedPath(pkgs.library)
28+
packages = data.frame(name = pkgs.name, library = pkgs.library,
29+
version = pkgs.version, desc = pkgs.desc, url = pkgs.url,
30+
loaded = pkgs.loaded, check.rows = TRUE, stringsAsFactors = FALSE)
31+
packages[order(packages$name), ]
32+
}
33+
34+
if(
35+
isTRUE(
36+
all.equal(expected, get(".rs.listInstalledPackages"))
37+
)
38+
)
39+
.rs.addFunction("listInstalledPackages", function()
40+
{
41+
# calculate unique libpaths
42+
uniqueLibPaths <- .rs.uniqueLibraryPaths()
43+
44+
# get packages
45+
x <- suppressWarnings(library(lib.loc=uniqueLibPaths))
46+
x <- x$results[x$results[, 1] != "base", , drop=FALSE]
47+
48+
49+
# extract/compute required fields
50+
pkgs.name <- x[, 1]
51+
pkgs.library <- x[, 2]
52+
pkgs.desc <- x[, 3]
53+
pkgs.url <- file.path("help/library",
54+
pkgs.name,
55+
"html",
56+
"00Index.html")
57+
loaded.pkgs <- .rs.pathPackage()
58+
pkgs.loaded <- !is.na(match(normalizePath(
59+
paste(pkgs.library,pkgs.name, sep="/")),
60+
loaded.pkgs))
61+
62+
63+
# build up vector of package versions
64+
instPkgs <- as.data.frame(installed.packages(), stringsAsFactors=F)
65+
pkgs.version <- character(length=length(pkgs.name))
66+
for (i in 1:length(pkgs.name)) {
67+
pkgs.version[[i]] <- .rs.packageVersion(pkgs.name[[i]],
68+
pkgs.library[[i]],
69+
instPkgs)
70+
}
71+
72+
# alias library paths for the client
73+
pkgs.library <- .rs.createAliasedPath(pkgs.library)
74+
75+
# return data frame sorted by name
76+
packages = data.frame(name=pkgs.name,
77+
library=pkgs.library,
78+
version=pkgs.version,
79+
desc=pkgs.desc,
80+
url=pkgs.url,
81+
loaded=pkgs.loaded,
82+
check.rows = FALSE,
83+
stringsAsFactors = FALSE)
84+
85+
# sort and return
86+
packages[order(packages$name),]
87+
})
88+
89+
}
90+
}

R/installMissingBasePackages.R

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
checkpointBasePkgs <- function(checkpointLocation = "~/"){
2+
checkpointPath(checkpointLocation = checkpointLocation, type = "base")
3+
}
4+
5+
basePkgLocations <- function(lib = .Library){
6+
pkgFolder <- function(x) dirname(normalizePath(base::system.file(package=x, lib.loc=lib)))
7+
bp <- installed.packages(priority="base", lib.loc = lib)[, "Package"]
8+
locations <- vapply(bp, pkgFolder, FUN.VALUE = character(1))
9+
w <- locations != pkgFolder("base")
10+
w["compiler"] <- TRUE # Ensure compiler is always copied
11+
locations[w]
12+
}
13+
14+
installCompiler <- function(libpath){
15+
pkg <- "checkpoint"
16+
to.dir <- file.path(libpath, pkg)
17+
compiler.path <- system.file(package = pkg, lib.loc = .Library)
18+
dir.create(to.dir, showWarnings = FALSE, recursive = TRUE)
19+
file.copy(to = to.dir, from = compiler.path, recursive = TRUE)
20+
}
21+
22+
23+
installMissingBasePackages <- function(){
24+
missingBase <- basePkgLocations()
25+
if(length(missingBase)){
26+
for(i in seq_along(missingBase)){
27+
pkg <- missingBase[i]
28+
to.dir <- file.path(checkpointBasePkgs(), names(pkg))
29+
dir.create(to.dir, showWarnings = FALSE, recursive = TRUE)
30+
file.copy(to = checkpointBasePkgs(), from = file.path(unname(pkg), names(pkg)), recursive = TRUE)
31+
}
32+
}
33+
}

0 commit comments

Comments
 (0)