Created
January 22, 2019 06:29
-
-
Save briatte/14e47fb0cfb8801f25c889edea3fcd9b to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# ============================================================================== | |
# SESSION_INFO | |
# | |
# A script to deal with package dependencies that will | |
# | |
# - detach all packages except base ones | |
# - install its own package dependencies | |
# - look for session_info.txt and parse it for packages | |
# - ensure the packages are installed and up to date | |
# | |
# Input: | |
# | |
# - a session_info.txt file must be present in the working directory | |
# - it should be formatted like the results of sessioninfo::session_info() | |
# | |
# Output: | |
# | |
# - packages listed in session_info.txt will be installed or updated if needed | |
# | |
# Limitations: | |
# | |
# - works only on CRAN and GitHub packages | |
# | |
# ============================================================================== | |
cran_link <- "https://cran.rstudio.com/" | |
installed <- utils::installed.packages()[, c("Version") ] | |
# ============================================================================== | |
# DETACH ALL NON-BASE PACKAGES | |
# | |
# Adapted from code by Romain François [1] and Zach Burchill [2] | |
# [1]: https://github.com/romainfrancois/nothing | |
# [2]: https://github.com/burchill/nothing | |
# | |
# ============================================================================== | |
suppressMessages( | |
repeat{ | |
p <- setdiff(loadedNamespaces(), sessionInfo()$basePkgs) | |
if (!length(p)) break | |
for (i in p) { | |
try(unloadNamespace(i), silent = TRUE) | |
} | |
} | |
) | |
# ============================================================================== | |
# INSTALL DEPENDENCIES FROM CRAN | |
# | |
# - remotes lighter version of devtools::install_* | |
# needed to run this script ................................ yes | |
# | |
# - sessioninfo more complete version of utils::sessionInfo | |
# needed to run this script ................................ no | |
# | |
# ============================================================================== | |
for (i in c("remotes", "sessioninfo")) { | |
if (!(i %in% names(installed))) { | |
install.packages(i, repos = cran_link) | |
} | |
} | |
# ============================================================================== | |
# PARSE SESSION INFO | |
# ============================================================================== | |
f <- c("session_info.txt") | |
if (file.exists(f)) { | |
f <- readLines(f) | |
p <- f[ grep("package(.*)version(.*)source", f) ] | |
stopifnot(length(p) == 1) | |
find_column <- function(pattern, x) { | |
x <- regexpr(paste0(pattern, "\\s+"), x) | |
c(x, x + attr(x, "match.length") - 1) | |
} | |
find_packages <- find_column("package", p) | |
find_versions <- find_column("version", p) | |
find_sources <- find_column("source", p) | |
# trim beginning | |
f <- f[ which(f == p):length(f) ] | |
# trim end | |
f <- f[ 2:(grep("^$", f) - 1) ] | |
find_string <- function(x, positions) { | |
x <- substr(x, start = positions[1], stop = positions[2]) | |
gsub("(.*?)\\s+$", "\\1", x) | |
} | |
f <- data.frame( | |
package = vapply(f, find_string, character(1), find_packages), | |
version = vapply(f, find_string, character(1), find_versions), | |
source = vapply(f, find_string, character(1), find_sources), | |
stringsAsFactors = FALSE, | |
row.names = NULL | |
) | |
# ============================================================================ | |
# FIND IF PACKAGES NEED TO BE INSTALLED OR UPDATED | |
# ============================================================================ | |
# is package missing? if so, flag it for installation | |
f$install <- !f$package %in% names(installed) | |
# if not, get package version | |
f$update <- 0L | |
f$update[ !f$install ] <- vapply(f$package[ !f$install ], function(x) { | |
as.character(packageVersion(x)) | |
}, character(1)) | |
# now, is it at least as recent as the one from session_info.txt? | |
f$update[ !f$install ] <- mapply( | |
compareVersion, | |
f$version[ !f$install ], | |
f$update[ !f$install ] | |
) | |
# if not, flag it for installation | |
f$install[ !f$install ] <- f$update[ !f$install ] > 0 | |
rm(find_column, find_string, find_packages, find_versions, find_sources) | |
# ============================================================================ | |
# INSTALL WHATEVER PACKAGES NEED TO BE | |
# ============================================================================ | |
p <- which(f$install & grepl("^(CRAN|[Gg]it[Hh]ub)", f$source)) | |
if (length(p) > 0) { | |
message( | |
"Installing or updating ", length(p), | |
" package(s) out of ", nrow(f), " checked" | |
) | |
for (i in p) { | |
if(grepl("^CRAN", f$source[i])) { | |
remotes::install_cran(f$package[i], repos = cran_link, upgrade = TRUE) | |
} | |
else if (grepl("^[Gg]it[Hh]ub", f$source[i])) { | |
i <- gsub("[Gg]it[Hh]ub\\s\\(|@(.*)$", "", f$source[i]) | |
remotes::install_github(i, upgrade = TRUE) | |
} | |
else { | |
message("Skipping package ", i, " (unsupported remote source)") | |
} | |
} | |
} else { | |
message( | |
"All ", nrow(f), " package(s) from session_info.txt are installed ", | |
"and up to date." | |
) | |
} | |
if (any(f$update < 0)) { | |
p <- f$package[ f$update < 0 ] | |
warning( | |
length(p), " package(s) in session_info.txt is/are older ", | |
"than those installed:\n ", paste0(p, collapse = ", ") | |
) | |
} | |
} else { | |
warning( | |
"No session_info.txt found in current working directory.\n ", | |
"No checks performed." | |
) | |
} | |
rm(i, f, p) | |
rm(cran_link, installed) | |
gc(verbose = FALSE) | |
if (!interactive()) | |
q("no") | |
# kthxbye |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# ============================================================================== | |
# SESSION_SAVE | |
# | |
# Saves session information to session_info.txt | |
# Requires the sessioninfo package | |
# | |
# ============================================================================== | |
sink("session_info.txt", append = FALSE) | |
# print() needed to work when used with 'Source on Save' in RStudio | |
# without it, sink() will save an empty file | |
print(sessioninfo::session_info()) | |
sink() | |
if (!interactive()) | |
q("no") | |
# kthxbye |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment