diff options
Diffstat (limited to 'sb_builder/packages.py')
| -rw-r--r-- | sb_builder/packages.py | 41 |
1 files changed, 34 insertions, 7 deletions
diff --git a/sb_builder/packages.py b/sb_builder/packages.py index f1a7224..0a669bb 100644 --- a/sb_builder/packages.py +++ b/sb_builder/packages.py @@ -17,6 +17,7 @@ """Packages tab: search the inventory, read a package's hints, start slackrepo previews.""" import html +import re from PyQt6.QtCore import QAbstractTableModel, QModelIndex, QSortFilterProxyModel, Qt, pyqtSignal from PyQt6.QtGui import QColor, QKeySequence, QShortcut @@ -29,22 +30,48 @@ from .fmt import NA, fmt_time from .ui import SP, action, chip, enable, group_label, search_field OVERLAYS = ("personal", "pentesting") -STATUSES = ("ok", "failed", "never", "outdated") +STATUSES = ("ok", "failed", "never", "outdated", "newer") COLUMNS = ("", "name", "category", "version", "built", "status", "maintainer") -STATUS_COLOR = {"ok": STATUS["ok"], "failed": STATUS["failed"], "outdated": STATUS["aborted"]} +STATUS_COLOR = {"ok": STATUS["ok"], "failed": STATUS["failed"], "outdated": STATUS["aborted"], + "newer": STATUS["bad"]} FIELDS = {"cat": "category", "maint": "maintainer", "req": "requires", "status": "status"} +PRE_RELEASE = ("alpha", "beta", "pre", "rc", "dev") + + +def _runs(v): + return [int(r) if r.isdigit() else r.lower() for r in re.findall(r"\d+|[A-Za-z]+", v)] + + +def vercmp(a, b): + """-1, 0 or 1: a older, equal, newer than b. + + Digit runs compare as numbers, letter runs as text, a number beats a + letter. Past the shorter version, a pre-release word makes the longer one + older (1.0rc1 < 1.0), anything else newer (1.0.1, 4.3.5b > their base). + """ + # ponytail: single-letter pre-releases (1.0b1) count as newer than 1.0; + # snapshots (20240101_ab12cd) order by date, their hash part arbitrarily + ra, rb = _runs(a), _runs(b) + for x, y in zip(ra, rb): + if x != y: + if type(x) is type(y): + return -1 if x < y else 1 + return 1 if isinstance(x, int) else -1 + if len(ra) == len(rb): + return 0 + sign, nxt = (1, ra[len(rb)]) if len(ra) > len(rb) else (-1, rb[len(ra)]) + return -sign if nxt in PRE_RELEASE else sign def status(row): - # ponytail: outdated compares versions only; slackrepo also rebuilds on - # SlackBuild or dependency changes, which its preview shows + # ponytail: compares versions only; slackrepo also rebuilds on SlackBuild + # or dependency changes, which its preview shows if not row["built_version"] and not row["result"]: return "never" if row["result"] in ("failed", "bad", "aborted"): return "failed" - if row["built_version"] != row["version"]: - return "outdated" - return "ok" + c = vercmp(row["built_version"] or "", row["version"] or "") + return "outdated" if c < 0 else "newer" if c > 0 else "ok" def overlay(row): |
