diff --git a/NEWS.md b/NEWS.md index a7a281894..ed773c73f 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,6 +1,9 @@ # renv 1.1.0 (UNRELEASED) +* `renv::use()` no longer re-installs packages which are already installed + and compatible with the requested packages. (#2044) + * Fixed an issue where `renv::init()` could fail when using named remotes in a DESCRIPTION file's `Remotes:` field. (#2055) diff --git a/R/use.R b/R/use.R index 279d9727c..3632eafae 100644 --- a/R/use.R +++ b/R/use.R @@ -76,18 +76,40 @@ use <- function(..., return(invisible()) # resolve the provided remotes - remotes <- lapply(dots, renv_remotes_resolve) - names(remotes) <- map_chr(remotes, `[[`, "Package") - + records <- lapply(dots, renv_remotes_resolve, latest = TRUE) + names(records) <- map_chr(records, `[[`, "Package") + + # remove any remotes which already appear to be installed + compat <- enum_lgl(records, function(package, record) { + + # check if the package is installed + if (!renv_package_installed(package, lib.loc = library)) + return(FALSE) + + # check if the installed package is compatible + record <- resolve(record) + current <- renv_snapshot_description(package = package) + diff <- renv_lockfile_diff_record(record, current) + + # a null diff implies the two records are compatible + is.null(diff) + + }) + + # drop the already-installed compatible records + records <- records[!compat] + if (empty(records)) + return(invisible()) + # install packages records <- local({ renv_scope_options(renv.verbose = verbose) - install(packages = remotes, library = library, prompt = FALSE) + install(packages = records, library = library, rebuild = character(), prompt = FALSE) }) # automatically load the requested remotes if (attach) { - enumerate(remotes, function(package, remote) { + enumerate(records, function(package, remote) { library(package, character.only = TRUE) }) }