# 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*: the ChangeLog's newest line for the package says `Added.`, it is on the mirror, and it is not installed. These are slackpkg's `install-new` semantics. - *Removed*: the ChangeLog's newest line for the package 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 the user's (not `SBo`), R equals U, and B is older than U. The SlackBuild is bumped and only needs building. 4. **Upstream newer**: U newer than both R and B. The SlackBuild or its hint needs bumping, then a build. `SBo` rows land here until the build appears in B. 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. It replaces nvtable's normalised equality, including its rule that an installed version extending upstream at a component boundary (a kernel suffix, a git hash) counts as equal; that rule is kept as a prefix check before ordering. **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 equal to 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.