diff options
| author | Danilo M. <danix@danix.xyz> | 2026-10-21 11:40:59 +0200 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-10-21 11:40:59 +0200 |
| commit | f8e9991c92618967e89a5ee4bf84de1556b6af5f (patch) | |
| tree | 6cd2048b7ff7949d935c350d48bddc0de12fd810 | |
| parent | 766ce6ff1ea584dfe980a5e0b29251768c4c0726 (diff) | |
| download | sb-builder-f8e9991c92618967e89a5ee4bf84de1556b6af5f.tar.gz sb-builder-f8e9991c92618967e89a5ee4bf84de1556b6af5f.zip | |
stats returns the prunable items instead of their count, and a click on
the Built tile shows them in a non-modal box, so they can be read while
another job holds the lock and Prune's preview cannot start.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
| -rw-r--r-- | README.md | 3 | ||||
| -rwxr-xr-x | remote/sbb-remote | 4 | ||||
| -rw-r--r-- | sb_builder/__init__.py | 2 | ||||
| -rw-r--r-- | sb_builder/dashboard.py | 2 | ||||
| -rw-r--r-- | sb_builder/mainwindow.py | 17 | ||||
| -rw-r--r-- | tests/test_gui.py | 9 | ||||
| -rw-r--r-- | tests/test_remote.py | 2 |
7 files changed, 30 insertions, 9 deletions
@@ -90,7 +90,8 @@ reopens it. - **Dashboard**: VM load, uptime and free disk, package counts, slackrepo build results, last overlay pull, SBo orphans, recent jobs. Refreshes while visible. The tiles open Packages (the orphans tile with only the orphaned - filter on), Results (one result kind) and Jobs. + filter on), Results (one result kind) and Jobs; Built lists the packages + to prune (built, SlackBuild gone). - **Packages**: every package of the repository, with built version, hint and status (`ok`, `failed`, `never`, `outdated`, `newer`: built newer than the target, e.g. after a pin left its hint, so a build would downgrade). The diff --git a/remote/sbb-remote b/remote/sbb-remote index 15c0fec..d075f38 100755 --- a/remote/sbb-remote +++ b/remote/sbb-remote @@ -41,7 +41,7 @@ import time import tomllib import urllib.request -VERSION = "0.12.0" +VERSION = "0.12.1" DEFAULTS = { "state_dir": "/var/lib/sb-builder", "repo_dir": "/var/lib/sbopkg/SBo-danix", @@ -537,7 +537,7 @@ def cmd_stats(cfg): "slackpkg": _slackpkg(), "packages": _try(lambda: _packages(cfg)), "orphans": _try(lambda: _orphans(cfg)), - "prunable": _try(lambda: len(_prunable(cfg))), + "prunable": _try(lambda: _prunable(cfg)), "sync": {o: _try(lambda o=o: int(_git(cfg, "log", "-1", "--format=%ct", "--", o + "/"))) for o in cfg["overlays"]}, "slackrepo": _try(lambda: _slackrepo(cfg)), diff --git a/sb_builder/__init__.py b/sb_builder/__init__.py index 99d4de6..22beac6 100644 --- a/sb_builder/__init__.py +++ b/sb_builder/__init__.py @@ -16,4 +16,4 @@ """sb-builder: Qt6 GUI driving the SlackBuild tooling on a build VM.""" -VERSION = "0.12.0" # must match remote/sbb-remote VERSION +VERSION = "0.12.1" # must match remote/sbb-remote VERSION diff --git a/sb_builder/dashboard.py b/sb_builder/dashboard.py index c70258c..f4ea687 100644 --- a/sb_builder/dashboard.py +++ b/sb_builder/dashboard.py @@ -328,7 +328,7 @@ class Dashboard(QWidget): else: never = "" if p is None else f" · {num(p['total'] - sr['built'])} never built" if s.get("prunable"): - never += f" · {num(s['prunable'])} to prune" + never += f" · {num(len(s['prunable']))} to prune" t["Built"].set(num(sr["built"]), f"of {num(p and p['total'])}{never}") known = [ts for ts in sync.values() if ts is not None] t["Last pull"].set(fmt_age(min(known)) if known else NA, diff --git a/sb_builder/mainwindow.py b/sb_builder/mainwindow.py index aab6093..cee984f 100644 --- a/sb_builder/mainwindow.py +++ b/sb_builder/mainwindow.py @@ -115,6 +115,8 @@ class MainWindow(QMainWindow): self.dashboard.tiles["Packages"].link(self.open_packages) self.dashboard.orphans.link(lambda: self.open_packages().filter_to("orphaned")) self.dashboard.jobs.link(self.open_jobs) + self.prunable = [] + self.dashboard.tiles["Built"].link(self.show_prunable) self.dashboard.result_clicked.connect(self.open_results) self.jobs_tab = JobsTab(self.remote) self.jobs_tab.refresh_requested.connect(self.poll_jobs) @@ -222,7 +224,8 @@ class MainWindow(QMainWindow): if err: return self._failed(err) self.dashboard.show_stats(data) - self.packages_tab.set_prunable(data.get("prunable")) + self.prunable = data.get("prunable") or [] + self.packages_tab.set_prunable(len(self.prunable)) def _got_version(self, data, err): if err: @@ -352,6 +355,18 @@ class MainWindow(QMainWindow): else: d.show() + def show_prunable(self): + """The built packages whose SlackBuild is gone, readable while a job runs.""" + if not self.prunable: + return + box = QMessageBox(QMessageBox.Icon.Information, "To prune", + "Built, but their SlackBuild is gone from the tree. " + "Packages, Prune removes them.", parent=self) + box.setDetailedText("\n".join(self.prunable)) + box.setModal(False) + box.setAttribute(Qt.WidgetAttribute.WA_DeleteOnClose) + box.show() + def show_build_result(self, job): """A slackrepo run's per-package results: logs, Retry failed.""" if job["id"] in self.next_steps: diff --git a/tests/test_gui.py b/tests/test_gui.py index f5894de..496061a 100644 --- a/tests/test_gui.py +++ b/tests/test_gui.py @@ -32,7 +32,7 @@ sys.path.insert(0, ROOT) from PyQt6.QtCore import QObject, QPointF, QProcess, pyqtSignal # noqa: E402 from PyQt6.QtGui import QColor # noqa: E402 -from PyQt6.QtWidgets import QApplication # noqa: E402 +from PyQt6.QtWidgets import QApplication, QMessageBox # noqa: E402 from sb_builder import VERSION, config # noqa: E402 from sb_builder import hints as hintlib # noqa: E402 @@ -486,10 +486,15 @@ class SmokeTest(unittest.TestCase): self.assertIn(("job-start", "slackrepo", "build", "--preview", "b", "c"), remote.calls) def test_prunable_enables_prune(self): - w, _ = self.window(stats=(dict(STATS, prunable=3, slackrepo={"results": {}, "built": 5}), None)) + gone = ["a/x", "b/y", "c/z"] + w, _ = self.window(stats=(dict(STATS, prunable=gone, slackrepo={"results": {}, "built": 5}), None)) w.poll_jobs() self.assertTrue(w.packages_tab.act_prune.isEnabled()) self.assertIn("3 to prune", w.dashboard.tiles["Built"].detail.text()) + w.dashboard.tiles["Built"].clicked.emit() + box = w.findChild(QMessageBox) + self.assertFalse(box.isModal()) + self.assertEqual(box.detailedText(), "a/x\nb/y\nc/z") def test_slackpkg_dot(self): old = dict(STATS, slackpkg={"update": None, "upgrade": 1}) diff --git a/tests/test_remote.py b/tests/test_remote.py index 9f28701..f9e541f 100644 --- a/tests/test_remote.py +++ b/tests/test_remote.py @@ -185,7 +185,7 @@ class KindsTest(Base): kind = sbb.KINDS["slackrepo"] self.assertEqual(kind(self.cfg, ["prune", "--preview"]), (["slackrepo", "--repo=SBo-danix", "remove", "--preview", "misc/gone"], {})) - self.assertEqual(sbb.cmd_stats(self.cfg)["prunable"], 1) + self.assertEqual(sbb.cmd_stats(self.cfg)["prunable"], ["misc/gone"]) with self.assertRaises(sbb.Error): kind(self.cfg, ["prune", "kept"]) self.make_pkg("misc/gone") |
