# Updates module A drawer tile and page that answer one question per row: what do I do next to bring this machine up to date. It replaces two places that showed the same facts less clearly: the conky updates card, a copy of `nvtable`'s table where installed-behind and repo-behind share a row and are told apart by colour, and the homepage ChangeLog widget, which shows the latest upstream -current entry rather than what this machine is missing. ## Sources and what they mean Four versions per tracked package: - **U, upstream**: `~/.config/nvchecker/new_ver.json`. - **R, recipe**: `VERSION=` in `.info` under the three repos of `~/Programming/GIT/slackbuilds-superrepo` (`sbo-slackbuilds`, `my-slackbuilds`, `Slackware-Pentesting-Suite`), falling back to the SlackBuilds.org clone at `/var/lib/sbopkg/SBo-git`. A recipe from that clone is tagged `SBo`: it is not the user's SlackBuild, and a bump of it happens through a slackrepo `.hint` file on the build VM, which is not visible from here. - **B, built**: `PACKAGES.TXT` of the user's binary repo, the directory named by the `danix` entry of `MIRRORPLUS` in `/etc/slackpkg/slackpkgplus.conf`. - **I, installed**: `/var/log/packages`, then appimage-updater's `installed.json`, then `flatpak list --app`, in that order, as `nvtable` does. nvtable's two alias tables (stanza name to installed name, stanza name to SlackBuild directory) are ported into the script as dicts. For Slackware itself, the mirror is the `file://` line active in `/etc/slackpkg/mirrors`. Its `PACKAGES.TXT` and `ChangeLog.txt` are compared against `/var/log/packages`. `/var/lib/slackpkg/ChangeLog.txt` is not used: `slackpkg update` replaces it without installing anything, so a diff against it reads "nothing pending" after an update that was never applied. ## Sections In page order. A package appears in exactly one section, the first that matches, so a row shows the next step and nothing after it. 1. **Slackware**, three groups, all from the mirror: - *Upgrade*: an installed package whose name is on the mirror with a different version or build. - *New*: of the ChangeLog's `Added.` and `Removed.` lines for the package, the newest says `Added.`; it is on the mirror and not installed. These are slackpkg's `install-new` semantics. Other lines (`Upgraded.`, `Rebuilt.`) are ignored, or a package added and later upgraded would never count as new. - *Removed*: of the same lines, the newest says `Removed.`, it is installed, and it is not on the mirror. The row carries the date of that ChangeLog entry. Installed packages whose build tag matches a pattern in `/etc/slackpkg/blacklist` (`_SBo`, `_danix`, `alien` and the rest) are skipped in all three, as slackpkg skips them; so are blacklisted names. 2. **Upgrade here**: B newer than I. The package is built and sitting in the repo. 3. **Awaiting build**: R is at or past U, B is older than U, and the package is installed. The SlackBuild, the user's or SBo's, is current and only needs building. 4. **Upstream newer**: U newer than the newest of R, B and I. The SlackBuild or its hint needs bumping, then a build. An `SBo` recipe that lags upstream lands here: the bump is a hint file on the build VM. Shown when the package is installed, or when the recipe is the user's (repo work either way). 5. **App updates**: I comes from AppImage or flatpak and is older than U. "Newer" and "older" are version order, never equality: an installed 2.1.278 against an SBo recipe of 2.1.267 is not an upgrade. A tracked package that is not installed and whose recipe is current is not shown. ## `updatesctl` `desktop/modules/updates/updatesctl`, `/usr/bin/python3`, standard library only. It prints one JSON document: { "checked": , "slackware": {"upgrade": [...], "new": [...], "removed": [...]}, "upgrade": [...], "build": [...], "upstream": [...], "apps": [...], "errors": {"mirror": "unreachable", ...} } Rows are `{name, repo, from, to}`; Slackware rows are `{name, from, to}`, `{name, version}` and `{name, date}`. `repo` is the label nvtable shows (`personal`, `my-sbo`, `pentesting`, `SBo`, `AppImage`, `flatpak`). **Version order** is a small `vercmp`: split on non-alphanumerics, compare numeric chunks as numbers and alphabetic chunks as strings, numbers before letters; when one runs out, the longer is newer unless its next chunk is alphabetic (a pre-release). It replaces nvtable's normalised equality. Its rule that an installed version extending upstream at a component boundary (a kernel suffix, a git hash) counts as equal needs no special case: the longer version orders as newer, which is never behind. **NFS reads** (`PACKAGES.TXT` of the repo and of the mirror, the mirror's `ChangeLog.txt`) go through `subprocess.run(["cat", path], timeout=5)`. The mount is `hard`, so a read during a NAS outage blocks; the timeout kills the child, the script carries on, and that source is reported in `errors` while the sections that do not need it still fill. **`--refresh`** runs `nvchecker -c ~/.config/nvchecker/nvchecker.toml` synchronously first, then prints as above. That config already names the GitHub keyfile. nvtake is not run: this model never reads `old_ver.json`. ## Module `desktop/modules/updates/UpdatesModule.qml`, name `updates`. - **Icon**: ``, `linux-slackware`, present in Inconsolata Nerd Font. - **Tile line**: `3 to install · 2 to build`, counting Slackware (all three groups) plus Upgrade here as "to install", and Awaiting build as "to build". `up to date` when both are zero. `checking…` before the first result. - **Active** (accent) when there is anything to install. - **Freshness**: when the tile is created, which is when the drawer opens, the module runs `updatesctl`. If `checked` is more than 30 minutes old it then runs `updatesctl --refresh` and the page shows `checking…` until it returns. Nothing runs while the drawer is closed, the same gating as KDE Connect. - **Page**: the five sections in order, each with a heading and a count, each hidden when empty. Rows read `name repo from → to`. A footer reads `checked 12 min ago` and holds a refresh button that runs `--refresh`. An entry in `errors` shows as one dim line under the section it empties, e.g. `mirror unreachable`. Read-only: no install or build buttons. ## Retiring conky's card Once the user trusts the tile, `bin/updates-sample.sh` and `widgets/updates.lua` are deleted from `conky-theme-udt`, with the card's slot, as a separate commit in that repo. `nvtable` stays in `danix-nvchecker` for the shell; this repo does not depend on it. ## Testing `desktop/modules/updates/test_updatesctl.py`, run with `/usr/bin/python3`: - `vercmp`: 1.14.10 > 1.14.9, 2.1.278 > 2.1.267, 2026_10_02 > 2026_09_12, a kernel suffix or git hash never behind its base. - Section assignment on fixture directories built in a temp dir, one row per case: built and newer goes to Upgrade here, bumped and unbuilt to Awaiting build, unbumped to Upstream newer, an SBo recipe behind upstream to Upstream newer, an installed version ahead of SBo to nothing, an AppImage behind to App updates. - Slackware: a mirror with one changed build, one `Added.` package and one `Removed.` package, plus a blacklisted `_SBo` build that must not appear. - An NFS path that times out: a fifo with no writer, read with a short timeout, must report `unreachable` without hanging the test. The tests must be shown to fail on a broken input before they are trusted. ## Not in scope Installing, building, or bumping from the page. Showing upstream lag of the NFS mirror itself. Reading slackrepo hint files from the build VM.