I have around 4000 R packages installed in my system (a server) and most of them are outdated because they were built before R-3.0.0. Now I know
update.packages(checkBuilt=TRUE, ask=FALSE)
would update all my packages but that's too slow. The thing is the users do not use most of the packages and now and then they ask me to update a package (say fields) they'd use. Now if I run
install.packages("fields")
it would only update the package fields but not the package maps even if fields depends on maps. Thus when I try to load the package fields:
library("fields")
I get an error message
Error: package ‘maps’ was built before R 3.0.0: please re-install it
Is there a way to upgrade fields so that it would also automatically update the packages fields depends on?
As Ben indicated in his comment, you need to get the dependencies for fields
, then filter out the packages with Priority "Base"
or "Recommended"
, and then pass that list of package to install.packages()
to deal with the installation. Something like:
instPkgPlusDeps <- function(pkg, install = FALSE,
which = c("Depends", "Imports", "LinkingTo"),
inc.pkg = TRUE) {
stopifnot(require("tools")) ## load tools
ap <- available.packages() ## takes a minute on first use
## get dependencies for pkg recursively through all dependencies
deps <- package_dependencies(pkg, db = ap, which = which, recursive = TRUE)
## the next line can generate warnings; I think these are harmless
## returns the Priority field. `NA` indicates not Base or Recommended
pri <- sapply(deps[[1]], packageDescription, fields = "Priority")
## filter out Base & Recommended pkgs - we want the `NA` entries
deps <- deps[[1]][is.na(pri)]
## install pkg too?
if (inc.pkg) {
deps = c(pkg, deps)
}
## are we installing?
if (install) {
install.packages(deps)
}
deps ## return dependencies
}
This gives:
R> instPkgPlusDeps("fields")
Loading required package: tools
[1] "fields" "spam" "maps"
which matches with
> packageDescription("fields", fields = "Depends")
[1] "R (>= 2.13), methods, spam, maps"
You get warnings from the sapply()
line if a dependency in deps
is not actually installed. I think these are harmless as the returned value in that case is NA
and we use that to indicate packages we want to install. I doubt it will affect you if you have 4000 packages installed.
The default is not to install packages but just return the list of dependencies. I figured this was safest as you may not realise the chain of dependencies implied and end up installing hundreds of packages accidentally. Pass in install = TRUE
if you are happy to install the packages indicated.
Note that I restrict the types of dependencies searched for - things balloon if you use which = "most"
- fields has over 300 such dependencies once you recursively resolve those dependences (which include Suggests:
fields too). which = "all"
will look for everything, including Enhances:
which will be a bigger list of packages again. See ?tools::package_dependencies
for valid inputs for the which
argument.