From 6a6c9d3938d490a3c93476c1428567bd22ddd53e Mon Sep 17 00:00:00 2001 From: Pieter Moris Date: Wed, 24 Aug 2022 15:32:56 +0200 Subject: [PATCH 1/2] Add additional options to installBioc.r Adds additional options to the installBioc.r example script based on the approach used in install2.r. The main goal was to be able to use the installBioc.r script as the main method to install bioconductor packages in Dockerfiles, and to make it fail the build process whenever an error occurs during package installation. The script now throws errors when a package fails to install due to missing dependencies, misspelled names, etc. Already installed packages can be skipped. Suggested dependencies can be toggled. Parallel install can be enabled. Download method can be set. A few options were added for BiocManager::install()'s unique arguments. A toggle to update other packages that are outdated. Additional repositories can be prepended to the standard BioC repository (only works for bioc sub-repositories like software/experiment). Already installed packages can be forced to redownload and install. In addition, the library path is now set in the same manner as is done in install2.r (by reading the first entry of .libPaths() and passing it to the install function, rather than setting it to `/usr/local/lib/R/site-library` via `.libPaths()`). --- inst/examples/installBioc.r | 103 ++++++++++++++++++++++++++++++++---- 1 file changed, 93 insertions(+), 10 deletions(-) diff --git a/inst/examples/installBioc.r b/inst/examples/installBioc.r index 5ce0ab9..6580084 100755 --- a/inst/examples/installBioc.r +++ b/inst/examples/installBioc.r @@ -9,13 +9,23 @@ ## load docopt package from CRAN library(docopt) -## configuration for docopt -doc <- "Usage: installBioc.r [-l LIBLOC] [-h] [-x] [PACKAGES ...] +## default to first library location in .libPaths() +libloc <- .libPaths()[1] --l --libloc LIBLOC location in which to install [default: /usr/local/lib/R/site-library] +## configuration for docopt +doc <- paste0("Usage: installBioc.r [-l LIBLOC] [-d DEPS] [-n NCPUS] [-r REPO ...] [--error] [--skipinstalled] [-m METHOD] [--force] [--update] [-h] [-x] [PACKAGES ...] +-l --libloc LIBLOC location in which to install [default: ", libloc, "] +-d --deps DEPS install suggested dependencies as well [default: NA] +-n --ncpus NCPUS number of processes to use for parallel install [default: getOption] +-r --repo REPO additional repository to use [default: getOption] +-e --error throw error and halt instead of a warning [default: FALSE] +-s --skipinstalled skip installing already installed packages (takes priority over --force) [default: FALSE] +-m --method METHOD method to be used for downloading files [default: auto] +-f --force force re-download of packages that are currently up-to-date [default: FALSE] +-u --update update old already installed packages [default: FALSE] -h --help show this help text --x --usage show help and short example usage" -opt <- docopt(doc) # docopt parsing +-x --usage show help and short example usage") +opt <- docopt(doc) # docopt parsing if (opt$usage) { cat(doc, "\n\n") @@ -24,6 +34,8 @@ package 'BiocManger' which has be installed. Examples: installBioc.r -l /tmp/lib S4Vectors # install into given library + installBioc.r --update Biobase # install package and update older packages + installBioc.r --deps NA --error --skipinstalled # install package without suggested dependencies, throw an error on installation failure and skip packages that are already present installBioC.r is part of littler which brings 'r' to the command-line. See http://dirk.eddelbuettel.com/code/littler.html for more information.\n") @@ -31,13 +43,84 @@ See http://dirk.eddelbuettel.com/code/littler.html for more information.\n") } if (!requireNamespace("BiocManager", quietly=TRUE)) { - stop("Please install 'BiocManager' first, for example via 'install.r BiocManager'.", call.=FALSE) + stop("Please install 'BiocManager' first, for example via 'install2.r BiocManager'.", call.=FALSE) +} + +## set repository to empty character vector if not supplied, since +## this is the input expected by BiocManager::install(site_repository=) +## (does not accept NA) +## the custom repository must be a sub-repository of a main BioC_mirror +## e.g. software: https://bioconductor.statistik.tu-dortmund.de/packages/3.15/bioc/ +## annotation: https://ftp.gwdg.de/pub/misc/bioconductor/packages/3.14/data/annotation +if (opt$repo == "getOption") { + opt$repo = character() +} + +## check if dependencies need to be installed, see +## https://www.rdocumentation.org/packages/utils/versions/3.6.2/topics/install.packages +## the default, NA, means c("Depends", "Imports", "LinkingTo"), but not "Suggests" +if (opt$deps == "TRUE" || opt$deps == "FALSE") { + opt$deps <- as.logical(opt$deps) +} else if (opt$deps == "NA") { + opt$deps <- NA +} + +## set the number of parallel processes to use for a parallel install of +## more than one source package, see +## https://www.rdocumentation.org/packages/utils/versions/3.6.2/topics/install.packages +if (opt$ncpus == "getOption") { + opt$ncpus <- getOption("Ncpus", 1L) +} else if (opt$ncpus == "-1") { + ## parallel comes with R 2.14+ + opt$ncpus <- max(1L, parallel::detectCores()) +} + +## helper function to catch errors that could arise when package installation has failed +## and to skip installation of packages that are already present (for BiocManager::install() +## these would otherwise result in additional warnings) +install_bioc <- function(pkgs, ..., error = FALSE, skipinstalled = FALSE) { + e <- NULL + capture <- function(e) { + if (error) { + catch <- + grepl("installation of one or more packages failed", e$message) || + grepl("is not available", e$message) || + grepl("had non-zero exit status", e$message) || + grepl("compilation failed for package.*", e$message) || + grepl("fatal error", e$message) || + grepl("No such file or directory", e$message) + if (catch) { + e <<- e + } + } + } + if (skipinstalled) { + pkgs <- setdiff(pkgs, installed.packages()[,1]) + } + if (length(pkgs) > 0) { + withCallingHandlers(BiocManager::install(pkgs, ...), warning = capture) + if (!is.null(e)) { + stop(e$message, call. = FALSE) + } + } } ## ensure installation is stripped Sys.setenv("_R_SHLIB_STRIP_"="true") -## set .libPaths() -.libPaths(opt$lib) - -BiocManager::install(opt$PACKAGES, update=FALSE, ask=FALSE) +## install requested packages using helper function +## ask must be set to FALSE because user prompts do not appear when calling +## R from the CLI, e.g. +## `R -e 'BiocManager::install("Biobase", ask=TRUE, update=TRUE)'` +## might warn that MASS is out of date, but would not show a user prompt +install_bioc(pkgs = opt$PACKAGES, + lib = opt$libloc, + site_repository = opt$repo, + update = opt$update, + ask = FALSE, + force = opt$force, + dependencies = opt$deps, + Ncpus = opt$ncpus, + method = opt$method, + error = opt$error, + skipinstalled = opt$skipinstalled) From 5f64d09260875bc344eb7a12d7d597a2c3094166 Mon Sep 17 00:00:00 2001 From: Dirk Eddelbuettel Date: Sun, 28 Aug 2022 16:16:37 -0500 Subject: [PATCH 2/2] minor edits as discussed in #103, add ChangeLog entry --- ChangeLog | 9 +++++++++ inst/examples/installBioc.r | 9 ++++++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2d6b5a7..e0b591b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2022-08-28 Dirk Eddelbuettel + + * inst/examples/installBioc.r: + +2022-08-24 Pieter Moris + + * inst/examples/installBioc.r: Generalization, extension and extra + features similar to how install2.r generalizes install2.r + 2022-07-16 Dirk Eddelbuettel * inst/examples/r2u.r: Add simple r2u.r frontend diff --git a/inst/examples/installBioc.r b/inst/examples/installBioc.r index 6580084..25d1384 100755 --- a/inst/examples/installBioc.r +++ b/inst/examples/installBioc.r @@ -2,7 +2,8 @@ # # Install a package from BioConductor # -# Copyright (C) 2020 - Dirk Eddelbuettel +# Copyright (C) 2020 - 2022 Dirk Eddelbuettel +# Copyright (C) 2022 - 2022 Dirk Eddelbuettel and Pieter Moris # # Released under GPL (>= 2) @@ -35,7 +36,9 @@ package 'BiocManger' which has be installed. Examples: installBioc.r -l /tmp/lib S4Vectors # install into given library installBioc.r --update Biobase # install package and update older packages - installBioc.r --deps NA --error --skipinstalled # install package without suggested dependencies, throw an error on installation failure and skip packages that are already present + installBioc.r --deps NA --error --skipinstalled # install package without suggested dependencies, + # throw an error on installation failure and skip + # packages that are already present installBioC.r is part of littler which brings 'r' to the command-line. See http://dirk.eddelbuettel.com/code/littler.html for more information.\n") @@ -43,7 +46,7 @@ See http://dirk.eddelbuettel.com/code/littler.html for more information.\n") } if (!requireNamespace("BiocManager", quietly=TRUE)) { - stop("Please install 'BiocManager' first, for example via 'install2.r BiocManager'.", call.=FALSE) + stop("Please install 'BiocManager' first, for example via 'install.r BiocManager'.", call.=FALSE) } ## set repository to empty character vector if not supplied, since