Skip to content

Commit

Permalink
tweak inference of repository type (#1997)
Browse files Browse the repository at this point in the history
* tweak inference of repository type

* fix up rmarkdown link

* ignore changes in mc.cores (can happen when parallel is loaded)

* update NEWS; ignore pak in clean (#1991)

* tweak check + use of parallel
  • Loading branch information
kevinushey authored Sep 27, 2024
1 parent 5961a60 commit 6c6dc7d
Show file tree
Hide file tree
Showing 8 changed files with 71 additions and 43 deletions.
8 changes: 8 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@

# renv (development version)

* Fixed an issue where `renv` tests could fail if the `parallel` package was
loaded during test execution.

* `renv` now determines a package repository's type through the HTTP headers
provided when accessing `src/contrib/PACKAGES`. This is mainly relevant
when detecting Nexus and Artifactory repositories.


# renv 1.0.9

Expand Down
5 changes: 4 additions & 1 deletion R/clean.R
Original file line number Diff line number Diff line change
Expand Up @@ -207,9 +207,12 @@ renv_clean_unused_packages <- function(project, prompt) {

# find packages installed in the project library
library <- renv_paths_library(project = project)
installed <- list.files(library)
installed <- list.files(library, pattern = renv_regexps_package_name())
if (empty(installed))
return(ntd())

# ignore 'pak' if we're configured to use it
installed <- setdiff(installed, if (config$pak.enabled()) "pak")

# find packages used in the project and their recursive dependencies
packages <- renv_snapshot_dependencies(project, dev = TRUE)
Expand Down
4 changes: 2 additions & 2 deletions R/dependencies.R
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
#' in the `DESCRIPTION` file. For projects using Python, \R dependencies within
#' the \R code chunks of your project's `.ipynb` files will also be used.
#'
#' Note that the [rmarkdown] package is required in order to crawl dependencies
#' in R Markdown files.
#' Note that the \code{\link[rmarkdown:rmarkdown-package]{rmarkdown}} package is
#' required in order to crawl dependencies in R Markdown files.
#'
#' # Missing dependencies
#'
Expand Down
4 changes: 2 additions & 2 deletions R/download.R
Original file line number Diff line number Diff line change
Expand Up @@ -591,7 +591,7 @@ renv_download_auth_gitlab <- function() {

}

renv_download_headers <- function(url, type, headers) {
renv_download_headers <- function(url, type = NULL, headers = NULL) {

# check for compatible download method
method <- renv_download_method()
Expand All @@ -606,7 +606,7 @@ renv_download_headers <- function(url, type, headers) {
destfile = file,
type = type,
request = "HEAD",
headers = headers
headers = headers %||% renv_download_custom_headers(url)
)

# check for failure
Expand Down
15 changes: 9 additions & 6 deletions R/parallel.R
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,20 @@ renv_parallel_cores <- function() {
return(1L)

value <- config$updates.parallel()
case(
identical(value, TRUE) ~ getOption("mc.cores", default = 2L),
identical(value, FALSE) ~ 1L,
~ as.integer(value)
)
if (identical(value, TRUE)) {
parallel <- requireNamespace("parallel", quietly = TRUE)
getOption("mc.cores", default = if (parallel) 2L else 1L)
} else if (identical(value, FALSE)) {
1L
} else {
as.integer(value)
}

}

renv_parallel_exec <- function(data, callback) {
cores <- renv_parallel_cores()
if (cores > 1)
if (cores > 1L)
parallel::mclapply(data, callback, mc.cores = cores)
else
lapply(data, callback)
Expand Down
73 changes: 43 additions & 30 deletions R/retrieve.R
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@

the$repos_archive <- new.env(parent = emptyenv())

#' Retrieve packages
#'
#' Retrieve (download) one or more packages from external sources.
Expand Down Expand Up @@ -905,13 +903,13 @@ renv_retrieve_repos_archive <- function(record) {
for (repo in getOption("repos")) {

# try to determine path to package in archive
url <- renv_retrieve_repos_archive_path(repo, record)
if (is.null(url))
root <- renv_retrieve_repos_archive_root(repo, record)
if (is.null(root))
next

# attempt download
name <- renv_retrieve_repos_archive_name(record, type = "source")
status <- catch(renv_retrieve_repos_impl(record, "source", name, url))
status <- catch(renv_retrieve_repos_impl(record, "source", name, root))
if (identical(status, TRUE))
return(TRUE)

Expand All @@ -921,58 +919,73 @@ renv_retrieve_repos_archive <- function(record) {

}

renv_retrieve_repos_archive_path <- function(repo, record) {
renv_retrieve_repos_archive_root <- function(url, record) {

# allow users to provide a custom archive path for a record,
# in case they're using a repository that happens to archive
# packages with a different format than regular CRAN network
# https://github.com/rstudio/renv/issues/602
override <- getOption("renv.retrieve.repos.archive.path")
if (is.function(override)) {
result <- override(repo, record)
result <- override(url, record)
if (!is.null(result))
return(result)
}

# retrieve the appropriate formatter for this repository url
formatter <- memoize(
key = url,
value = renv_retrieve_repos_archive_formatter(url)
)

# use it
formatter(url, record)

}

# if we already know the format of the repository, use that
if (exists(repo, envir = the$repos_archive)) {
formatter <- get(repo, envir = the$repos_archive)
root <- formatter(repo, record)
return(root)
}
renv_retrieve_repos_archive_formatter <- function(url, record) {

# otherwise, try determining the archive paths with a couple
# custom locations, and cache the version that works for the
# associated repository
# list of known formatters
formatters <- list(

# default CRAN format
function(repo, record) {
cran = function(repo, record) {
with(record, file.path(repo, "src/contrib/Archive", Package))
},

# format used by Artifactory
# https://github.com/rstudio/renv/issues/602
function(repo, record) {
artifactory = function(repo, record) {
with(record, file.path(repo, "src/contrib/Archive", Package, Version))
},

# format used by Nexus
# https://github.com/rstudio/renv/issues/595
function(repo, record) {
nexus = function(repo, record) {
with(record, file.path(repo, "src/contrib"))
}

)

name <- renv_retrieve_repos_archive_name(record, "source")
for (formatter in formatters) {
root <- formatter(repo, record)
url <- file.path(root, name)
if (renv_download_available(url)) {
assign(repo, formatter, envir = the$repos_archive)
return(root)
}

# check for an override
override <- getOption("renv.repos.formatters")
if (!is.null(override)) {
formatter <- formatters[[override[[url]] %||% ""]]
if (!is.null(formatter))
return(formatter)
}

# build URL to PACKAGES file in src/contrib
pkgurl <- file.path(url, "src/contrib/PACKAGES")
headers <- renv_download_headers(pkgurl)

# use the headers to infer the repository type
if ("x-artifactory-id" %in% names(headers)) {
formatters[["artifactory"]]
} else if (grepl("Nexus", headers[["server"]] %||% "")) {
formatters[["nexus"]]
} else {
formatters[["cran"]]
}

}
Expand Down
4 changes: 2 additions & 2 deletions man/dependencies.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions tests/testthat/helper-testthat.R
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ renv_test_state <- function(cran) {
opts$ambiguousMethodSelection <- NULL
opts$restart <- NULL
opts$repos[opts$repos == "@CRAN@"] <- "https://cloud.r-project.org"
opts$mc.cores <- NULL
opts <- opts[csort(names(opts))]

envvars <- as.list(Sys.getenv())
Expand Down

0 comments on commit 6c6dc7d

Please sign in to comment.