aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CLAUDE.md55
-rw-r--r--README.md54
2 files changed, 99 insertions, 10 deletions
diff --git a/CLAUDE.md b/CLAUDE.md
index 139c896..9983392 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -53,7 +53,12 @@ Top-to-bottom layout:
`CHROOT_LOCATION=/tmp LOG_ROOT PKG_CACHE='' VERSION=15.0`, sources the config
if present
(NOT an error if missing, so the script stays sourceable by `test-logic.sh`),
- then derives `MIRROR_TREE`. `require_config` (called by `validate_env` and
+ then derives `MIRROR_TREE`. Also sets `SBO_RSYNC_URL` (empty default; rsync
+ source for the SBo tree itself, e.g. `slackbuilds.org::slackbuilds/15.0`,
+ the same source `sbopkg` uses, distinct from the NFS `LOCAL_MIRROR_15` which
+ is a package source only) and `SBO_PERSONAL_TREES` (empty bash associative
+ array; personal-subtree-dir-name -> git clone URL, cloned under
+ `SBO_TREE_ROOTS[0]`). `require_config` (called by `validate_env` and
`init_base`) is what hard-fails a real run when the config is absent or has
not set the required paths. `LOCAL_MIRROR_15` is the NFS mountpoint; the tree
is one level down, `MIRROR_TREE="$LOCAL_MIRROR_15/slackware64-$VERSION"`
@@ -77,10 +82,24 @@ Top-to-bottom layout:
6. **Dependency resolution** - `resolve_target` -> `_resolve_visit` (DFS topo
sort + cycle detection). Outputs `RESOLVED_ORDER[]`, records `UNMET[]`,
`CYCLES[]`, `HAS_README[]`. `installed_in_base` checks base package db.
-7. **Overlay lifecycle** - `setup_overlay` (echoes tmpdir, mounts overlay +
+7. **SBo tree lifecycle (`--setup-repo` / `--update`)** - `rsync_excludes`
+ (echoes one anchored `--exclude=/<dir>/` per `SBO_PERSONAL_TREES` key, the
+ safety invariant that keeps `rsync --delete` from ever touching a personal
+ clone), `rsync_tree` (runs the actual rsync from `SBO_RSYNC_URL` into the
+ tree root with those excludes applied), `collect_shadows` (read-only scan:
+ for each personal-subtree package, finds same-named upstream dirs elsewhere
+ in the tree), `shadow_scan` (prints `collect_shadows` output, confirms
+ interactively, then `rm -r`'s the confirmed set), `setup_repo` (`--setup-repo`
+ entry point: root check, confirm, `rm -rf` the tree root, `rsync_tree`, clone
+ each `SBO_PERSONAL_TREES` subtree, `shadow_scan`, exit; hard-fails on
+ rsync/clone error), `update_personal_trees` (`--update` entry point, runs
+ inline before a build: `rsync_tree` with `--delete` to refresh upstream and
+ undo prior shadows, `git pull` each personal subtree, `shadow_scan` again;
+ fail-soft, warns and continues on any network/git error).
+8. **Overlay lifecycle** - `setup_overlay` (echoes tmpdir, mounts overlay +
binds), `teardown_overlay` (idempotent, correct reverse order), `cleanup_trap`
(EXIT/INT/TERM, unwinds all live overlays).
-8. **build_one** - copies SlackBuild into overlay, runs download/md5/build/
+9. **build_one** - copies SlackBuild into overlay, runs download/md5/build/
installpkg INSIDE the chroot non-interactively via heredoc, reads back a
status token file, sets status maps. Logs resolved .info env up front and
the installed file list (from /var/log/packages) after installpkg, so the
@@ -92,11 +111,13 @@ Top-to-bottom layout:
echoed to the screen (indented) as well as the log, so problems are easy to
catch. Called while the overlay is still mounted so the host path to the .txz
is reachable; no cache dependency.
-9. **run_target** - fresh overlay per target, builds resolved chain in order,
- marks `BLOCKED-BY-DEP` on dependents of failures, tears down.
-10. **print_summary** - color screen recap + plain `summary.log`.
-11. **main** - parse, validate, make `RUN_DIR`, update base, collect targets
- (single-package or category-folder), run each.
+10. **run_target** - fresh overlay per target, builds resolved chain in order,
+ marks `BLOCKED-BY-DEP` on dependents of failures, tears down.
+11. **print_summary** - color screen recap + plain `summary.log`.
+12. **main** - parse; `--setup-repo` runs and exits before `validate_env`
+ (mirrors `--init-base`); `validate_env`; `--update` runs right after
+ (`update_personal_trees`, before `update_base`); make `RUN_DIR`, update
+ base, collect targets (single-package or category-folder), run each.
## Teardown order (do not reorder)
@@ -116,8 +137,12 @@ recorded separately as a reminder flag, not a status.
- **Verified by self-check** (`test-logic.sh` in repo, `bash test-logic.sh`, no
VM needed): topo order, `%README%` recording, unmet-dep, cycle detection, and
BLOCKED-BY-DEP propagation (`depends_on_failed`, including the transitive
- one-hop cascade), and the package-cache logic
- (`cache_decision`/`cache_path`/`cache_store`/`version_of`). The check builds a
+ one-hop cascade), the package-cache logic
+ (`cache_decision`/`cache_path`/`cache_store`/`version_of`), and the SBo
+ tree-lifecycle helpers `rsync_excludes` (one anchored `--exclude=/<dir>/` per
+ `SBO_PERSONAL_TREES` key, empty when no personal trees) and `collect_shadows`
+ (finds upstream dups of personal packages, excludes personal-tree paths
+ themselves, ignores packages with no upstream twin). The check builds a
fake SBo tree and sources the script with
config overridden AFTER sourcing (sourcing re-runs the CONFIG block, which
resets the vars to empty defaults and may source the external config, so test
@@ -149,6 +174,16 @@ recorded separately as a reminder flag, not a status.
target only (cached `imlib2` dep not linted), and left SUCCESS unaffected.
Pure host I/O against an external tool, no self-check stub (trivial, no branch
logic beyond the install check).
+- **NOT runnable-tested (repo lifecycle)**: `--setup-repo` and `--update` have
+ not been run against the real rsync source or real personal-tree git remotes
+ on hardware yet, so `rsync_tree`, `setup_repo`, `update_personal_trees`, the
+ `git clone`/`git pull` paths, and the interactive `shadow_scan` confirm/`rm -r`
+ step are unverified end to end. Only the pure logic underneath
+ (`rsync_excludes`, `collect_shadows`) is self-checked. The load-bearing safety
+ invariant, that `rsync_excludes` anchors each personal dir so `rsync --delete`
+ in `rsync_tree` can never wipe a personal clone, is covered by the
+ `rsync_excludes` self-check but has not been exercised against a live rsync
+ run with `--delete`.
## Known shortcuts (ponytail: comments in source)
diff --git a/README.md b/README.md
index b361e46..aa14781 100644
--- a/README.md
+++ b/README.md
@@ -77,6 +77,58 @@ The base is kept patched automatically on each run: when the mirror's
ChangeLog head differs from the recorded marker, new packages from
`patches/packages/` are applied to the local base via `upgradepkg`.
+## Repository setup and refresh
+
+Two config vars manage the SBo tree itself, on top of the read-in-place lookup
+described above:
+
+- **`SBO_RSYNC_URL`** - rsync source for the tree, the same source `sbopkg`
+ uses (e.g. `slackbuilds.org::slackbuilds/15.0`). This is the public
+ slackbuilds.org rsync tree, distinct from `LOCAL_MIRROR_15` (the NFS package
+ mirror). Leave empty and `--setup-repo` refuses to run; `--update` skips the
+ rsync and only pulls + shadows.
+- **`SBO_PERSONAL_TREES`** - a bash associative array, directory name (created
+ under `SBO_TREE_ROOTS[0]`) to git clone URL, for your own SlackBuilds that
+ live outside upstream (unpublished/personal/pentesting packages).
+
+### First-time setup: `--setup-repo`
+
+Builds `SBO_TREE_ROOTS[0]` from scratch. Runs as root, asks for confirmation,
+then REMOVES the existing tree root, rsyncs it fresh from `SBO_RSYNC_URL`,
+clones each `SBO_PERSONAL_TREES` subtree into it, then shadows (see below,
+with its own confirmation). Exits afterward, does not build. Hard-fails on an
+rsync or clone error.
+
+```sh
+sbo-batch-test --setup-repo
+```
+
+### Per-run refresh: `--update`
+
+Runs inline before a build, refreshing the tree without wiping personal work.
+rsyncs the tree with `--delete` to pull in upstream changes and removals
+(personal subtrees are excluded from the rsync, so they are never touched by
+`--delete`), which also brings back any upstream package that a previous
+shadow removed. Then git-pulls each personal subtree, then re-shadows.
+Fail-soft: a network or git error prints a warning and the run continues.
+
+```sh
+sbo-batch-test --update playwright-cli
+```
+
+### Shadowing
+
+Your personal packages win. When a package under a `SBO_PERSONAL_TREES` subtree
+shares a name with a package elsewhere in the upstream tree, the upstream copy
+is `rm -r`'d so lookup (first match wins per `SBO_TREE_ROOTS` order, but within
+one root the personal copy would otherwise collide) resolves to yours. Both
+`--setup-repo` and `--update` run this scan, and both ask for confirmation
+before removing anything.
+
+This self-heals: if you later drop a package from a personal repo, the next
+`--update` rsync brings the upstream copy back, since nothing shadows it
+anymore.
+
## Package cache
Set `PKG_CACHE` in your config to a local directory to cache built packages
@@ -136,6 +188,8 @@ sbo-batch-test --dry-run playwright-cli
| `--with-x` | Enable X passthrough (`xhost +local:hosts`). Headless by default. Security caveat: allows local non-network connections to your X server. |
| `-j`, `--jobs N` | Reserved. No-op stub today (builds are serial). |
| `--init-base` | First-time populate `SLACKWARE_BASE` from the mirror, then exit. Run once before the first build. Refuses to clobber an existing base. |
+| `--setup-repo` | First-time build of the SBo tree from `SBO_RSYNC_URL` and `SBO_PERSONAL_TREES`. See below. Exits, does not build. |
+| `--update` | Before building, refresh the SBo tree (rsync + git pull + shadow). See below. |
## Per-package status values