aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CLAUDE.md49
-rw-r--r--README.md19
-rw-r--r--config.example35
-rwxr-xr-xsbo-batch-test117
4 files changed, 163 insertions, 57 deletions
diff --git a/CLAUDE.md b/CLAUDE.md
index d6ee7e9..1254ab1 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -30,8 +30,11 @@ docs in `README.md`.
local SBo tree is the single source of truth (contains unpublished
personal/pentesting packages). Settled, not open for revisiting.
- **overlay lowerdir must be LOCAL.** `SLACKWARE_BASE` is a local fs path.
- `LOCAL_MIRROR_15` is NFS and is a package SOURCE only. overlayfs over NFS
- lowerdir is fragile. The script guards against pointing base under the mirror.
+ `LOCAL_MIRROR_15` is the NFS mountpoint, a package SOURCE only (content read
+ via the derived `MIRROR_TREE`). overlayfs over NFS lowerdir is fragile. The
+ script guards against pointing base under the mirror. The mirror fstab entry
+ is `noauto`; the script checks `mountpoint -q` and auto-mounts (`mount
+ $LOCAL_MIRROR_15`) if absent, left mounted after the run.
- **Do not wrap/drive slackrepo.** Separate pipeline, keep independent.
- **Shares host kernel.** No kernel-module testing claims.
- Runs as root only (overlay + chroot).
@@ -42,18 +45,30 @@ docs in `README.md`.
Top-to-bottom layout:
-1. **CONFIG block** - `SLACKWARE_BASE`, `LOCAL_MIRROR_15`, `SBO_TREE_ROOTS[]`,
- `CHROOT_LOCATION`, `LOG_ROOT`, `VERSION`. Currently placeholder paths (we are
- not in the VM, no real values yet). User fills these in.
+1. **CONFIG block** - empty defaults plus a `source` of the external config
+ file. Real values live OUTSIDE the script in `$SBO_BATCH_CONFIG` (default
+ `~/.config/sbo-batch-tester/config`, i.e. `/root/.config/...` since it runs
+ as root); `config.example` in the repo is the template. The block sets empty
+ defaults (`SLACKWARE_BASE LOCAL_MIRROR_15 SBO_TREE_ROOTS`) plus
+ `CHROOT_LOCATION=/tmp LOG_ROOT 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
+ `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"`
+ (holds ChangeLog.txt, slackware64/, patches/). All mirror content reads use
+ `MIRROR_TREE`; the mountpoint check, auto-mount, and the under-mirror guard
+ use `LOCAL_MIRROR_15`.
2. **Globals / flags** - `USE_COLOR DRY_RUN WITH_X JOBS`, status maps
(`ST_STATUS ST_REASON ST_TIME ST_README`), `ACTIVE_MOUNTS[]`.
3. **usage / init_color / parse_args / validate_env** - fail-fast startup
checks with copy-pasteable hints.
4. **init_base** - `--init-base` mode only. First-time populate: `installpkg
--root` the full `slackware64/*/*.t?z` set into `SLACKWARE_BASE`, seed the
- `last-base-update` marker, exit. Runs its own checks (root, NFS reachable,
- not under mirror) since the base does not exist yet; refuses to clobber a
- populated base. Wired in `main` before `validate_env`, exits 0.
+ `last-base-update` marker, exit. Runs its own checks (root, mirror mounted
+ /auto-mount, ChangeLog.txt present, not under mirror) since the base does not
+ exist yet; refuses to clobber a populated base. Wired in `main` before
+ `validate_env`, exits 0. installpkg/upgradepkg run with `--terse`.
**update_base** - patches local base from mirror's `patches/packages/` when
ChangeLog head differs (reused from reference script).
5. **SBo tree lookup** - `find_slackbuild_dir`, `category_of`, `pkg_key`,
@@ -93,13 +108,21 @@ not a status.
VM needed): topo order, `%README%` recording, unmet-dep, cycle detection, and
BLOCKED-BY-DEP propagation (`depends_on_failed`, including the transitive
one-hop cascade). The check builds a fake SBo tree and sources the script with
- config overridden AFTER sourcing (sourcing re-runs the CONFIG block, so test
- vars must be set after the `source`). Gotchas baked in: do not name the dead
+ 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
+ vars must be set after the `source`). The test runs as a normal user, so
+ `~/.config/sbo-batch-tester/config` usually does not exist and is not sourced;
+ even if it did, the post-source overrides win. Gotchas baked in: do not name the dead
list `failed` (collides with `depends_on_failed`'s `local -n failed`), and
`ok`/`bad` must `return 0` (`((x++))` returns nonzero when x was 0).
-- **NOT runnable-tested** (needs the VM): overlay mounts, chroot build flow,
- base patching, `--init-base` populate, installpkg. Logic mirrors the
- reference script / the prior manual populate hint.
+- **Verified on the build system**: `--init-base` populate ran clean against
+ the real mirror (mountpoint check, auto-mount of the noauto NFS entry,
+ `MIRROR_TREE` derivation, external config sourcing, full installpkg --terse
+ set). The external-config split (`require_config`, missing/incomplete errors)
+ was checked in isolation too.
+- **NOT runnable-tested** (needs a real build run): overlay mounts, chroot
+ build flow, base patching (update_base), per-package installpkg. Logic mirrors
+ the reference script.
## Known shortcuts (ponytail: comments in source)
diff --git a/README.md b/README.md
index b29542c..6a15ff0 100644
--- a/README.md
+++ b/README.md
@@ -26,15 +26,22 @@ current-vs-15.0 drift bites.
## Prerequisites
-You need three things in place, all configured in the CONFIG block at the top
-of `sbo-batch-test`:
+Configuration lives in an external file, not in the script. Copy `config.example`
+to `~/.config/sbo-batch-tester/config` and edit it (the tool runs as root, so
+that is `/root/.config/sbo-batch-tester/config`). Override the path with the
+`SBO_BATCH_CONFIG` environment variable. You need three things set in it:
1. **`SLACKWARE_BASE`** - a LOCAL (non-NFS) full Slackware 15.0 install tree.
This is the overlay lowerdir. It MUST be local (ext4/xfs). overlayfs over an
NFS lowerdir is fragile and a known source of intermittent failures.
-2. **`LOCAL_MIRROR_15`** - the NFS-mounted Slackware 15.0 mirror. Used only as a
- package SOURCE to populate and patch `SLACKWARE_BASE`. Read-only is fine.
+2. **`LOCAL_MIRROR_15`** - the NFS mountpoint for the Slackware 15.0 mirror.
+ Point it at the mount root itself; the actual tree (ChangeLog.txt,
+ slackware64/, patches/) is found one level down at
+ `$LOCAL_MIRROR_15/slackware64-$VERSION`. Used only as a package SOURCE to
+ populate and patch `SLACKWARE_BASE`. Read-only is fine. If the fstab entry is
+ `noauto`, the script auto-mounts it (`mount $LOCAL_MIRROR_15`) when absent and
+ leaves it mounted after the run.
3. **`SBO_TREE_ROOTS`** - one or more LOCAL SBo tree roots, resolved in order
(first match wins). Standard SBo layout
@@ -49,8 +56,8 @@ Populate from the NFS mirror with the FULL package set, not a minimal install.
A minimal base causes false "missing dependency" results that would not happen
on a normal user's full Slackware install.
-Set `SLACKWARE_BASE` and `LOCAL_MIRROR_15` in the script's CONFIG block, then
-run once as root:
+Set `SLACKWARE_BASE` and `LOCAL_MIRROR_15` in your config file, then run once
+as root:
```sh
sbo-batch-test --init-base
diff --git a/config.example b/config.example
new file mode 100644
index 0000000..88cc264
--- /dev/null
+++ b/config.example
@@ -0,0 +1,35 @@
+# sbo-batch-test config. Sourced by the script as bash.
+#
+# Copy to ~/.config/sbo-batch-tester/config and edit. The script runs as root,
+# so that is /root/.config/sbo-batch-tester/config. Override the path with the
+# $SBO_BATCH_CONFIG environment variable.
+
+# LOCAL (non-NFS) read-only 15.0 base install tree. This is the overlay
+# lowerdir. MUST be a local filesystem (ext4/xfs). NEVER point this at the NFS
+# mirror: overlayfs over NFS lowerdir is fragile and fails intermittently.
+# Populate it once with: sbo-batch-test --init-base
+SLACKWARE_BASE="/sbo-base/15.0"
+
+# NFS mountpoint for the 15.0 mirror. Point at the mount root itself; the script
+# checks it with mountpoint -q and auto-mounts it (mount $LOCAL_MIRROR_15) if the
+# fstab entry is noauto. The actual Slackware tree (ChangeLog.txt, slackware64/,
+# patches/) is found one level down at $LOCAL_MIRROR_15/slackware64-$VERSION.
+# Package SOURCE only. Read-only is fine. Never the overlay lowerdir.
+LOCAL_MIRROR_15="/mnt/mirror-15.0"
+
+# One or more LOCAL SBo tree roots, resolved in order (first match wins).
+# Standard SBo layout: <root>/<category>/<prog>/{prog.SlackBuild,prog.info,...}.
+# Read in place, never copied or synced.
+SBO_TREE_ROOTS=(
+ "/var/lib/sbopkg/SBo-danix"
+)
+
+# Where overlays are created. LOCAL, needs space. One disposable overlay per
+# target lives here.
+CHROOT_LOCATION="/tmp"
+
+# Where persistent logs are written (outside the overlay, survives teardown).
+LOG_ROOT="/var/log/sbo-batch-test"
+
+# Slackware version, used for the mirror ChangeLog / patches path.
+VERSION="15.0"
diff --git a/sbo-batch-test b/sbo-batch-test
index 4683eb3..0c39ed2 100755
--- a/sbo-batch-test
+++ b/sbo-batch-test
@@ -19,35 +19,39 @@
# No em dashes in prose by author convention.
# =============================================================================
-# CONFIG (edit these for your VM)
+# CONFIG
# =============================================================================
-
-# LOCAL (non-NFS) read-only 15.0 base install tree. This is the overlay
-# lowerdir. MUST be a local filesystem (ext4/xfs). NEVER point this at the NFS
-# mirror: overlayfs over NFS lowerdir is fragile and fails intermittently.
-SLACKWARE_BASE="/sbo-base/15.0"
-
-# NFS-mounted 15.0 mirror. Package SOURCE only, used to populate/patch
-# SLACKWARE_BASE. Read-only is fine. Never used as the overlay lowerdir.
-LOCAL_MIRROR_15="/mnt/nfs/slackware64-15.0"
-
-# One or more LOCAL SBo tree roots, resolved in order (first match wins).
-# Standard SBo layout: <root>/<category>/<prog>/{prog.SlackBuild,prog.info,...}.
-# Read in place, never copied or synced.
-SBO_TREE_ROOTS=(
- "/home/danix/SBo-danix"
- "/home/danix/slackbuilds-15.0"
-)
-
-# Where overlays are created. LOCAL. One disposable overlay per target lives here.
+#
+# Do NOT edit values here. Real config lives in an external file, sourced below.
+# Default path: ~/.config/sbo-batch-tester/config (override with $SBO_BATCH_CONFIG).
+# Copy config.example from the repo and edit it. Runs as root, so ~ is root's
+# home (/root/.config/sbo-batch-tester/config).
+#
+# Config file sets these (see config.example for docs on each):
+# SLACKWARE_BASE LOCAL_MIRROR_15 SBO_TREE_ROOTS CHROOT_LOCATION LOG_ROOT VERSION
+
+# Defaults. The config file overrides any it sets. These are placeholders, a run
+# fails fast in validate_env / init_base if the config has not set real paths.
+SLACKWARE_BASE=""
+LOCAL_MIRROR_15=""
+SBO_TREE_ROOTS=()
CHROOT_LOCATION="/tmp"
-
-# Where persistent logs are written (outside the overlay, survives teardown).
LOG_ROOT="/var/log/sbo-batch-test"
-
-# Slackware version, used for the mirror ChangeLog / patches path.
VERSION="15.0"
+# Source the external config if present. Not an error here if missing (keeps the
+# script sourceable by test-logic.sh); validate_env / init_base report it.
+SBO_BATCH_CONFIG="${SBO_BATCH_CONFIG:-$HOME/.config/sbo-batch-tester/config}"
+if [[ -f "$SBO_BATCH_CONFIG" ]]; then
+ # shellcheck disable=SC1090
+ source "$SBO_BATCH_CONFIG"
+fi
+
+# Derived: the actual Slackware tree under the mirror mountpoint. Holds
+# ChangeLog.txt, slackware64/, and patches/. Set after sourcing so it picks up
+# the config's LOCAL_MIRROR_15 and VERSION.
+MIRROR_TREE="$LOCAL_MIRROR_15/slackware64-$VERSION"
+
# =============================================================================
# END CONFIG
# =============================================================================
@@ -151,11 +155,33 @@ parse_args() {
# =============================================================================
# startup validation (fail fast, copy-pasteable hints)
# =============================================================================
+
+# Shared: the config file must exist and set the required paths. Called by both
+# validate_env and init_base.
+require_config() {
+ if [[ ! -f "$SBO_BATCH_CONFIG" ]]; then
+ cat >&2 <<EOF
+No config file: $SBO_BATCH_CONFIG
+Copy the example and edit it (paths run as root, so this is /root/.config/...):
+
+ mkdir -p "\$(dirname "$SBO_BATCH_CONFIG")"
+ cp config.example "$SBO_BATCH_CONFIG"
+ \${EDITOR:-vi} "$SBO_BATCH_CONFIG"
+EOF
+ exit 1
+ fi
+ if [[ -z "$SLACKWARE_BASE" || -z "$LOCAL_MIRROR_15" || ${#SBO_TREE_ROOTS[@]} -eq 0 ]]; then
+ echo "Config $SBO_BATCH_CONFIG is missing SLACKWARE_BASE, LOCAL_MIRROR_15, or SBO_TREE_ROOTS." >&2
+ exit 1
+ fi
+}
+
validate_env() {
if [[ $EUID -ne 0 ]]; then
echo "This tool must run as root (overlay + chroot)." >&2
exit 1
fi
+ require_config
# SLACKWARE_BASE: local, looks like a real Slackware install.
if [[ ! -d "$SLACKWARE_BASE" || ! -d "$SLACKWARE_BASE/var/log/packages" ]]; then
@@ -176,10 +202,18 @@ EOF
exit 1 ;;
esac
- # LOCAL_MIRROR_15: NFS, must be mounted/reachable.
- if [[ ! -d "$LOCAL_MIRROR_15" || ! -f "$LOCAL_MIRROR_15/ChangeLog.txt" ]]; then
- echo "LOCAL_MIRROR_15 not reachable (NFS mount absent?): $LOCAL_MIRROR_15" >&2
- echo "Expected a Slackware 15.0 mirror with ChangeLog.txt at its root." >&2
+ # LOCAL_MIRROR_15: NFS, fstab entry is noauto. Auto-mount if not mounted
+ # (needs the fstab entry for bare `mount <path>`). Left mounted after the run.
+ if ! mountpoint -q "$LOCAL_MIRROR_15"; then
+ echo "LOCAL_MIRROR_15 not mounted, attempting: mount $LOCAL_MIRROR_15" >&2
+ if ! mount "$LOCAL_MIRROR_15"; then
+ echo "Could not mount $LOCAL_MIRROR_15 (no fstab entry? mount it manually)." >&2
+ exit 1
+ fi
+ fi
+ if [[ ! -f "$MIRROR_TREE/ChangeLog.txt" ]]; then
+ echo "Mirror mounted but no ChangeLog.txt under: $MIRROR_TREE" >&2
+ echo "Expected the Slackware 15.0 tree at \$LOCAL_MIRROR_15/slackware64-\$VERSION." >&2
exit 1
fi
@@ -209,12 +243,19 @@ init_base() {
if [[ $EUID -ne 0 ]]; then
echo "--init-base must run as root (installpkg --root)." >&2; exit 1
fi
+ require_config
case "$SLACKWARE_BASE" in
"$LOCAL_MIRROR_15"*)
echo "SLACKWARE_BASE must NOT live under LOCAL_MIRROR_15 (NFS)." >&2; exit 1 ;;
esac
- if [[ ! -d "$LOCAL_MIRROR_15" || ! -f "$LOCAL_MIRROR_15/ChangeLog.txt" ]]; then
- echo "LOCAL_MIRROR_15 not reachable (NFS mount absent?): $LOCAL_MIRROR_15" >&2; exit 1
+ if ! mountpoint -q "$LOCAL_MIRROR_15"; then
+ echo "LOCAL_MIRROR_15 not mounted, attempting: mount $LOCAL_MIRROR_15" >&2
+ if ! mount "$LOCAL_MIRROR_15"; then
+ echo "Could not mount $LOCAL_MIRROR_15 (no fstab entry? mount it manually)." >&2; exit 1
+ fi
+ fi
+ if [[ ! -f "$MIRROR_TREE/ChangeLog.txt" ]]; then
+ echo "Mirror mounted but no ChangeLog.txt under: $MIRROR_TREE" >&2; exit 1
fi
if [[ -d "$SLACKWARE_BASE/var/log/packages" ]]; then
echo "Base already populated: $SLACKWARE_BASE" >&2
@@ -224,34 +265,34 @@ init_base() {
echo "Populating base from mirror into: $SLACKWARE_BASE"
mkdir -p "$SLACKWARE_BASE"
local p n=0
- for p in "$LOCAL_MIRROR_15"/slackware64/*/*.t?z; do
+ for p in "$MIRROR_TREE"/slackware64/*/*.t?z; do
[[ -e "$p" ]] || continue
- installpkg --root "$SLACKWARE_BASE" "$p"
+ installpkg --terse --root "$SLACKWARE_BASE" "$p"
((n++)); ((n % 50 == 0)) && echo " ...$n packages"
done
if [[ $n -eq 0 ]]; then
- echo "No packages found under $LOCAL_MIRROR_15/slackware64/*/. Wrong mirror layout?" >&2
+ echo "No packages found under $MIRROR_TREE/slackware64/*/. Wrong mirror layout?" >&2
exit 1
fi
# Seed the update marker so the next run does not re-patch needlessly.
- head -n1 "$LOCAL_MIRROR_15/ChangeLog.txt" > "$SLACKWARE_BASE/last-base-update"
+ head -n1 "$MIRROR_TREE/ChangeLog.txt" > "$SLACKWARE_BASE/last-base-update"
echo "Base populated: $n packages installed into $SLACKWARE_BASE"
}
update_base() {
local marker="$SLACKWARE_BASE/last-base-update"
touch "$marker"
- local head_now; head_now="$(head -n1 "$LOCAL_MIRROR_15/ChangeLog.txt")"
+ local head_now; head_now="$(head -n1 "$MIRROR_TREE/ChangeLog.txt")"
if [[ "$head_now" == "$(cat "$marker")" ]]; then
echo "Base is up-to-date with the mirror."
return
fi
echo "Patching base from mirror..."
local p
- for p in "$LOCAL_MIRROR_15"/patches/packages/*.t?z; do
+ for p in "$MIRROR_TREE"/patches/packages/*.t?z; do
[[ -e "$p" ]] || continue
if [[ ! -e "$SLACKWARE_BASE/var/lib/pkgtools/packages/$(basename "${p%.*}")" ]]; then
- ROOT="$SLACKWARE_BASE" upgradepkg --install-new "$p"
+ ROOT="$SLACKWARE_BASE" upgradepkg --terse --install-new "$p"
fi
done
echo "$head_now" > "$marker"
@@ -505,7 +546,7 @@ if [ -z "\$pkg" ]; then
echo "No package produced in \$out"
echo BUILD-FAILED > "$workroot/$prog.status"; exit 1
fi
-if ! installpkg "\$pkg"; then
+if ! installpkg --terse "\$pkg"; then
echo INSTALL-FAILED > "$workroot/$prog.status"; exit 1
fi
# Log the installed file list (from the package db) so the overlay is disposable.