Skip to content

Commit 76c05ce

Browse files
authored
Support declaring extra dependencies (#483)
1 parent ab75061 commit 76c05ce

23 files changed

+353
-108
lines changed

NEWS.md

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# remotes (development version)
22

3+
* Remotes functions can now install dependencies from additional DESCRIPTION fields, e.g. passing `dependencies = "Config/Needs/website"` will install the dependencies listed in the `Config/Needs/website: ` field in the package's DESCRIPTION.
4+
Prefixing fields with `Config/Needs` allows them to pass `R CMD check` without a NOTE, so it is the recommended format.
5+
6+
* New `system_requirements()` function to query the Public RStudio Package Manager for system requirements for a package (and its dependencies)
7+
38
* `install_*()` family of functions defaults to the default branch, not the `master` branch (@MyKo101,#508).
49

510
* Another fix for the mixed binary and source dependency issue, it should hopefully be fully squashed now (#296).
@@ -12,7 +17,7 @@
1217

1318
* `parse_submodules()` internal regular expression is now PCRE 2 compatible (#502, @jan-glx)
1419

15-
* New `system_requirements()` function to query the Public RStudio Package Manager for system requirements for a package (and its dependencies)
20+
* Another fix for the mixed binary and source dependency issue, it should hopefully be fully squashed now (#296)
1621

1722
* `install_version()` now avoids use of `base::url()`, as prior to R 3.6.2 it had a bug when downloading large files (#463)
1823

R/deps.R

+55-19
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,13 @@
1616
#' "Suggests". `NA` is shorthand for "Depends", "Imports" and "LinkingTo"
1717
#' and is the default. `FALSE` is shorthand for no dependencies (i.e.
1818
#' just check this package, not its dependencies).
19+
#'
20+
#' The value "soft" means the same as `TRUE`, "hard" means the same as `NA`.
21+
#'
22+
#' You can also specify dependencies from one or more additional fields,
23+
#' common ones include:
24+
#' - Config/Needs/website - for dependencies used in building the pkgdown site.
25+
#' - Config/Needs/coverage for dependencies used in calculating test coverage.
1926
#' @param quiet If `TRUE`, suppress output.
2027
#' @param upgrade One of "default", "ask", "always", or "never". "default"
2128
#' respects the value of the `R_REMOTES_UPGRADE` environment variable if set,
@@ -131,12 +138,16 @@ dev_package_deps <- function(pkgdir = ".", dependencies = NA,
131138
repos[missing_repos] <- bioc_repos[missing_repos]
132139
}
133140

134-
combine_deps(
135-
package_deps(deps, repos = repos, type = type),
136-
remote_deps(pkg))
141+
cran_deps <- package_deps(deps, repos = repos, type = type)
142+
143+
res <- combine_remote_deps(cran_deps, extra_deps(pkg, "remotes"))
144+
145+
res <- do.call(rbind, c(list(res), lapply(get_extra_deps(pkg, dependencies), extra_deps, pkg = pkg), stringsAsFactors = FALSE))
146+
147+
res[!duplicated(res$package, fromLast = TRUE), ]
137148
}
138149

139-
combine_deps <- function(cran_deps, remote_deps) {
150+
combine_remote_deps <- function(cran_deps, remote_deps) {
140151
# If there are no dependencies there will be no remote dependencies either,
141152
# so just return them (and don't force the remote_deps promise)
142153
if (nrow(cran_deps) == 0) {
@@ -189,8 +200,17 @@ compare_versions <- function(inst, remote, is_cran) {
189200
integer(1))
190201
}
191202

192-
has_dev_remotes <- function(pkg) {
193-
!is.null(pkg[["remotes"]])
203+
has_extra_deps <- function(pkg, dependencies) {
204+
any(dependencies %in% names(pkg))
205+
}
206+
207+
get_extra_deps <- function(pkg, dependencies) {
208+
dependencies <- tolower(dependencies)
209+
210+
dependencies <- intersect(dependencies, names(pkg))
211+
212+
#remove standard dependencies
213+
setdiff(dependencies, tolower(standardise_dep(TRUE)))
194214
}
195215

196216
#' @export
@@ -248,6 +268,7 @@ update.package_deps <- function(object,
248268
type = getOption("pkgType"),
249269
...) {
250270

271+
dependencies <- standardise_dep(dependencies)
251272

252273
object <- upgradable_packages(object, upgrade, quiet)
253274

@@ -394,6 +415,11 @@ find_deps <- function(packages, available = available_packages(),
394415
#' "Suggests". `NA` is shorthand for "Depends", "Imports" and "LinkingTo"
395416
#' and is the default. `FALSE` is shorthand for no dependencies.
396417
#'
418+
#' The value "soft" means the same as `TRUE`, "hard" means the same as `NA`.
419+
#'
420+
#' Any additional values that don't match one of the standard dependency
421+
#' types are filtered out.
422+
#'
397423
#' @seealso <http://r-pkgs.had.co.nz/description.html#dependencies> for
398424
#' additional information on what each dependency type means.
399425
#' @keywords internal
@@ -406,7 +432,13 @@ standardise_dep <- function(x) {
406432
} else if (identical(x, FALSE)) {
407433
character(0)
408434
} else if (is.character(x)) {
409-
x
435+
if (any(x == "hard")) {
436+
c("Depends", "Imports", "LinkingTo")
437+
} else if (any(x == "soft")) {
438+
c("Depends", "Imports", "LinkingTo", "Suggests")
439+
} else {
440+
intersect(x, c("Depends", "Imports", "LinkingTo", "Suggests", "Enhances"))
441+
}
410442
} else {
411443
stop("Dependencies must be a boolean or a character vector", call. = FALSE)
412444
}
@@ -478,11 +510,15 @@ fix_repositories <- function(repos) {
478510
repos
479511
}
480512

481-
parse_one_remote <- function(x, ...) {
513+
parse_one_extra <- function(x, ...) {
482514
pieces <- strsplit(x, "::", fixed = TRUE)[[1]]
483515

484516
if (length(pieces) == 1) {
485-
type <- "github"
517+
if (!grepl("/", pieces)) {
518+
type <- "cran"
519+
} else {
520+
type <- "github"
521+
}
486522
repo <- pieces
487523
} else if (length(pieces) == 2) {
488524
type <- pieces[1]
@@ -504,10 +540,10 @@ parse_one_remote <- function(x, ...) {
504540
res
505541
}
506542

507-
split_remotes <- function(x) {
543+
split_extra_deps <- function(x, name = "Remotes") {
508544
pkgs <- trim_ws(unlist(strsplit(x, ",[[:space:]]*")))
509545
if (any((res <- grep("[[:space:]]+", pkgs)) != -1)) {
510-
stop("Missing commas separating Remotes: '", pkgs[res], "'", call. = FALSE)
546+
stop("Missing commas separating ", name, ": '", pkgs[res], "'", call. = FALSE)
511547
}
512548
pkgs
513549
}
@@ -526,22 +562,22 @@ package_deps_new <- function(package = character(), installed = character(),
526562
res
527563
}
528564

529-
remote_deps <- function(pkg) {
530-
if (!has_dev_remotes(pkg)) {
565+
extra_deps <- function(pkg, field) {
566+
if (!has_extra_deps(pkg, field)) {
531567
return(package_deps_new())
532568
}
569+
dev_packages <- split_extra_deps(pkg[[field]])
570+
extra <- lapply(dev_packages, parse_one_extra)
533571

534-
dev_packages <- split_remotes(pkg[["remotes"]])
535-
remote <- lapply(dev_packages, parse_one_remote)
536-
537-
package <- vapply(remote, function(x) remote_package_name(x), character(1), USE.NAMES = FALSE)
572+
package <- vapply(extra, function(x) remote_package_name(x), character(1), USE.NAMES = FALSE)
538573
installed <- vapply(package, function(x) local_sha(x), character(1), USE.NAMES = FALSE)
539-
available <- vapply(remote, function(x) remote_sha(x), character(1), USE.NAMES = FALSE)
574+
available <- vapply(extra, function(x) remote_sha(x), character(1), USE.NAMES = FALSE)
540575
diff <- installed == available
541576
diff <- ifelse(!is.na(diff) & diff, CURRENT, BEHIND)
542577
diff[is.na(installed)] <- UNINSTALLED
578+
is_cran_remote <- vapply(extra, inherits, logical(1), "cran_remote")
543579

544-
package_deps_new(package, installed, available, diff, is_cran = FALSE, remote)
580+
package_deps_new(package, installed, available, diff, is_cran = is_cran_remote, extra)
545581
}
546582

547583

R/install-cran.R

+3-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,9 @@ install_cran <- function(pkgs, repos = getOption("repos"), type = getOption("pkg
3838
...)
3939
}
4040

41-
cran_remote <- function(pkg, repos, type, ...) {
41+
cran_remote <- function(pkg, repos = getOption("repos"), type = getOption("pkgType"), ...) {
42+
43+
repos <- fix_repositories(repos)
4244

4345
remote("cran",
4446
name = pkg,

R/install-version.R

+1-1
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ version_satisfies_criteria <- function(to_check, criteria) {
109109
}
110110

111111
package_installed <- function(pkg, criteria) {
112-
v <- suppressWarnings(packageDescription(pkg, fields = "Version"))
112+
v <- suppressWarnings(utils::packageDescription(pkg, fields = "Version"))
113113
!is.na(v) && version_satisfies_criteria(v, criteria)
114114
}
115115

R/install.R

-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
install <- function(pkgdir, dependencies, quiet, build, build_opts, build_manual, build_vignettes,
22
upgrade, repos, type, ...) {
3-
43
warn_for_potential_errors()
54

65
if (file.exists(file.path(pkgdir, "src"))) {

inst/install-github.R

+59-22
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)