diff options
| author | Danilo M. <danix@danix.xyz> | 2026-10-20 10:44:34 +0200 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-10-20 10:44:34 +0200 |
| commit | 8ad8b0bafe212b47f4a2365669cbc0a2153d4243 (patch) | |
| tree | 2a1f95301fda91b6c4beef7b9bd5f8bd925a8e88 /docs | |
| parent | 7deece04759c0efd2cca73d4af96479b343c2ae4 (diff) | |
| download | sb-builder-8ad8b0bafe212b47f4a2365669cbc0a2153d4243.tar.gz sb-builder-8ad8b0bafe212b47f4a2365669cbc0a2153d4243.zip | |
Add phase 4 design: hints managed by the helper
mkhint's hint logic moves into sbb-remote and the upstream check runs
nvchecker on the desktop with a config tracked in this repo.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/superpowers/specs/2026-10-19-sb-builder-phase1-design.md | 2 | ||||
| -rw-r--r-- | docs/superpowers/specs/2026-10-20-sb-builder-phase4-design.md | 238 |
2 files changed, 240 insertions, 0 deletions
diff --git a/docs/superpowers/specs/2026-10-19-sb-builder-phase1-design.md b/docs/superpowers/specs/2026-10-19-sb-builder-phase1-design.md index 36b539b..3ec3fc0 100644 --- a/docs/superpowers/specs/2026-10-19-sb-builder-phase1-design.md +++ b/docs/superpowers/specs/2026-10-19-sb-builder-phase1-design.md @@ -30,6 +30,8 @@ Each phase gets its own spec, plan and implementation cycle. any hint slackrepo searches becomes `DOWNLOAD="no"` (an existing `DOWNLOAD` line is replaced, since `DOWNLOAD="no"` overrides it anyway), backed up to `.bak` first, idempotent. As of 2026-10-19 no hint carries the line. + Superseded by `2026-10-20-sb-builder-phase4-design.md`: the hint logic + moves into the helper instead of extending mkhint. 5. **Orphans**: SBo orphan discovery (`EMAIL="NOEMAIL"` in `.info`, the `sbo-orphans` logic from slackbuilds-superrepo), including orphaned deps in REQUIRES. Needs an SBo-stable tree, which is not on the VM today. diff --git a/docs/superpowers/specs/2026-10-20-sb-builder-phase4-design.md b/docs/superpowers/specs/2026-10-20-sb-builder-phase4-design.md new file mode 100644 index 0000000..df360eb --- /dev/null +++ b/docs/superpowers/specs/2026-10-20-sb-builder-phase4-design.md @@ -0,0 +1,238 @@ +# sb-builder phase 4: hints + +Date: 2026-10-20 +Status: draft +Builds on: `2026-10-19-sb-builder-phase1-design.md` (helper, job model, GUI shell), +`2026-10-19-sb-builder-phase2-design.md` (inventory, hint view, slackrepo jobs) + +## Goal + +Manage slackrepo hint files from sb-builder: check upstream versions, update +version hints, create and delete hints, sweep `DELREQUIRES` for -current +phantom deps, and see a diff of every change with a way to revert it. + +Direction set by the user: the repo is run from the desktop, the VM shell is +for upgrading Slackware only. The VM-side tools were built for a terminal; a +tool may lose its in-VM usability if that makes sb-builder simpler. So the +hint logic of mkhint moves into `sbb-remote` (Python, JSON answers) and the +upstream check moves to the desktop. mkhint is not extended. + +## Facts this design rests on + +Verified on the VM, in the mkhint source (`~/Programming/GIT/mkhintfile/mkhint`, +1.4.0, 2291 lines) and in slackrepo (`../GITHUB/slackrepo`): + +- The VM has 607 hints, all in `hintdir`, none in subdirectories and none in + the SBo tree. 594 carry `DELREQUIRES` (from `mkhint -F`), 13 carry + `VERSION` + `ARCH` + `DOWNLOAD` + `MD5SUM`, one carries `OPTIONS`. No hint + carries `NODOWNLOAD` or a `DOWNLOAD_x86_64`/`MD5SUM_x86_64` line. +- slackrepo reads `DOWNLOAD="no"` as "no download" and ignores `NODOWNLOAD`. + `DOWNLOAD_$ARCH` replaces `DOWNLOAD` when set + (`libexec/functions.d/parsefunctions.sh:457`), so `DOWNLOAD="no"` next to a + `DOWNLOAD_x86_64` line has no effect. +- mkhint's version update: back up to `.bak`, replace the old version by the + new one everywhere in the file, also the `_` -> `-` form when either version + contains `_`, also the dotless form of a dotted version inside URLs as a + whole number (`_swap_dotless_url_version`), then for `DOWNLOAD`/`MD5SUM` and + `DOWNLOAD_x86_64`/`MD5SUM_x86_64`: download the first URL and recompute its + md5, keep the md5 of continuation URLs unless the user typed a new URL. + `UNSUPPORTED`/`UNTESTED` values are skipped. +- mkhint's new hint from `.info`: copy the `.info`, drop `PRGNAM`, `HOMEPAGE`, + `MAINTAINER`, `EMAIL`, comment out `REQUIRES`, set `ARCH="x86_64"`, append + `DELREQUIRES` for phantom deps in `REQUIRES`, then apply a version as above + when one is given. +- mkhint's `-F`: for every `.info` in the repo whose `REQUIRES` contains a + phantom dep, merge those deps into the hint's `DELREQUIRES` (union, first + seen order, `.bak` only when something changes, minimal hint created when + absent). +- The VM's nvchecker config has 65 stanzas named after the packages, plus a + `[__config__]` with oldver, newver and keyfile. nvchecker v2.22 is + installed on the desktop, with a GitHub token in + `~/.config/nvchecker/keys.toml`. Its newver file is + `{"version": 2, "data": {"<name>": {"version": "..."}, ...}}`. +- The phantom deps list on the VM (`/root/.config/mkhint/phantom-deps`) has + 18 entries. +- Two packages use bundled-dep manifests: neovim (url mode) and openvino + (sha mode, GitHub submodules). That code is about 470 lines of mkhint. + +## Scope + +In: upstream check, version update, new hint, delete hint, fix-current, +`--no-dl` as `DOWNLOAD="no"`, diff and revert. + +Out, for good (the Hints screen covers them): mkhint `--list`, `--versions`, +`--review`, `--strip-version`, `--info`, `--clean`. + +Out, later: bundled-dep reconcile for neovim and openvino (phase 4b, which +then removes mkhint and nvchecker from the VM), generating nvchecker stanzas +for new packages (add them to `nvchecker.toml` by hand), free text hint +editing, migration of `NODOWNLOAD=yes` lines (none exist). + +## Part 1: upstream check, on the desktop + +- `nvchecker.toml` in the repo root: the VM's 65 stanzas, without + `[__config__]`. Stanza name = package name. Git-tracked, edited by hand. +- `sb_builder/upstream.py` runs nvchecker through `QProcess` (as `remote.py` + runs `virsh`) with a fixed argv: `nvchecker -c <tmp>/nvchecker.toml`. The + temp dir holds a generated config: a `[__config__]` with `keyfile` (from + the GUI config) and `newver = "<tmp>/new.json"`, followed by the repo + file's text. No oldver, no `nvtake`: the comparison is against the hints. +- Result: `{pkg: version}` from the newver file. Failure: the exit status and + stderr, shown as a `nvchecker error` state. +- A package is outdated when its upstream version differs from the hint + `VERSION`, or from the `.info` `VERSION` when the hint has none. Versions + are compared as strings; no ordering is attempted. + +GUI config gains `nvchecker_keyfile`, default +`~/.config/nvchecker/keys.toml` (expanded). A missing keyfile is not an +error: nvchecker runs without a token. + +## Part 2: helper (`sbb-remote` 0.5.0) + +### Config + +New key `phantom_deps`, list of strings, default `[]`. The VM config gets +the 18 entries at deploy. `remote/config.example.toml` shows the key. + +### Arguments + +- package: `PKGNAME` and present in the repo (as for slackrepo jobs). +- version: `^[A-Za-z0-9._+-]+$`, at most 64 characters. +- hint path: always `<hintdir>/<pkg>.hint`. If `find_hint` returns a + different file for the package (a hint earlier in slackrepo's search + order), every hint command refuses: "hint lives at <path>, not managed". +- packages with a bundled-dep manifest are named in config key + `manifest_packages`, default `["neovim", "openvino"]`. `hint-update` and + `hint-new` with a version refuse them: "bundled deps: use mkhint until + phase 4b". + +### Job kinds + +- `hint-update <pkg>=<ver>... [--no-dl]`: per package, in order: back up the + hint to `.bak`, apply the version (below), write atomically. A failure + restores the hint from the `.bak` it just wrote, logs `<pkg>: failed: <why>` + and continues with the next package. The last log line is + `SBB-RESULT {"ok": [...], "failed": [...]}`. Exit status 1 when any + package failed. +- `hint-new <pkg> [<ver>] [--no-dl]`: refuses when the hint exists. Builds + the hint from the `.info` as mkhint does, phantom deps from + `phantom_deps`, then applies the version when given. No `.bak` (nothing to + back up); revert means delete. +- `fix-current`: mkhint's `-F` with `phantom_deps`. Logs one line per + changed hint, then `SBB-RESULT {"ok": [...], "failed": []}`. + +These jobs never sign, so they do not check the signing key. + +### Applying a version + +1. Old version = hint `VERSION`, else `.info` `VERSION`. +2. Replace old by new everywhere in the file. When either contains `_`, also + the `-` forms. When old contains `.`, also its dotless form inside URLs, + as a whole number (no digit before or after), so md5 hex is untouched. +3. Without `--no-dl`: for `DOWNLOAD`/`MD5SUM` and + `DOWNLOAD_x86_64`/`MD5SUM_x86_64`, split the values on whitespace (hint + values may continue over lines with `\`). Skip a pair whose value is empty, + `UNSUPPORTED` or `UNTESTED`. Download the first URL with `urllib` + (timeout 60 s, streamed into `hashlib.md5`, nothing kept on disk) and + replace its md5; keep the md5s of the other URLs. Write values back one + URL per line with ` \` continuation, as mkhint does. +4. With `--no-dl`: nothing is downloaded. Every `DOWNLOAD*` and `MD5SUM*` + assignment is removed (whole multi-line values) and `DOWNLOAD="no"` is + written, because `DOWNLOAD_$ARCH` would override it. + +Hint text is edited as text, not regenerated, so comments, order and other +keys stay as they are. Assignments are located with the rules the helper's +`parse_assignments` already uses (`KEY="..."` at line start, values may span +lines inside the quotes). + +### Commands (answer at once, not jobs) + +- `hint-diff <pkg>`: `{"bak": text|null, "current": text|null}`. Both null + is an error ("no backup"). +- `hint-revert <pkg>`: when a `.bak` exists, move it over the hint (also + recreating a deleted hint); when there is no `.bak` and the hint exists, + delete the hint (reverting a `hint-new`). Returns `{"ok": true}`. +- `hint-delete <pkg>`: move the hint to `.bak`. Errors when there is no hint. + +`.bak` is one level deep and overwritten by each change, the mkhint +convention. + +### Version + +`VERSION` 0.5.0 in `remote/sbb-remote` and `sb_builder/__init__.py`. + +## Part 3: GUI + +### Hints screen (`sb_builder/hints_tab.py`, ribbon entry and `Open > Hints`) + +- Rows: every package with a stanza in `nvchecker.toml` or a hint in + `hintdir`. Columns: checkbox, package, hint version, `.info` version, + upstream, state. Versions come from the existing `inventory` call. +- States: `outdated`, `current`, `no stanza`, `not checked`, + `nvchecker error` (stderr in the tooltip). Filter chips per state and a + text filter on the name, as in the Packages tab. +- Buttons: + - **Check upstream**: runs Part 1 over the whole file, fills the upstream + column, checks the outdated rows. Results live for the session. + - **Update selected**: starts `hint-update pkg=ver ...` for the checked + rows that have an upstream version; a **No download** checkbox adds + `--no-dl`. + - **Fix current**: starts `fix-current`. + - **Delete hint**: confirm dialog, then `hint-delete` for the current row. +- Jobs go through the Jobs tab like every other job. + +### After a hint job + +When a `hint-update`, `hint-new` or `fix-current` job ends, the GUI reads +its `SBB-RESULT` line and opens a dialog with one entry per changed package: +a unified diff (`difflib`) of `hint-diff`, and a **Revert** button per +package. Failed packages are listed with their reason. The dialog ends with +**Build these**, which starts the usual slackrepo preview for the changed +packages (`update` when built, `build` otherwise, as the Packages tab +decides), and **Close**. After Revert or Delete the inventory is reloaded. + +For `fix-current` the dialog lists the packages without opening every diff +(it can touch hundreds); clicking one shows its diff. + +### Packages detail pane + +- No hint: **New hint**, with an optional version field and a **No + download** checkbox, starts `hint-new`. +- Hint present: **Open in Hints** selects the package in the Hints screen. + +## Error handling + +- Bad arguments, unmanaged hint paths and manifest packages are refused by + the helper before a job starts; the GUI shows the message. +- A download failure (HTTP status, timeout, DNS) fails that package only and + leaves its hint as it was. +- Writes are atomic (temp file in the same directory, `os.replace`). +- nvchecker missing or failing on the desktop affects only the upstream + column; the rest of the screen works. +- A job without an `SBB-RESULT` line (killed, lost) opens no dialog; the + log shows what happened and `hint-diff` still works per package. + +## Testing + +- `test_remote.py`: an `http.server` thread serves fixture files for md5. + Version swap forms (plain, `_`/`-`, dotless in URL only, md5 hex not + touched), multi-line `DOWNLOAD`/`MD5SUM` with continuation md5s kept, + `UNSUPPORTED` skipped, `--no-dl` removing `DOWNLOAD_x86_64` and writing + `DOWNLOAD="no"`, a download failure restoring the hint while the next + package still updates, `SBB-RESULT` contents, `hint-new` from `.info` + with phantom deps, `fix-current` merge and idempotence (second run + changes nothing and writes no `.bak`), new -> revert, update -> diff -> + revert, delete -> revert, manifest package refusal, unmanaged hint path + refusal, bad version and package rejection. +- `test_upstream.py`: generated config text, newver parsing from a fixture, + outdated comparison (hint version, `.info` fallback). No network. +- `test_gui.py`: Hints screen with a fake remote and injected upstream + results (states, checked rows, Update selected argv), diff dialog Revert + call. + +## Deploy (asks first) + +1. `./install.sh --remote` with helper 0.5.0. +2. Add `phantom_deps` (the VM's 18 entries) to `/etc/sb-builder/config.toml`. +3. mkhint, nvchecker and `/root/.config/{mkhint,nvchecker}` stay on the VM + until phase 4b. |
