Skip to content

Instantly share code, notes, and snippets.

@bearloga
Last active October 8, 2020 12:46
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 8 You must be signed in to fork a gist
  • Save bearloga/7c9078b493e7afb0ca46d5d16bd1aba4 to your computer and use it in GitHub Desktop.
Save bearloga/7c9078b493e7afb0ca46d5d16bd1aba4 to your computer and use it in GitHub Desktop.
The script can be used to re-install packages after upgrading R (on Linux or Mac), since libraries cannot be reused between different minor versions (e.g. when upgrading 3.2.3 to 3.3.2). It detects when a package was installed from CRAN vs GitHub/Git and re-installs it using the appropriate func. Usage: `Rscript upgrade_packages.R`
# WMF only:
if (file.exists("/etc/wikimedia-cluster")) {
message('Detected that this script is being run on a WMF machine ("', Sys.info()["nodename"], '"). Setting proxies...')
Sys.setenv("http_proxy" = "http://webproxy.eqiad.wmnet:8080")
Sys.setenv("https_proxy" = "http://webproxy.eqiad.wmnet:8080")
}
# General use:
message("Checking for a personal library...")
if (!dir.exists(Sys.getenv("R_LIBS_USER"))) {
warning("Personal library not found, creating one...")
dir.create(Sys.getenv("R_LIBS_USER"), recursive = TRUE)
message("Registering newly created personal library...")
.libPaths(Sys.getenv("R_LIBS_USER"))
} else {
message("Personal library found.")
}
message("Installing {remotes} for re-installing from GitHub, etc....")
install.packages("remotes", repos = c(CRAN = "https://cran.rstudio.com"))
# ^ also ensures that we have a personal library for this version of R
if (! "remotes" %in% installed.packages()[, "Package"]) {
stop("{remotes} is/was not installed!")
}
# First, we locate the various personal R libraries the user has:
if (Sys.info()["sysname"] == "Linux") {
pkg_paths <- dir(paste0(Sys.getenv("HOME"), "/R/", R.version$platform, "-library"), full.names = TRUE)
} else if (Sys.info()["sysname"] == "Darwin") {
pkg_paths <- file.path(dir("~/Library/R", full.names = TRUE), "library")
}
# Pick the latest one that is not the current R version's library:
pkg_paths <- pkg_paths[!vapply(pkg_paths, function(path) { any(grepl(path, .libPaths(), fixed = TRUE)) }, FALSE)]
pkg_path <- tail(pkg_paths, 1)
if (length(pkg_path) == 0) {
stop("Nothing to do.")
} else {
message("Found library from previous R installation: ", pkg_path)
}
# List of installed packages in the user's personal library:
installed_pkgs <- dir(pkg_path)
if (length(installed_pkgs) == 0) {
stop("Did not find any packages from previous R installation.")
}
message("Found ", length(installed_pkgs), " packages from previous R installation.")
# A helper function for extracting a parameter
# from an installed package's DESCRIPTION file
extract_param <- function(DESCRIPTION, param) {
return(sub(paste0(param, ": "), "", DESCRIPTION[grepl(param, DESCRIPTION)], fixed = TRUE))
}
message("Extracting metadata about packages from previous R installation...")
pkgs_info <- do.call(rbind, lapply(installed_pkgs, function(installed_pkg) {
# message('Checking how "', installed_pkg, '" was installed...')
pkg_description <- readLines(file.path(find.package(installed_pkg, lib.loc = pkg_path), "DESCRIPTION"))
if (any(grepl("Repository: CRAN", pkg_description))) {
# message('"', installed_pkg, '" was installed from CRAN.')
pkg_source <- "cran"; pkg_url <- NA
} else if (any(grepl("Additional_repositories", pkg_description))) {
# e.g. {cmdstanr} & {posterior} installed from https://mc-stan.org/r-packages/ (drat)
pkg_source <- "other"; pkg_url <- extract_param(pkg_description, "Additional_repositories")
} else if (any(grepl("RemoteType", pkg_description))) {
# message('"', installed_pkg, '" was installed from a remote source like GitHub.')
pkg_source <- extract_param(pkg_description, "RemoteType")
if (pkg_source == "github") {
pkg_url <- paste(extract_param(pkg_description, "GithubUsername"), extract_param(pkg_description, "GithubRepo"), sep = "/")
} else if (pkg_source == "git") {
pkg_url <- extract_param(pkg_description, "RemoteUrl")
} else {
pkg_source <- "other remote"; pkg_url <- NA
}
} else {
# message('"', installed_pkg, '" was installed from a local source.')
pkg_source <- "local"; pkg_url <- NA
}
return(data.frame(
package = installed_pkg,
source = pkg_source,
url = pkg_url,
stringsAsFactors = FALSE
))
}))
# Re-install packages:
if (sum(pkgs_info$source == "cran") > 0) {
message("Re-installing ", sum(pkgs_info$source == "cran"), " R packages from CRAN...")
install.packages(pkgs_info$package[pkgs_info$source == "cran"], repos = c(CRAN = "https://cran.rstudio.com"))
}
if (sum(pkgs_info$source == "github") > 0) {
message("The following ", sum(pkgs_info$source == "github"), " packages will be re-installed from GitHub: ", paste(pkgs_info$package[pkgs_info$source == "github"], collapse = ", "))
remotes::install_github(pkgs_info$url[pkgs_info$source == "github"])
}
if (sum(pkgs_info$source == "git") > 0) {
message("The following ", sum(pkgs_info$source == "git"), " packages will be re-installed from Git repos: ", paste(pkgs_info$package[pkgs_info$source == "git"], collapse = ", "))
remotes::install_git(pkgs_info$url[pkgs_info$source == "git"])
}
if (sum(pkgs_info$source == "other") > 0) {
message("The following ", sum(pkgs_info$source == "other"), " packages will be re-installed from other repos: ", paste(pkgs_info$package[pkgs_info$source == "other"], collapse = ", "))
install.packages(pkgs_info$package[pkgs_info$source == "other"], repos = c(CRAN = "https://cran.rstudio.com", pkgs_info$url[pkgs_info$source == "other"]))
}
if (sum(pkgs_info$source %in% c("other remote", "local")) > 0) {
message("The following ", sum(pkgs_info$source %in% c("other remote", "local")), " packages will need to be manually re-installed (sorry): ", paste(pkgs_info$package[pkgs_info$source %in% c("other remote", "local")], collapse = ", "))
}
@bearloga
Copy link
Author

bearloga commented Oct 8, 2020

Then re-install the R kernel spec:

IRkernel::installspec()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment