Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
104 commits
Select commit Hold shift + click to select a range
c2830a6
Add pak as dep-resolver and install backend for Require
eliotmcintire Apr 2, 2026
128a923
Fix integration test: reset offlineMode/useCache, remove real_join call
eliotmcintire Apr 2, 2026
de2fdab
Fix test-05 regression: revert dependencies=FALSE→NA, filter Require …
eliotmcintire Apr 6, 2026
e0e0040
Fix pak upgrade behavior: use dependencies=FALSE to honor Require ver…
eliotmcintire Apr 7, 2026
a691adb
Add pak dep-tree caching, verbose control, version checks, and bug fixes
eliotmcintire Apr 8, 2026
e9fff33
Fix url:: archive ref handling, dep-conflict false positives, add pak…
eliotmcintire Apr 8, 2026
cdb95a9
Fix false-positive version satisfiability warning for GitHub refs
eliotmcintire Apr 8, 2026
8ff8ee9
Guard step-3b version check against NA/empty pak versions
eliotmcintire Apr 8, 2026
e4619ea
Default Require.usePak = TRUE on pak-dep-cache branch
eliotmcintire Apr 9, 2026
c4ce825
Fix misleading post-install warning after build failure
eliotmcintire Apr 10, 2026
1234df5
Fix namespace-version dep failures in non-pak install path
eliotmcintire Apr 10, 2026
37c00d4
Improve pak build-failure messaging with actual reason
eliotmcintire Apr 10, 2026
d7017c0
Fix misleading conflict message when different pkg's Remotes cause clash
eliotmcintire Apr 13, 2026
8ea88ed
Clarify Remotes-clash conflict message to show both refs explicitly
eliotmcintire Apr 13, 2026
868c939
Include full GitHub ref of Remotes-source in conflict message
eliotmcintire Apr 13, 2026
acd0235
Show pak dep-tree cache hits at verbose = 1
eliotmcintire Apr 13, 2026
718170d
Add test-17usePak.R covering pak-backend changes
eliotmcintire Apr 13, 2026
d281825
Update NEWS.md for 1.1.0.9007
eliotmcintire Apr 13, 2026
2c206b1
Fix two test failures under usePak = TRUE
eliotmcintire Apr 13, 2026
ce46ea1
Fix require() not called for GitHub pkgs replaced by CRAN version-spe…
eliotmcintire Apr 14, 2026
18062af
Fix require() skipped for packages whose dev version is already insta…
eliotmcintire Apr 14, 2026
3a8079b
Warn when pak permanently drops a build-failed package from the retry…
eliotmcintire Apr 14, 2026
d38b6d5
Fix: recover user-requested packages absent from pkgDT in pak path
eliotmcintire Apr 14, 2026
544a872
Update NEWS.md for recovery mechanism fix
eliotmcintire Apr 14, 2026
6b236a4
Use immediate. = TRUE for pak install-failure warnings
eliotmcintire Apr 14, 2026
4f8ae3c
Always warn when require() returns FALSE, with libPaths context
eliotmcintire Apr 14, 2026
e51e64f
Fallback-load installed package when pak install fails for newer version
eliotmcintire Apr 14, 2026
d3fa49b
Surface pak error reason in 'could not be installed' warning
eliotmcintire Apr 14, 2026
7123be1
Fix pak install failures for GitHub dev packages
eliotmcintire Apr 14, 2026
34c2c9a
Use upgrade=TRUE for GitHub/url:: packages in pakRetryLoop
eliotmcintire Apr 14, 2026
ff8c7ce
Fix GH upgrade: use dependencies=FALSE to avoid cascading CRAN upgrades
eliotmcintire Apr 14, 2026
e1fffd4
Fix spurious pak post-install warnings and loadOrder misassignment
eliotmcintire Apr 16, 2026
a2628c4
Fix loadOrder set for base packages and all user packages when requir…
eliotmcintire Apr 17, 2026
5873147
Remove misleading 'loadOrder set but require=FALSE' message
eliotmcintire Apr 20, 2026
457f7d7
Move pak to Imports; defensive coercion in pakDepsCacheKey
eliotmcintire Apr 24, 2026
c7f2edb
pakInstall: use dependencies=NA for CRAN-like batch
eliotmcintire Apr 24, 2026
f58ea2d
Document pakErrorHandling parser fix in NEWS
eliotmcintire Apr 25, 2026
964ff3b
feat: iterative identify-and-defer install strategy
eliotmcintire Apr 28, 2026
89c4f23
fix: nowInstalledAll uses <- not <<- (post-install Package-lookup error)
eliotmcintire Apr 28, 2026
e7dd989
feat: end-of-install summary with per-package failure reasons
eliotmcintire Apr 28, 2026
cc0390d
feat: archive fallback for archived-CRAN refs + integration tests
eliotmcintire Apr 28, 2026
2f57120
fix: archive fallback installs cross-archive refs in single pak batch
eliotmcintire Apr 28, 2026
ae202c7
fix: pakGetArchive guards against malformed CRAN refs
eliotmcintire Apr 29, 2026
11c233d
fix: recover from cannot-be-unloaded failure in doLoads
eliotmcintire Apr 29, 2026
77fd242
fix: surface real pak subprocess failure reason
eliotmcintire Apr 29, 2026
2706317
feat: skip reinstall when loaded version is sufficient
eliotmcintire Apr 29, 2026
6efd8c3
fix: pass noCache=TRUE to post-install installed.packages() checks
eliotmcintire Apr 29, 2026
5162eac
fix: surface pak's real cause and stop duplicate install warning
eliotmcintire Apr 30, 2026
732c76f
fix: strip any:: prefix in identify-and-defer iter check
eliotmcintire Apr 30, 2026
192f7b9
fix: respect user-supplied version constraints through full pak insta…
eliotmcintire Apr 30, 2026
45b99b1
bump: 1.1.0.9030 + NEWS
eliotmcintire Apr 30, 2026
a12300d
redoc
eliotmcintire May 2, 2026
4c36f01
fix: useLoadedIfSufficient honour standAlone
eliotmcintire May 2, 2026
5c8d2a8
fix: warn when pak installs version that doesn't satisfy
eliotmcintire May 2, 2026
5c60e1b
test: use truly-archived fastdigest for archive URL test
eliotmcintire May 2, 2026
547ac4e
test: use .Library for cross-platform base R lib path
eliotmcintire May 2, 2026
6364768
test: parentChain forces non-pak path instead of skipping
eliotmcintire May 2, 2026
6d3a8f3
test: assert pak surface signal on misspelled GitHub user
eliotmcintire May 2, 2026
78bdffb
fix: pakGetArchive returns source Archive URL for archived pkgs
eliotmcintire May 2, 2026
5fdf58b
test: gate test-08 on isDev (not isDevAndInteractive)
eliotmcintire May 2, 2026
ded0c59
test: revert pakGetArchive test back to pryr
eliotmcintire May 2, 2026
cd30c60
test: keep parentChain skip with TODO for pak path
eliotmcintire May 2, 2026
be8fecb
test: gate test-10 on isDev; drop !isMacOS guard
eliotmcintire May 2, 2026
9d1febd
fix: surface 'did you spell' hint when pak rejects GH ref
eliotmcintire May 2, 2026
beb4d93
test: skip-on-CI test-08 and test-10 (heavy installs, run locally)
eliotmcintire May 2, 2026
f6712f7
fix: .runLongExamples returns FALSE on CI to avoid timeout
eliotmcintire May 2, 2026
8627e91
fix: don't call pak::cache_summary under R CMD check
eliotmcintire May 3, 2026
ac4a358
fix: .runLongExamples requires explicit opt-in env var
eliotmcintire May 3, 2026
35bf767
feat: pak-path offline install via local cache
eliotmcintire May 3, 2026
f0f058a
fix: pakCachedTarball filters out pak intermediate files
eliotmcintire May 3, 2026
9ec26bf
fix: drop eager pak load in test setup; was hanging R CMD check
eliotmcintire May 3, 2026
6415618
fix: set R_USER_CACHE_DIR for tests so pak can install under R CMD check
eliotmcintire May 4, 2026
edb22b3
fix: create R_USER_CACHE_DIR before setting it for pak
eliotmcintire May 4, 2026
da66109
fix: set R_USER_CACHE_DIR in testthat.R before library(Require)
eliotmcintire May 4, 2026
d1a7201
debug: surface real pak loadNamespace error in pakDepsToPkgDT
eliotmcintire May 4, 2026
404f825
debug: print libPaths/pak state at test start
eliotmcintire May 4, 2026
c0d2e50
fix: setupTest prefixes newLib onto libPaths so Imports stay visible
eliotmcintire May 4, 2026
94125f0
fix: strip non-ASCII chars from R/pak.R and R/Require2.R; drop diag
eliotmcintire May 4, 2026
e0cdd58
fix: setupTest libPaths only includes pak/Require host libs
eliotmcintire May 4, 2026
7ec0c1c
fix: preload pak/Require namespaces, then narrow libPaths in setupTest
eliotmcintire May 4, 2026
61515fe
fix: don't preload Require namespace; only pak (covr-friendly)
eliotmcintire May 4, 2026
4b5db62
fix: pakInstallFiltered honours install=force via upgrade flag
eliotmcintire May 4, 2026
e3d3a65
fix: silentlyFailed warning appends spelling hint when GH ref fails
eliotmcintire May 4, 2026
07b90ec
test: tolerate knn build failure on R-devel toolchains
eliotmcintire May 4, 2026
05ddf20
fix: pakGetArchive guards his$Version when pkg_history fails
eliotmcintire May 4, 2026
545d03c
test: un-skip test-09 body and remove dev-only browser() calls
eliotmcintire May 4, 2026
feeb992
perf: hoist strsplit out of pakErrorHandling pattern loop
eliotmcintire May 4, 2026
1057c24
perf: cache pak::pkg_deps results and short-circuit pakErrorHandling
eliotmcintire May 4, 2026
de65ede
test: skip_on_ci for test-09 (380-pkg snapshot install too slow for CI)
eliotmcintire May 4, 2026
5ff2ef6
fix: don't append "(==NA)" to GitHub-pinned snapshot rows
eliotmcintire May 4, 2026
2c73bd0
test: add small-snapshot install test (5 pkgs, ~1 min)
eliotmcintire May 4, 2026
51ac74b
fix: pak install path broken on R 4.3 + always installed wrong archiv…
eliotmcintire May 5, 2026
5044dc7
test: remove failing test-07 PPM/LandR experiment
eliotmcintire May 5, 2026
d3e5912
ci: surface .Rout.fail contents when covr fails
eliotmcintire May 5, 2026
fe212f0
ci: run testthat::test_local directly before covr to surface failures
eliotmcintire May 5, 2026
c231200
ci: use pkgload::load_all (devtools not installed on test-coverage ru…
eliotmcintire May 5, 2026
ca0192d
test: switch test-19 fixture to pure-R packages
eliotmcintire May 5, 2026
8fa1b05
ci: revert test-coverage diagnostic; covr alone is fine again
eliotmcintire May 5, 2026
2023dc1
feat: snapshot installer that bypasses pak's solver via install.packages
eliotmcintire May 5, 2026
f996f90
chore: merge stashed test/vignette changes from other workstation
eliotmcintire May 5, 2026
b973ea4
feat: gate Require.snapshotInstaller='install.packages' to Linux
eliotmcintire May 5, 2026
f99d72f
feat: route Linux snapshot installs through PPM binaries by default
eliotmcintire May 5, 2026
9cf0eef
feat: substitute nearest archived version for unresolvable snapshot refs
eliotmcintire May 5, 2026
0f9269f
feat: honor snapshot Repository column for resolution (e.g., r-universe)
eliotmcintire May 5, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ Description: A single key function, 'Require' that makes rerun-tolerant
URL:
https://Require.predictiveecology.org,
https://github.com/PredictiveEcology/Require
Date: 2026-04-01
Version: 1.1.0.9001
Date: 2026-04-30
Version: 1.1.0.9030
Authors@R: c(
person(given = "Eliot J B",
family = "McIntire",
Expand All @@ -37,6 +37,7 @@ Depends:
Imports:
data.table (>= 1.10.4),
methods,
pak,
sys,
tools,
utils
Expand All @@ -47,7 +48,6 @@ Suggests:
fpCompare,
gitcreds,
httr,
pak,
parallel,
rematch2,
rmarkdown,
Expand Down
500 changes: 499 additions & 1 deletion NEWS.md

Large diffs are not rendered by default.

74 changes: 72 additions & 2 deletions R/Require-helpers.R
Original file line number Diff line number Diff line change
Expand Up @@ -411,8 +411,78 @@ installedVers <- function(pkgDT, libPaths, standAlone = FALSE) {
}

installed <- !is.na(pkgDT$Version)
if (any(installed)) {
set(pkgDT, NULL, "installed", installed)
set(pkgDT, NULL, "installed", installed)
pkgDT
}

# When a package is already loaded in the current R session with a version
# that satisfies the user's version constraint, mark it as installed so the
# downstream gate skips reinstall. Trying to upgrade a loaded package whose
# namespace is imported by another loaded package (e.g. `reproducible` ->
# `climateData`) is the most common cause of pak's
# "Error : ! error in pak subprocess" — pak can't unload the live namespace
# to swap in the new version, the subprocess aborts, and the user is left
# with a useless generic error. If the loaded version already meets the
# requested constraint, there is no reason to reinstall in the first place.
#
# Side-effect: also flags `loadedSufficient = TRUE` so doLoads() can attach
# via `require(x, character.only = TRUE)` without `lib.loc`, avoiding R's
# "cannot be unloaded because <X> is imported by <Y>" error path.
useLoadedIfSufficient <- function(pkgDT,
libPaths = .libPaths(),
standAlone = FALSE,
verbose = getOption("Require.verbose")) {
if (!NROW(pkgDT)) return(pkgDT)
if (!"needInstall" %in% names(pkgDT)) return(pkgDT)
candidates <- which(pkgDT[["needInstall"]] %in% .txtInstall)
if (!length(candidates)) return(pkgDT)
loaded <- loadedNamespaces()
loaded <- setdiff(loaded, .basePkgs)
if (!length(loaded)) return(pkgDT)
if (!"loadedSufficient" %in% names(pkgDT))
set(pkgDT, NULL, "loadedSufficient", FALSE)
# standAlone = TRUE means the user wants the package physically present in
# libPaths[1]; a namespace loaded from another library does NOT satisfy that.
effectiveLibPaths <- if (isTRUE(standAlone))
normPath(libPaths[1L]) else normPath(libPaths)
intercepted <- character(0)
reasons <- character(0)
for (i in candidates) {
pkg <- pkgDT[["Package"]][i]
if (!pkg %in% loaded) next
loadedVer <- tryCatch(as.character(getNamespaceVersion(pkg)),
error = function(e) NA_character_)
if (is.na(loadedVer) || !nzchar(loadedVer)) next
vSpec <- pkgDT[["versionSpec"]][i]
ineq <- pkgDT[["inequality"]][i]
hasConstraint <- !is.na(vSpec) && nzchar(vSpec) &&
!is.na(ineq) && nzchar(ineq)
if (hasConstraint) {
ok <- isTRUE(compareVersion2(loadedVer, vSpec, ineq))
if (!ok) next
}
lp <- tryCatch(dirname(system.file(package = pkg)),
error = function(e) NA_character_)
if (!nzchar(lp)) lp <- NA_character_
if (!is.na(lp) && !normPath(lp) %in% effectiveLibPaths) next
set(pkgDT, i, "installed", TRUE)
set(pkgDT, i, "installedVersionOK", TRUE)
set(pkgDT, i, "needInstall", .txtDontInstall)
set(pkgDT, i, "Version", loadedVer)
if (!is.na(lp)) set(pkgDT, i, "LibPath", lp)
set(pkgDT, i, "loadedSufficient", TRUE)
intercepted <- c(intercepted, pkg)
reasons <- c(reasons,
if (hasConstraint)
paste0(pkg, " ", loadedVer, " satisfies ", ineq, " ", vSpec)
else
paste0(pkg, " ", loadedVer, " (no version constraint)"))
}
if (length(intercepted)) {
messageVerbose(
"Already loaded with sufficient version, skipping reinstall: ",
paste(unique(reasons), collapse = "; "),
verbose = verbose, verboseLevel = 1)
}
pkgDT
}
Expand Down
334 changes: 284 additions & 50 deletions R/Require2.R

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion R/RequireOptions.R
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,11 @@ RequireOptions <- function() {
"terra",
"units"
), # c("raster", "s2", "sf", "sp", "units")
Require.snapshotInstaller = "pak",
Require.snapshotInstallerUsePPM = TRUE,
Require.standAlone = TRUE,
Require.useCranCache = FALSE,
Require.usePak = FALSE,
Require.usePak = TRUE,
Require.updateRprofile = FALSE,
Require.verbose = 1
)
Expand Down
36 changes: 31 additions & 5 deletions R/extract.R
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,20 @@ extractPkgName <- function(pkgs, filenames) {
#' ))
extractVersionNumber <- function(pkgs, filenames) {
if (!missing(pkgs)) {
hasVersionNum <- grepl(grepExtractPkgs, pkgs, perl = FALSE)
out <- rep(NA, length(pkgs))
out[hasVersionNum] <- gsub(grepExtractPkgs, "\\2", pkgs[hasVersionNum], perl = FALSE)
## Strip pak's source prefixes (any::, cran::, github::, url::) before
## attempting version extraction; without this an "any::pkg@ver" ref
## doesn't match either form.
pkgsBare <- sub("^[A-Za-z][A-Za-z0-9+.-]*::", "", pkgs)
hasVersionNum <- grepl(grepExtractPkgs, pkgsBare, perl = FALSE)
out <- rep(NA, length(pkgsBare))
out[hasVersionNum] <- gsub(grepExtractPkgs, "\\2", pkgsBare[hasVersionNum], perl = FALSE)
## Also handle pak's "pkg@ver" form -- skip GitHub refs (owner/repo@sha)
## by requiring no "/" in the part before "@".
if (isTRUE(getOption("Require.usePak", FALSE))) {
atForm <- is.na(out) & grepl("@", pkgsBare, fixed = TRUE) &
!grepl("/", sub("@.*$", "", pkgsBare), fixed = TRUE)
out[atForm] <- sub("^[^@]+@", "", pkgsBare[atForm])
}
} else {
if (!missing(filenames)) {
fnsSplit <- strsplit(basename(filenames), "_")
Expand Down Expand Up @@ -115,12 +126,27 @@ trimVersionNumber <- function(pkgs) {
if (!is.null(pkgs)) {
nas <- is.na(pkgs)
if (any(!nas)) {
## Strip pak source prefixes first (any::, cran::, etc.) so the bare
## name matches downstream string ops (installed.packages() rownames,
## pkg_history lookups). Leave url:: alone -- those callers usually
## want the URL preserved.
hasPrefix <- grepl("^[A-Za-z][A-Za-z0-9+.-]*::", pkgs[!nas]) &
!startsWith(pkgs[!nas], "url::")
pkgs[!nas][hasPrefix] <- sub("^[A-Za-z][A-Za-z0-9+.-]*::", "", pkgs[!nas][hasPrefix])
ew <- endsWith(pkgs[!nas], ")")
if (getOption("Require.usePak", FALSE))
ew <- ew | grepl("@", pkgs[!nas])
if (any(ew)) {
pkgs[!nas][ew] <- gsub(paste0("\n|\t|", .grepVersionNumber), "", pkgs[!nas][ew])
}
## pak "pkg@ver" form. Skip GitHub refs (owner/repo@sha) by requiring
## no "/" before the "@". Only active when usePak so non-pak callers
## keep their existing behavior.
if (isTRUE(getOption("Require.usePak", FALSE))) {
atForm <- grepl("@", pkgs[!nas], fixed = TRUE) &
!grepl("/", sub("@.*$", "", pkgs[!nas]), fixed = TRUE)
if (any(atForm)) {
pkgs[!nas][atForm] <- sub("@.+$", "", pkgs[!nas][atForm])
}
}
}
pkgs
}
Expand Down
9 changes: 7 additions & 2 deletions R/helpers.R
Original file line number Diff line number Diff line change
Expand Up @@ -640,8 +640,13 @@ SysInfo <-
}

.runLongExamples <- function() {
.isDevelVersion() ||
Sys.getenv("R_REQUIRE_RUN_ALL_EXAMPLES") == "true"
# Auto-enable based on .isDevelVersion() is unsafe: with
# `--run-dontrun --run-donttest` (default in r-lib/actions/check-r-package),
# every dev-version R CMD check runs the full Require::Install() cascade
# for every example in Require.Rd — hours on a cold CI runner.
# Require explicit opt-in (R_REQUIRE_RUN_ALL_EXAMPLES=true) regardless of
# version. Devs can set it in .Renviron locally.
Sys.getenv("R_REQUIRE_RUN_ALL_EXAMPLES") == "true"
}

doCranCacheCheck <- function(localFiles, verbose = getOption("Require.verbose")) {
Expand Down
Loading
Loading