diff options
| -rw-r--r-- | README.md | 5 | ||||
| -rwxr-xr-x | remote/sbb-remote | 11 | ||||
| -rw-r--r-- | sb_builder/__init__.py | 2 | ||||
| -rw-r--r-- | sb_builder/dashboard.py | 5 | ||||
| -rw-r--r-- | sb_builder/mainwindow.py | 1 | ||||
| -rw-r--r-- | sb_builder/packages.py | 8 | ||||
| -rw-r--r-- | tests/test_gui.py | 8 | ||||
| -rw-r--r-- | tests/test_remote.py | 7 |
8 files changed, 40 insertions, 7 deletions
@@ -52,8 +52,9 @@ now** loses nothing: **Run it** in the Jobs tab, on a finished preview, reopens it. - **Dashboard**: VM load, uptime and free disk, package counts, slackrepo - build results, last overlay pull, recent jobs. Refreshes while visible. - The tiles open Packages, Results (one result kind) and Jobs. + 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. - **Packages**: every package of the repository, with built version and status (`ok`, `failed`, `never`, `outdated`). Search by name or summary, or with `cat:`, `maint:`, `req:`, `status:`; toggle the overlay and status diff --git a/remote/sbb-remote b/remote/sbb-remote index 5f01186..1c87f80 100755 --- a/remote/sbb-remote +++ b/remote/sbb-remote @@ -40,7 +40,7 @@ import time import tomllib import urllib.request -VERSION = "0.8.0" +VERSION = "0.9.0" DEFAULTS = { "state_dir": "/var/lib/sb-builder", "repo_dir": "/var/lib/sbopkg/SBo-danix", @@ -416,6 +416,14 @@ def _packages(cfg): "shadowed": len(shadowed)} +def _orphans(cfg): + """Packages SBo marks MAINTAINER="orphaned - no maintainer"; None without a repo.""" + if not os.path.isdir(cfg["repo_dir"]): + return None + return sum(re.search(r'^MAINTAINER="orphaned', _read(os.path.join(d, os.path.basename(d) + ".info")) or "", + re.M) is not None for d in _pkgdirs(cfg["repo_dir"], "*/*")) + + def _slackrepo(cfg): db = sqlite3.connect(f"file:{cfg['slackrepo_db']}?mode=ro", uri=True) try: @@ -478,6 +486,7 @@ def cmd_stats(cfg): "disk": {"total": root and root.total, "free": root and root.free}, "slackpkg": _slackpkg(), "packages": _try(lambda: _packages(cfg)), + "orphans": _try(lambda: _orphans(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 e4a5697..c845154 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.8.0" # must match remote/sbb-remote VERSION +VERSION = "0.9.0" # must match remote/sbb-remote VERSION diff --git a/sb_builder/dashboard.py b/sb_builder/dashboard.py index 3096fb8..9b04183 100644 --- a/sb_builder/dashboard.py +++ b/sb_builder/dashboard.py @@ -278,9 +278,7 @@ class Dashboard(QWidget): self.results.body.addWidget(self.legend) self.results.body.addStretch() - self.orphans = Card("SBo orphans") - self.orphans.body.addWidget(muted(QLabel("coming in phase 5"))) - self.orphans.body.addStretch() + self.orphans = Tile("SBo orphans") self.jobs = Card("Recent jobs") self.jobs_list = QLabel("no jobs yet") @@ -320,6 +318,7 @@ class Dashboard(QWidget): else: extra = " · ".join(f"{num(v)}\u00a0{k}" for k, v in p.items() if k != "total") t["Packages"].set(num(p["total"]), extra) + self.orphans.set(num(s.get("orphans")), "packages with no maintainer on SBo") if sr is None: t["Built"].set(NA, "no slackrepo database") else: diff --git a/sb_builder/mainwindow.py b/sb_builder/mainwindow.py index ec2b87a..3860079 100644 --- a/sb_builder/mainwindow.py +++ b/sb_builder/mainwindow.py @@ -108,6 +108,7 @@ class MainWindow(QMainWindow): self.dashboard = Dashboard() self.dashboard.refresh.triggered.connect(self.poll_stats) 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.dashboard.result_clicked.connect(self.open_results) self.jobs_tab = JobsTab(self.remote) diff --git a/sb_builder/packages.py b/sb_builder/packages.py index 68de7c2..f1a7224 100644 --- a/sb_builder/packages.py +++ b/sb_builder/packages.py @@ -319,6 +319,14 @@ class PackagesTab(QWidget): self.model.set_rows(load_rows(data)) self.update_count() + def filter_to(self, name): + """Show only one chip's packages (from a Dashboard click).""" + for k, c in self.chips.items(): + c.blockSignals(True) + c.setChecked(k == name) + c.blockSignals(False) + self.refilter() + def refilter(self): on = {n for n, b in self.chips.items() if b.isChecked()} self.proxy.update(self.query.text(), on - set(STATUSES) - {"orphaned"}, on & set(STATUSES), diff --git a/tests/test_gui.py b/tests/test_gui.py index beec1fe..d005447 100644 --- a/tests/test_gui.py +++ b/tests/test_gui.py @@ -358,6 +358,14 @@ class SmokeTest(unittest.TestCase): self.assertEqual(w.conn.text(), "● VM off") self.assertFalse(w.vm_btn.isHidden()) + def test_orphans_tile_opens_filtered_packages(self): + w, _ = self.window(stats=(dict(STATS, orphans=1936), None)) + w.poll_jobs() + self.assertEqual(w.dashboard.orphans.value.text(), "1,936") + w.dashboard.orphans.clicked.emit() + self.assertIs(w.tabs.currentWidget(), w.packages_tab) + self.assertEqual([n for n, c in w.packages_tab.chips.items() if c.isChecked()], ["orphaned"]) + def test_slackpkg_dot(self): old = dict(STATS, slackpkg={"update": None, "upgrade": 1}) w, _ = self.window(stats=(old, None)) diff --git a/tests/test_remote.py b/tests/test_remote.py index 30bdc73..7288828 100644 --- a/tests/test_remote.py +++ b/tests/test_remote.py @@ -779,12 +779,19 @@ class JobsTest(Base): class StatsTest(Base): + def test_orphans(self): + self.make_pkg("net/a", 'MAINTAINER="orphaned - no maintainer"\nEMAIL="NOEMAIL"\n') + self.make_pkg("net/b", 'MAINTAINER="Someone"\n') + self.make_pkg("personal/c", 'PRGNAM="c"\nMAINTAINER="orphaned - no maintainer"\n') + self.assertEqual(sbb._orphans(self.cfg), 2) + def test_missing_sources_are_null(self): s = sbb.cmd_stats(self.cfg) self.assertIsNotNone(s["load"]) self.assertEqual(set(s["disk"]), {"total", "free"}) self.assertIn("slackpkg", s) self.assertIsNone(s["packages"]) + self.assertIsNone(s["orphans"]) self.assertIsNone(s["slackrepo"]) self.assertEqual(s["sync"], {"personal": None, "pentesting": None}) json.dumps(s) |
