fix(patches): validator portability, clearer docs, broader hook trigger
This commit is contained in:
parent
a826a27246
commit
f3f3bfa20d
1 changed files with 2428 additions and 8 deletions
95
.superpowers/handoff/task-A0-brief.md
Normal file
95
.superpowers/handoff/task-A0-brief.md
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
### Task A0: Proof of mechanism — pak installs a patched binary from a prepended `file://` repo
|
||||
|
||||
This de-risks the core assumption before building anything on top: that `pak` installs a binary from a local `file://` repo in preference to CRAN for an equal version, and does so without recompiling. If this fails, the contingency (documented in Step 4) is to serve patched *source* and rely on `pkgcache` build-caching — the rest of the plan changes only inside `build_patched_binary()`.
|
||||
|
||||
**Files:**
|
||||
- Create: `tools/verify-patch-mechanism.R`
|
||||
|
||||
**Interfaces:**
|
||||
- Produces: a runnable script proving `pak::pkg_install()` resolves a local patched binary over CRAN. No package API.
|
||||
|
||||
- [ ] **Step 1: Write the verification script**
|
||||
|
||||
```r
|
||||
# tools/verify-patch-mechanism.R
|
||||
# Proves pak installs a patched binary from a prepended file:// repo instead of
|
||||
# CRAN's, without recompiling. Run inside a Linux build-env container:
|
||||
# Rscript tools/verify-patch-mechanism.R
|
||||
# Exits 0 on success, 1 on failure.
|
||||
|
||||
pkg <- "glue" # small, pure-R CRAN package
|
||||
sentinel <- "PatchMechanismProof"
|
||||
|
||||
work <- tempfile("verify_")
|
||||
repo <- file.path(work, "repo", "src", "contrib")
|
||||
lib <- file.path(work, "lib")
|
||||
dir.create(repo, recursive = TRUE)
|
||||
dir.create(lib, recursive = TRUE)
|
||||
|
||||
# 1. Download CRAN source for the current version.
|
||||
ap <- available.packages(repos = "https://cloud.r-project.org")
|
||||
ver <- ap[pkg, "Version"]
|
||||
src <- file.path(work, sprintf("%s_%s.tar.gz", pkg, ver))
|
||||
download.file(
|
||||
sprintf("https://cloud.r-project.org/src/contrib/%s_%s.tar.gz", pkg, ver),
|
||||
src, mode = "wb"
|
||||
)
|
||||
|
||||
# 2. Unpack, inject a sentinel field into DESCRIPTION, build a binary.
|
||||
untar(src, exdir = work)
|
||||
desc <- file.path(work, pkg, "DESCRIPTION")
|
||||
writeLines(c(readLines(desc), sprintf("%s: yes", sentinel)), desc)
|
||||
pkgbuild::build(
|
||||
file.path(work, pkg), binary = TRUE, vignettes = FALSE,
|
||||
dest_path = repo, quiet = TRUE
|
||||
)
|
||||
built <- list.files(repo, pattern = sprintf("^%s_.*\\.tar\\.gz$", pkg), full.names = TRUE)
|
||||
file.rename(built[1L], file.path(repo, sprintf("%s_%s.tar.gz", pkg, ver)))
|
||||
cranlike::add_PACKAGES(sprintf("%s_%s.tar.gz", pkg, ver), repo)
|
||||
|
||||
# 3. Install with the local repo prepended; assert our patched build won.
|
||||
withr::with_options(
|
||||
list(repos = c(patched = sprintf("file://%s", dirname(dirname(repo))),
|
||||
CRAN = "https://cloud.r-project.org")),
|
||||
pak::pkg_install(pkg, lib = lib, ask = FALSE, upgrade = FALSE)
|
||||
)
|
||||
|
||||
installed_desc <- file.path(lib, pkg, "DESCRIPTION")
|
||||
ok <- file.exists(installed_desc) &&
|
||||
any(grepl(sentinel, readLines(installed_desc)))
|
||||
|
||||
if (ok) {
|
||||
cat("PROOF PASSED: pak installed the patched local binary.\n")
|
||||
quit(status = 0L)
|
||||
} else {
|
||||
cat("PROOF FAILED: pak did not install the patched local binary.\n")
|
||||
quit(status = 1L)
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Run the proof in a build-env container**
|
||||
|
||||
Run (amd64 example; use any supported build-env image):
|
||||
|
||||
```bash
|
||||
just build-single ubuntu 2604 amd64 4.5.0 glue 1.0.0 1 || true # warms the env
|
||||
docker run --rm -v "$PWD":/work -w /work reg.devxy.io/rpkgs/build-env-ubuntu:2604 \
|
||||
Rscript tools/verify-patch-mechanism.R
|
||||
```
|
||||
|
||||
Expected: final line `PROOF PASSED: pak installed the patched local binary.` and exit status 0.
|
||||
|
||||
- [ ] **Step 3: Commit**
|
||||
|
||||
```bash
|
||||
git add tools/verify-patch-mechanism.R
|
||||
git commit -m "test(patches): prove pak installs a patched binary from a local file:// repo"
|
||||
```
|
||||
|
||||
- [ ] **Step 4: Record the outcome / contingency**
|
||||
|
||||
If the proof PASSED, proceed to Task A1 unchanged.
|
||||
If it FAILED (pak recompiled or picked CRAN's), the mechanism switches to serving patched *source*: in Task A4 `build_patched_binary()` skips `pkgbuild::build()` and instead repackages the patched source tree with `pkgbuild::build(binary = FALSE)`; everything else (registry, matching, cache, repo prepend) is unchanged because `pak` build-caches the compiled result via `pkgcache`. Note the chosen path in the commit message and continue.
|
||||
|
||||
---
|
||||
|
||||
Loading…
Reference in a new issue