Feature Request: Add strict mode flag to fail on unavailable packages in `install.r`/`install2.r`
Description
Current Behavior
When using install.r to install packages, if a package doesn't exist in any configured repository, the script only issues a warning and continues with exit status 0:
$ install.r BiocManager remotes nonexistentpackage
# ... installations proceed ...
Warning in install.packages :
package 'nonexistentpackage' is not available for this version of R
# Exit code: 0 (success)
While install2.r has an --error flag, this only catches installation failures, not unavailable packages. A package can be unavailable (not in repos) but install2.r --error will still exit with status 0 because no installation was attempted.
Expected Behavior
There should be a flag (e.g., --strict or --check-availability) that:
- Checks if all requested packages exist in configured repositories before attempting installation
- Exits with non-zero status if any package is unavailable
- Provides clear error messaging listing which packages were not found
Use Case
In containerized environments (especially with rocker/r2u) and CI/CD pipelines, silent failures from typos or unavailable packages cause runtime errors that are hard to debug:
# This succeeds even with typo, failing later at runtime
RUN install.r Seurat SeurtObject # typo in "SeuratObject"
Currently, explicit verification is required after each install.r call:
RUN install.r package1 package2 package3 \
&& R -e "if (!requireNamespace('package1', quietly=TRUE)) stop('package1 failed')" \
&& R -e "if (!requireNamespace('package2', quietly=TRUE)) stop('package2 failed')" \
&& R -e "if (!requireNamespace('package3', quietly=TRUE)) stop('package3 failed')"
Proposed Solution
Add --strict or --check-availability flag to validate package availability:
install2.r --strict package1 package2 nonexistentpackage
# Error: Package(s) not available in repositories: nonexistentpackage
# Available packages checked against: CRAN, BioConductor
# Exit code: 1
Implementation Sketch
if (opt$strict) {
available_pkgs <- available.packages(repos = opt$repos)
# Filter out local files and GitHub repos
remote_pkgs <- opt$PACKAGES[!isMatchingFile(opt$PACKAGES) & !grepl("/", opt$PACKAGES)]
missing <- remote_pkgs[!remote_pkgs %in% rownames(available_pkgs)]
if (length(missing) > 0) {
cat("Error: Package(s) not available in configured repositories:\n", file=stderr())
cat(paste(" -", missing, collapse="\n"), "\n", file=stderr())
cat("\nConfigured repos:", opt$repos, "\n", file=stderr())
q(status = 1)
}
}
Difference from Existing --error Flag
--error: Fails ifinstall.packages()returns an error during installation--strict(proposed): Fails if package doesn't exist in repos (pre-installation check)
Both flags could be used together for comprehensive validation.
Benefits
- Fail-fast behavior in Docker builds
- Clear error messages with package names
- Catches typos immediately
- No additional dependencies required
- Backward compatible (opt-in flag)
Workflows where I use the scripts often start fromt the other end, i.e. by accessing what available.packages() and/or CRAN_package_db() return but I had this on occassion. I would possibly rename the flag to --mustexist or something closer to the meaning of 'please fail if unavailable package asked for'. But I hit this too once or twice and it would be a possibly useful addtion to install2.r. (Whereas install.r may stay smaller/simpler...)
Feel free to sketch a PR. install2.r is already complicated because of the error handler and whatnot, but the added block you suggest may work. I look forward to maybe seeing some tests (illustrations really) and examples.