Skip to content

Mac test fixes + pak cascade fix#149

Open
eliotmcintire wants to merge 104 commits intodevelopmentfrom
usePak
Open

Mac test fixes + pak cascade fix#149
eliotmcintire wants to merge 104 commits intodevelopmentfrom
usePak

Conversation

@eliotmcintire
Copy link
Copy Markdown
Contributor

Summary

Three groups of fixes that together resolve all R-CMD-check / testthat failures on macOS R 4.5 and reduce skipped tests from 8 to 5.

Code fixes

  • useLoadedIfSufficient now honors standAlone: a package loaded from a parent libpath no longer suppresses a fresh install into libPaths[1].
  • pak post-install warning fires correctly when pak installs a version that doesn't satisfy the user's >= constraint (handles first-time install, version-changed, and pak-chose-installed cases; pak-resolved-version comparison is now against user's spec, not against installed version).
  • Big one: pakGetArchive now returns the source Archive URL (/Archive/X/X_ver.tar.gz) instead of a stale binary URL. The previous code preferred the macOS binary URL when available.packages(type='binary') listed the package — but for archived-from-source packages whose Mac binary was pruned, that URL is dead. The cascade install of pryr (and via it, LandR -> PSPclean -> pemisc -> ...) now recovers cleanly.
  • pak path now surfaces the same 'did you spell the GitHub.com repository correctly' hint that the non-pak path emits when a GH ref can't be resolved.

Test re-enablement (now run and pass thanks to the cascade fix)

  • test-08 modules: gated on isDev (was isDevAndInteractive); now runs the full module-install scenario.
  • test-10 DifferentPkgs: same gate change + drop the !isMacOS() guard.
  • test-11 misc: added pak-path assertion for misspelled-GitHub-user (verifies the new spelling-hint code).

Test portability

  • .Library instead of hardcoded /usr/lib/R/library in test-16 cross-platform fixtures.
  • parentChain test keeps the existing skip with a TODO note: the parentChain feature isn't implemented in pak's pkgDep path.

Test plan

🤖 Generated with Claude Code

eliotmcintire and others added 30 commits April 2, 2026 16:40
When options(Require.usePak = TRUE):
- pakDepsToPkgDT(): resolves full dependency tree via pak::pkg_deps(),
  converting pak tibble format to Require's pkgDT. Falls back to
  toPkgDTFull() if pak fails (e.g., archived packages, dep conflicts).
- pakInstallFiltered(): installs only packages that Require's version-
  priority gate (whichToInstall) determined need installing, using
  dependencies = NA so pak respects build ordering.
- Shared pipeline (checkHEAD, installedVers, whichToInstall) runs for
  both pak and non-pak paths, preserving Require's version-requirement
  priority behavior.

Bug fixes in existing pak support code:
- pakCacheDeleteTryAgain: fix "condition has length > 1" when pkg3 is vector
- pakGetArchive: strip any:: prefix before pkg_history; guard his$Package
  when his is try-error; fix type uninitialized on Linux; fix grep()
  returning integer(0) when isCRAN is empty
- pakErrorHandling: guard Map subscript-out-of-bounds when grep returns
  integer(0); unlist() Map result before gsub
- lessThanToAt/pakCheckGHversionOK: replace browser() with graceful returns
- pakInstallFiltered: add pak's own library to .libPaths() for subprocess;
  post-install version check for impossible constraints; tryCatch around
  pakErrorHandling to prevent crashes propagating up
- installedVers: always set 'installed' column even when all are FALSE

Remove obsolete snapshot warning (.txtPakCurrentlyPakNoSnapshots) and
corresponding test guards since snapshots now work with pak.

Test changes:
- setup.R: Require.usePak driven by R_REQUIRE_USE_PAK env var (not hardcoded)
- test-08, test-09: remove skip_if(usePak) guards
- test-00pkgSnapshot, test-01packages: remove okWarn checks for removed warning

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Two root causes of GHA failures on macOS/Windows:
1. Require.offlineMode=TRUE (set by a network failure in a previous test)
   caused pkgDepCRAN to skip its entire block, emitting no messages.
2. Require.useCache=TRUE may return a cached pryr dep entry, bypassing
   getDepsNonGH entirely for pryr (no pkgDepCRAN call, no message).

Fix: reset both options at test start (restored on exit).

Also remove the real_join call from the mock — the mock now constructs
the return value directly, making zero network calls and eliminating
any risk of setOfflineModeTRUE being called mid-test.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…from transitive deps

- pakInstallFiltered: revert dependencies=FALSE back to NA (accidentally changed
  during today's refactor). FALSE caused LearnBayes-style install failures and left
  transitive deps (DBI, Formula, etc.) with installed=FALSE, installResult=NA.
- pakDepsToPkgDT: filter 'Require' from all_reqs. Full transitive dep resolution
  now pulls Require into pkgDT (as dep of SpaDES.core/LandR); since Require is
  loaded from devtools (not in test tmpdir), installedVers() marks it not installed,
  needToRestartR() fires NeedRestart=TRUE, and data.table/sys incorrectly get
  "Need to restart R" instead of "Can't install Require dependency".
- Various pak integration improvements: archived transitive dep supplement
  mechanism, pakPkgDep includeSelf url:: fix, compact conflict messaging,
  per-package fallback for unresolvable batch conflicts, isCRANlike "/" fix,
  pakCacheDeleteTryAgain setdiff bug, pakErrorHandling .txtFailedToBuildSrcPkg
  direct regex extraction.
- Bump version to 1.1.0.9002, update NEWS.md.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…sion philosophy

pak with dependencies=NA re-resolves deps and upgrades already-satisfied packages
(e.g. tibble 3.2.1→3.3.1 when no constraint requires it). Require's philosophy is:
only install/update what the version specs require. Switch back to dependencies=FALSE
so pak installs exactly what Require determined, nothing more. pak still reads
DESCRIPTION files for topological ordering even with dependencies=FALSE, so
install ordering remains correct given that pakDepsToPkgDT supplies the complete
transitive dep tree.

Also fix post-install update loop: use wh[1L] only for scalar reads (versionSpec/
inequality) but full wh vector for set() calls, so duplicate Package rows in pkgDT
(if any survive trimRedundancies) are all updated consistently.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Two-tier dep cache (in-memory + disk, 24h TTL) via pakDepsResolve()
- pakCall() wrapper for verbose suppression (3 levels: full/messages/silent)
- Version satisfiability check: warn and exclude packages with impossible constraints
- standAlone=TRUE trims .libPaths() for pak subprocess
- Fix logical(0) return when all packages excluded due to unsatisfiable constraints
- Document repos limitation (pak always includes CRAN/Bioc regardless of options(repos))
- Conflict/archive resolution table in retry loop

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…WhoNeeds diagnostic

- url:: fix (pakDepsToPkgDT): break SEXP aliasing between Package and packageFullName
  before any := operations. toPkgDTFull sets both columns to the same character
  vector SEXP for url:: refs (extractPkgName returns input unchanged). Using
  as.character() to allocate a new vector makes the columns independent, so
  Package can be set to the plain package name while packageFullName retains
  the full archive URL needed by pakInstallFiltered.

- dep-conflict handler (pakDepsResolve): only add a conflict table entry when a
  concrete GitHub ref is found. Without one the error is a version-solver conflict
  (incompatible transitive version constraints), not a Remotes clash. Previously
  the table showed misleading "via pkg Remotes" entries for BH, DBI, etc.

- Add pakWhoNeeds() diagnostic: queries the in-memory pak cache to show which
  packages list a given package as a direct dependency. Useful for debugging
  unexpected conflicts (e.g. Require:::pakWhoNeeds("BH")).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The step-3b check compared pak's resolved version against the user's >=
constraint. For GitHub refs like PredictiveEcology/reproducible@recovery,
pak may have resolved an older CRAN or cached version for the same package
name, causing compareVersion2() to return FALSE and emit a spurious
"could not be installed" warning even though the branch exists and satisfies
the constraint.

Fix: skip GitHub (owner/repo@branch) and url:: refs in the satisfiability
check. For those refs pak installs directly from the specified branch/URL
and will error itself if the version constraint cannot be met. Only CRAN-like
packages (where pak silently installs the latest) need this pre-flight check.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
compareVersion2("", "1.0.0", ">=") returns FALSE, so packages where pak
returned an empty or NA version would spuriously appear in badPkgs and
trigger the "could not be installed" warning. Skip them: if pak couldn't
determine a version it can't be used to reliably reject the package.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When pak fails to build a package (e.g. compile error), the old version
stays installed. The post-install check was comparing that unchanged old
version against the required constraint and emitting "Please change
required version e.g., LandR (>=1.1.5.9058)" -- telling the user to
lower their requirement to the pre-existing version, which is wrong and
confusing.

Snapshot pre-install versions before pakRetryLoop runs. If the version
is unchanged after the attempt, the install failed (build error or
cancelled batch) and pakRetryLoop already emitted "could not be
installed". Skip the misleading suggestion in that case. Only emit
"Please change required version" when pak actually installed a different
(but still insufficient) version.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Four related fixes:

1. Detect "lazy loading failed" in sysInstallAndDownload's early-return
   pattern (line ~3675) so the function returns the logFile immediately
   instead of falling through to the compareVersion2 check with stale state.

2. Replace try(!compareVersion2(...)) with tryCatch(..., error=) so the
   "invalid argument type" crash is silenced rather than printed to stderr
   when dt$vers is NULL or mismatched (happens when args$pkgs is empty).

3. Guard the "-- To install: " print with nzchar(trimws(fullMess)) so a
   blank message is not emitted when args$pkgs is empty.

4. Real fix: after a failed install, scan the log for
   "namespace 'X' Y is being loaded, but >= Z is required".  When found,
   install X (>= Z) immediately and retry the failing package.  This
   handles the case where e.g. LandR 1.1.5.9100 requires
   SpaDES.tools >= 2.1.1 but only 2.0.9 is installed — Require now
   detects the mismatch from the install log and upgrades SpaDES.tools
   before the retry, rather than failing and requiring the user to
   diagnose and re-run manually.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add pakBuildFailReason() helper that strips ANSI codes from pak's error
output and extracts the most informative diagnostic line(s) (namespace
version mismatch, invalid regex, compile failure, locked file, etc.).

In pakRetryLoop:
- Track whether the tryCatch error handler already issued a "could not
  be installed: <reason>" warning.  If so, suppress the previously bare
  duplicate warning when packages becomes empty.
- When packages becomes empty and no warning was yet issued, attach the
  extracted reason: "could not be installed: <why>" instead of the bare
  "could not be installed".

Before:
  Warning: could not be installed: invalid regular expression ...  (from tryCatch handler)
  Warning: could not be installed                                   (bare duplicate)
  Warning: Please change required version e.g., LandR (>=1.1.5.9058) (misleading)

After:
  Warning: could not be installed: invalid regular expression ...  (single, informative)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When pak reports "sp: dependency conflict" because e.g. SpaDES.core has sp
in its Remotes, the "Conflicts with" error line reads:
  PredictiveEcology/SpaDES.core@development: Conflicts with sp

The previous code picked lhs2 (SpaDES.core) as the GitHub ref for sp,
producing the nonsensical table entry "sp vs PredictiveEcology/SpaDES.core".

Fix: after extracting the candidate ref, check extractPkgName(cand) == dcp.
If not, record it as viaRef (the package whose Remotes caused the conflict)
and use the new Case 2 message: "sp (CRAN) via SpaDES.core Remotes".

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
"sp (CRAN) via SpaDES.core Remotes" was ambiguous.
Now shows: "sp (CRAN)  vs  sp (via SpaDES.core Remotes)" — same parallel
structure as the direct-conflict rows (e.g. "quickPlot  vs  owner/quickPlot@branch").

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Was: sp (CRAN)  vs  sp (via SpaDES.core Remotes)
Now: sp (CRAN)  vs  sp (via PredictiveEcology/SpaDES.core@development Remotes)

Keep cand (the full ref) instead of extractPkgName(cand) so the user
can see exactly which version of SpaDES.core is pulling in the alternate sp.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
In-memory and disk cache hit messages were at verboseLevel = 2, so users
at the default verbosity never saw them. Lowering to 1 makes it visible
that subsequent Require() calls are using a cached dep tree rather than
querying pak/CRAN again.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Extract pakDepConflictRow() helper from inline pakDepsResolve loop so
  the conflict-message logic is directly unit-testable
- Fix stale test-13coverage assertion: Require.usePak default is now TRUE
- New test-17usePak.R (23 tests):
    * RequireOptions default Require.usePak = TRUE
    * pakBuildFailReason: ANSI stripping, namespace mismatch, file lock,
      lazy loading, compilation failure, <=2 lines, fallback, empty result
    * pakDepConflictRow: same-package case, via-other-Remotes case, empty cand
    * pakDepsResolve in-memory cache message at verbose=1 (not at verbose=0)
    * pakDepsResolve disk cache message at verbose=1

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Document all pak-backend changes from this session: default usePak=TRUE,
improved build-failure messaging, suppressed misleading version-change
warnings, clearer Remotes-conflict table entries, dep-tree cache messages
at verbose=1, and automatic namespace-version retry in non-pak path.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1. pakDepConflictRow: guard against character(0) cand (not just "")
   The conflict-parsing code can produce cand = character(0) when no
   matching "Conflicts with" line exists. Change !nzchar(cand) to
   !length(cand) || !nzchar(cand). Add unit test for this case.

2. test-01packages: accept "Please change required version" as valid
   With pak, installing PredictiveEcology/fpCompare (>=2.0.0) succeeds
   at version 0.2.4 (best available), then post-install check emits
   "Please change required version" rather than "could not be installed".
   Both messages correctly indicate the constraint cannot be met; the
   test now accepts either.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…c ref

Root cause: when the user supplies a GitHub ref with no version spec
(e.g. "owner/Pkg@branch") and a transitive dep has a CRAN entry with a
version spec ("Pkg (>= X.Y)"), trimRedundantVersionAndNoVersion removes
the GitHub ref (no version) in favour of the CRAN one (has version).
After this, pkgDT$packageFullName = "Pkg (>= X.Y)", but recordLoadOrder
compared trimVersionNumber(pfn) = "Pkg" against packagesWObase =
"owner/Pkg@branch" — no match → loadOrder never set → base::require()
never called for that package.

Fix: also match by plain Package name (extractPkgName) so that any row
whose Package column matches a user-requested package gets loadOrder set,
regardless of which packageFullName format survived trimRedundancies.

Add two regression tests:
- recordLoadOrder sets loadOrder when GitHub ref replaced by CRAN spec
- trimRedundancies keeps only the highest version for duplicate GH refs
  (production LandR Install() regression test)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…lled

pakDepsToPkgDT step-3b compared pak's CRAN-resolved version against the
user's constraint.  When a dev-version package (e.g. LandR >= 1.1.5.9064)
was already installed satisfying the constraint, but pak's CRAN resolution
returned an older version, the package was incorrectly removed from user_pkgFN.
If the package was not a transitive dep of anything else it disappeared from
pkgDT entirely, recordLoadOrder() could not find it, and base::require() was
never called — the package was installed but never attached.

Fix: before removing a package from the list in step-3b, check if the
installed version satisfies the constraint.  Only truly-unsatisfiable packages
(neither pak's resolution nor the installed version can meet the constraint)
are removed and warned about.

Adds test-17 section 8 covering this scenario.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… list

When a GitHub source package (e.g. map) fails to build, pakRetryLoop clears
pak's cache and retries once.  On the second failure pakErrorHandling removes
the package from the install list so the remaining 62 packages can still
succeed.  Previously this produced zero output from Require — the user saw
pak's ✖ Failed to build map line but no Require warning explaining what
happened or which other packages (e.g. climateData that imports map) were
also left uninstalled.

Fix:
- pakRetryLoop now compares the package list before/after pakErrorHandling.
  Any packages permanently dropped (list shrank) trigger an immediate warning
  with the build failure reason from pakBuildFailReason().
- A second pass after the update loop warns about packages that were in
  toInstall but are still not installed after all retries (cascade failures
  not covered by the first pass).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When pak's CRAN resolution can't satisfy a dev-version constraint (e.g.
LandR >= 1.1.5.9100 but CRAN has 1.1.3.9), step-3b in pakDepsToPkgDT
removes the package from the local packages list to avoid a false warning.
If that package is NOT pulled in as a transitive dep of any other package,
it ends up completely absent from pkgDT — so recordLoadOrder() cannot
set loadOrder, and doLoads() never calls require().

Fix: after the main pipeline (but before doLoads), check if any
user-requested package is absent from pkgDT but installed at a
satisfying version.  If so, rbind a minimal row back with loadOrder set
and installedVersionOK = TRUE so doLoads() will attach it.

Also:
- Use libPaths argument (not .libPaths()) in step-3b so the "is it
  installed?" check uses the same paths that doLoads() / installedVers()
  will use, fixing a potential mismatch for standAlone = TRUE.
- Add verbose >= 1 diagnostics in doLoads() to report packages that have
  loadOrder set but won't be loaded (installedVersionOK = FALSE) and
  packages where base::require() itself returns FALSE.
- Add test for the recovery mechanism.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
R's default warn=0 collects warnings and shows them only at session end
("There were 20 warnings").  When map fails to build during a large pak
batch, the "Could not be installed: map; ..." warning and any cascade
failures (e.g. climateData) were silently queued, not visible in the
console.  Using immediate. = TRUE bypasses the buffer so the user sees
the failure notification right when it happens — between the
"✖ Failed to build map" pak line and the subsequent simInit startup.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When Require.verbose <= 0, require() was called with quietly=TRUE and
any failure was silently swallowed — the only symptom was a downstream
error like "object 'sppEquivalencies_CA' not found" with no hint that
LandR (or any other package) failed to attach.

Fix: wrap require() in withCallingHandlers to capture its own warning
messages, then unconditionally emit a warning(immediate.=TRUE) when
require() returns FALSE. The warning includes the underlying R message
and the full libPaths that were searched, making the root cause
immediately visible.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When pak cannot install a newer version but an older version is already
present, load the installed version with a warning instead of refusing
to attach at all.  Previously the contradictory combination of
installResult="could not be installed" + require=FALSE left packages
completely unattached, causing confusing downstream errors like
"object not found" with no hint about the real cause.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When pakErrorHandling doesn't recognise the error pattern (packages list
unchanged after handling), stop retrying immediately and include the raw
pak error reason in the warning.  Also thread lastPakErr into the
silentlyFailed fallback path.  Previously: bare "could not be installed:
LandR" with 15 silent retries and no explanation.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Switch dependencies=FALSE → dependencies=NA so pak can satisfy any
new dep requirements in the latest DESCRIPTION of GitHub dev packages
that weren't in Require's earlier dep-tree snapshot.  Also fix a
spurious "Please change required version" warning that fired when a
package was absent from the library before the install attempt (NA
pre-install version was incorrectly compared to post-attempt version).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
pak::pak() with upgrade=FALSE treats a bare 'owner/repo@branch' ref as
satisfied by any installed version of that package, so it 'keeps' e.g.
LandR 1.1.5.9088 even when 1.1.5.9100 is required.  Fix: split the
install call — GitHub/url:: packages use upgrade=TRUE (always fetch
latest from branch), CRAN-like packages keep upgrade=FALSE (don't
over-upgrade already-satisfied deps).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
eliotmcintire and others added 30 commits May 3, 2026 22:27
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
knn is an off-CRAN archive package; its source can fail to compile under
R-devel toolchains. Skip when the install genuinely doesn't land rather
than fail as a Require regression — all stable R versions still assert.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
pak::pkg_history is single-package; given a vector ref or one it can't
parse it returns try-error, so his$Version blew up with "$ operator is
invalid for atomic vectors". Skip the version-pin warning block when
his isn't a data.frame and let the existing try-error handler clean up.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Drop the isDevAndInteractive && isMacOS() guard that was hiding the
test from CI runs, and drop three browser() calls left over from
debugging. Test still gated by getRversion() <= 4.4.3 so it only
runs on R that matches the snapshot.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The 9-iteration grp/pat loop was re-splitting err by newline on every
iteration. Hoist the strsplit so it runs once. Modest savings (~3%
of pkgDep on a 30-pkg snapshot per profiling), but it's the cheap
half of a larger pkgDep perf fix series.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two optimizations on the pkgDep hot path measured against a 30-pkg
slice of the LandR snapshot:

1. pakPkgDep memoizes pak::pkg_deps results in pakEnv() keyed on
   (refs + supplement + which). pak::pkg_deps was previously called
   afresh on every Map iteration, paying the full callr subprocess
   cost; recursive pkgDep traversals revisit the same refs.

2. pakErrorHandling pre-screens with a single combined check across
   the 9 grp patterns and exits early when none match. Within the
   loop, switches grep() to fixed=TRUE for the 8 literal patterns
   (only .txtFailedToDLFrom is a regex).

Net: 30-pkg pkgDep dropped from 635s to 497s (~22%). Remaining cost
is dominated by per-failure pakErrorHandling string parsing.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
A 30-pkg slice of the snapshot profiles at ~8 min for pkgDep alone;
the full 380-pkg test runs to multiple hours including the install
itself. Run locally via R_REQUIRE_RUN_ALL_TESTS=true.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
packageFullNameFromSnapshot was unconditionally appending "(==Version)"
to every row. For a GitHub@SHA pin without a Version field, that
produced "owner/repo@<sha> (==NA)", which downstream got mangled into
"owner/repo@<sha>@na" -- pak then refused to install it. Skip the
version suffix for GH refs (the SHA already pins identity) and for
rows with no Version at all.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Exercises the version-pin install paths Require must support without
the LandR-shaped Remotes-conflict mess that makes test-09 unrunnable
on CI:
  - 4 CRAN packages pinned to non-current versions in CRAN Archive
    (crayon 1.4.0, glue 1.4.0, lifecycle 1.0.0, cli 3.4.0)
  - 1 GitHub@SHA pin (r-lib/R6 at a Dec-2023 SHA, leaf package with
    no Imports/Remotes)

Lightweight enough to run under CI budget and gives continuous
coverage of the snapshot-install code path.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…e version

Three stacked bugs that together caused pak's install path to fail
silently on R 4.3 and to install the wrong version when archive
fallback succeeded:

1. pakCall used `verbose %||% 0L`. `%||%` is base in R 4.4+ but not in
   R 4.3, and Require doesn't import it from rlang. Every pak install
   call in pakSerialInstall errored on R 4.3 inside try(silent=TRUE),
   so every per-pkg install was a no-op -- a 380-pkg snapshot install
   ended with only ~35 packages (just the seed pre-install). Replaced
   with explicit is.null() check.

2. pakGetArchive built archive URLs from `tail(pak::pkg_history, 1)`,
   the LATEST archive entry. A snapshot ref like "BH@1.81.0-1"
   produced a URL for "BH_1.90.0-1.tar.gz" -- pak then 404'd. Now
   extracts the requested version from the input ref and picks the
   matching pkg_history row.

3. Archive fallback called pakGetArchive(bare_name) so the version pin
   was lost before pakGetArchive ever saw it. Built a bare->ref map at
   the call site and threaded the original version-pinned ref through.

extract.R: extractVersionNumber and trimVersionNumber now strip pak's
source prefixes (any::, cran::, github::) and handle pak's "pkg@ver"
ref form (under usePak), reusing the same helpers across non-pak and
pak code paths instead of introducing parallel logic.

pak.R: pakSerialInstall now calls pakResetSubprocess() after a failed
ref so a wedged r_session doesn't cascade-fail every subsequent ref
in the loop.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file was a half-built experiment trying to install the LandR
2024-06 dep tree against PPM. We discovered pak unconditionally
follows DESCRIPTION Remotes (no public flag to disable), so any PE
package's "Remotes: ...@development" overrides our SHA pins and the
install plan never solves. Locally the test always failed. On CI,
covr's runner doesn't respect skip_on_ci() the same way testthat
does, so the failures surfaced there too.

test-19 now covers the same testing surface (CRAN version pin +
GitHub@SHA pin) with a fixture that actually installs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
covr::codecov() reports failures as 'Failure in .../testthat.Rout.fail'
without printing what's actually in the file, so CI failures are opaque.
Wrap covr::codecov() in tryCatch and dump the .Rout.fail contents on
error before re-raising, so the next failed run shows which test failed
and why.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
covr::codecov() hides test failures inside a temp .Rout.fail it deletes
before the workflow can read it. Run testthat::test_local() in the same
step first; failures stream straight to the action log. covr still runs
afterward when tests pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…nner)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
cli 3.4.0 (Sept 2022) and glue 1.4.0 both have C source that no longer
compiles against R 4.6 headers (CI failure: 'compilation failed for
package cli'). Replace both with pure-R archive pins (assertthat 0.2.0,
withr 2.5.0) so the fixture is toolchain-independent and the test
exercises the version-pin path without compile risk.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The ad-hoc pkgload::load_all + test_local prefix was only needed to
surface a failing test name through covr's .Rout.fail wrapping. With
the underlying test fix landed, restore the original single-line step.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Three files survived the rebase onto 48 upstream commits:

* test-09: add skip_if_offline2() so the long snapshot install test
  short-circuits when there's no network (it can't possibly pass
  offline anyway). Upstream had already removed the macOS / R-version
  skips.
* test-16: split the combined "drops resolved culprits AND labels
  archive build errors" test into two focused tests, each with the
  scenario it documents (deferred-pass success vs archive-pass
  compile failure). Auto-merged with upstream's fixture refresh.
* vignettes/Require.Rmd: restructure Key Features around the new
  pak-default behavior, add a "New default as of 2.0.0" section.

Two stashed changes were obsolete and dropped: a pak::pkg_history()
guard in R/pak.R (upstream now has a better version that also handles
the tail(., 1) snapshot-version bug), and edits to test-07 (replaced
upstream by test-19smallSnapshot_testthat.R).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant