Kodiologist
Kodiologist

Reputation: 3495

When installing an R package, automatically reinstall dependencies when needed

utils::install.packages seems to be perfectly capable of installing dependencies that are missing. But if there's a dependency that's already installed without being of the right version for some reason (e.g., when trying to install DiagrammeR, Error: package ‘igraph’ was installed by an R version with different internals; it needs to be reinstalled for use with this R version), the original install.packages call just stops there. I then have to go and manually reinstall each problematic dependency. How can I automate this?

I'm running R 3.6.1 on Linux.

Upvotes: 4

Views: 2531

Answers (2)

Kodiologist
Kodiologist

Reputation: 3495

This method is crude (especially since it will happily redownload a package multiple times), but it's the best I've come up with so far:

install.rec = function(pkg, repos = 'http://archive.linux.duke.edu/cran')
# Install a package and reinstall any dependencies that need
# to be reinstalled, recursively.
   {while (T)
       {message("INSTALLING: ", pkg)
        out = paste0(collapse = " ",
            system2("Rscript", stdout = T, stderr = T, sprintf(
                "--no-init-file -e \"install.packages('%s', repos='%s')\"",
                pkg, repos)))
        p = regmatches(out, regexec(text = out, perl = T,
            "package ‘(\\S+)’ was installed (?:before R|by an R version)"))[[1]]
        if (length(p))
           {p = p[2]
            message("START RECURSING: ", pkg, " - ", p)
            install.rec(p, repos)
            message("END RECURSING: ", pkg, " - ", p)}
        else
            break}
   message("DONE WITH: ", pkg)}

install.packages doesn't raise conditions, nor does it return errors, nor does it produce its output in a way captureable with capture.output, so we have to use a system call to see the error message. The idea comes from here.

Upvotes: 2

smingerson
smingerson

Reputation: 1438

There doesn't seem to be a way to enforce this in install.packages(). Instead, you could use pak::pkg_install(). From pak::pkg_install() "upgrade" argument :

upgrade 
Whether to upgrade already installed packages to the latest available version. If this is 
FALSE, then only packages that need updates to satisfy version requirements, will be 
updated. If it is TRUE, all specified or dependent packages will be updated to the latest 
available version.

Edit: Reading your question more carefully, it sounds like you might be using a 3.5 package library with 3.6. If that's the case, I recommend the R package installr when upgrading between versions. It can automate the re-installation of all packages you had in the previous version.

Edit2: The below code will show you which are built on the previous version. I would run install.packages(built_on_earlier_version, force = TRUE) for these packages.

installed_packages <- as.data.frame(installed.packages())

installed_packages[as.package_version(installed_packages$Built) < as.package_version("3.6.0"),]

Upvotes: 2

Related Questions