build-cran-binaries/.superpowers/handoff/task-A0-brief.md

95 lines
3.8 KiB
Markdown

### 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.
---