Skip to content

Commit

Permalink
New strategy to retrieve DESCRIPTION if project uses renv (#931)
Browse files Browse the repository at this point in the history
Previously we'd always restore the packages from the lockfile, which I had expected to be fast since I had expected the packages to be in the cache. However, this doesn't appear to always be the case, so I instead use a simpler approach where I just force the user to resolve the problem. This means that we can always use the `DESCRIPTION` present in the `.libPaths()` making the code much simpler.

Fixes #930
  • Loading branch information
hadley authored Jul 25, 2023
1 parent 4c55d69 commit 02cada1
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 19 deletions.
5 changes: 5 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# rsconnect (development version)

* `deployApp()` and `writeManifest()` now error if your library and `renv.lock`
are out-of-sync. Previously it always used what was defined in the `renv.lock`
but that was (a) slow and (b) could lead to different results than what you
see when running locally (#930).

* Deploying from an renv project includes the `renv.lock` in the bundle. A
manifest created for an renv project references the `renv.lock` in the
`manifest.json`. (#926)
Expand Down
32 changes: 13 additions & 19 deletions R/bundlePackageRenv.R
Original file line number Diff line number Diff line change
Expand Up @@ -34,24 +34,18 @@ parseRenvDependencies <- function(bundleDir, snapshot = FALSE) {
return(data.frame())
}

if (snapshot) {
# Can use system libraries
deps$description <- lapply(deps$Package, package_record)
} else {
old <- options(renv.verbose = FALSE)
defer(options(old))

# Generate a library from the lockfile
lib_dir <- dirCreate(file.path(bundleDir, "renv_library"))
defer(unlink(lib_dir, recursive = TRUE))
renv::restore(bundleDir, library = lib_dir, prompt = FALSE)

deps$description <- lapply(
deps$Package,
package_record,
# Ensure we fall back to system libraries
lib_dir = c(lib_dir, .libPaths())
)
deps$description <- lapply(deps$Package, package_record)

if (!snapshot) {
lib_versions <- unlist(lapply(deps$description, "[[", "Version"))

if (any(deps$Version != lib_versions)) {
cli::cli_abort(c(
"Library and lockfile are out of sync",
i = "Use renv::restore() or renv::snapshot() to synchronise",
i = "Or ignore the lockfile by adding to you .rscignore"
))
}
}

deps
Expand Down Expand Up @@ -89,7 +83,7 @@ standardizeRenvPackage <- function(pkg,
}

if (pkg$Source == "Repository") {
if (pkg$Repository == "CRAN") {
if (identical(pkg$Repository, "CRAN")) {
if (isDevVersion(pkg, availablePackages)) {
pkg$Source <- NA_character_
pkg$Repository <- NA_character_
Expand Down
10 changes: 10 additions & 0 deletions tests/testthat/_snaps/bundlePackageRenv.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# errors if library and project are inconsistent

Code
parseRenvDependencies(app_dir)
Condition
Error in `parseRenvDependencies()`:
! Library and lockfile are out of sync
i Use renv::restore() or renv::snapshot() to synchronise
i Or ignore the lockfile by adding to you .rscignore

11 changes: 11 additions & 0 deletions tests/testthat/test-bundlePackageRenv.R
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,17 @@ test_that("gets DESCRIPTION from renv & system libraries", {
expect_type(deps$description[[which(deps$Package == "MASS")]], "list")
})


test_that("errors if library and project are inconsistent", {
withr::local_options(renv.verbose = FALSE)

app_dir <- local_temp_app(list("foo.R" = "library(foreign); library(MASS)"))
renv::snapshot(app_dir, prompt = FALSE)
renv::record("[email protected]", project = app_dir)

expect_snapshot(parseRenvDependencies(app_dir), error = TRUE)
})

# standardizeRenvPackage -----------------------------------------

test_that("SCM get names translated", {
Expand Down

0 comments on commit 02cada1

Please sign in to comment.