aboutsummaryrefslogtreecommitdiffstats
path: root/remote/sbb-remote
diff options
context:
space:
mode:
Diffstat (limited to 'remote/sbb-remote')
-rwxr-xr-xremote/sbb-remote42
1 files changed, 39 insertions, 3 deletions
diff --git a/remote/sbb-remote b/remote/sbb-remote
index ace4fb9..15c0fec 100755
--- a/remote/sbb-remote
+++ b/remote/sbb-remote
@@ -41,7 +41,7 @@ import time
import tomllib
import urllib.request
-VERSION = "0.11.0"
+VERSION = "0.12.0"
DEFAULTS = {
"state_dir": "/var/lib/sb-builder",
"repo_dir": "/var/lib/sbopkg/SBo-danix",
@@ -63,7 +63,7 @@ JOB_ID = re.compile(r"^\d{8}-\d{6}-[a-z]+(-[a-z]+)*(-\d+)?$")
PKG = re.compile(r"^[^/]+/([^/]+)/\1\.SlackBuild$")
PKGNAME = re.compile(r"^[A-Za-z0-9._+-]+$")
VERSION_ARG = re.compile(r"^[A-Za-z0-9._+-]{1,64}$")
-ACTIONS = ("build", "rebuild", "update", "remove")
+ACTIONS = ("build", "rebuild", "update", "remove", "prune")
PRESET = "/usr/libexec/gpg-preset-passphrase"
ITEM = re.compile(r"^[A-Za-z0-9._+-]+/[A-Za-z0-9._+-]+$") # category/pkg
LOG_TAIL = 512 * 1024 # bytes of the log returned; the failure is at the end
@@ -126,6 +126,27 @@ def kind_sbshadow(cfg, args):
return ["sbshadow", _flag(args)], {}
+def _prunable(cfg):
+ """Built items (slackrepo's packages table) whose SlackBuild is gone from the tree."""
+ db = sqlite3.connect(f"file:{cfg['slackrepo_db']}?mode=ro", uri=True)
+ try:
+ items = [i for (i,) in db.execute("select distinct itemid from packages order by itemid")]
+ finally:
+ db.close()
+ return [i for i in items if ITEM.match(i) and not i.startswith("-") and not os.path.isfile(
+ os.path.join(cfg["repo_dir"], i, os.path.basename(i) + ".SlackBuild"))]
+
+
+def _results_since(cfg, start):
+ """{itemid: result} of the slackrepo items that finished since start."""
+ db = sqlite3.connect(f"file:{cfg['slackrepo_db']}?mode=ro", uri=True)
+ try:
+ return dict(db.execute("select itemid, result from buildresults"
+ " where cast(time as integer) >= ?", (int(start),)))
+ finally:
+ db.close()
+
+
def kind_slackrepo(cfg, args):
if not args or args[0] not in ACTIONS:
raise Error(f"slackrepo: action must be one of {', '.join(ACTIONS)}")
@@ -141,7 +162,14 @@ def kind_slackrepo(cfg, args):
raise Error(f"slackrepo: no such package: {p}")
if p not in pkgs:
pkgs.append(p)
- if not pkgs and action != "update":
+ if action == "prune":
+ if pkgs:
+ raise Error("slackrepo: prune takes no packages")
+ pkgs = _prunable(cfg) # computed here, never named by the GUI
+ if not pkgs:
+ raise Error("slackrepo: nothing to prune")
+ action = "remove"
+ elif not pkgs and action != "update":
raise Error(f"slackrepo: {action} needs at least one package")
argv = ["slackrepo", f"--repo={cfg['slackrepo_repo']}", action]
if "--preview" in opts:
@@ -360,6 +388,13 @@ def cmd_run(cfg, jid=None):
rc = p.wait()
meta.update(end=time.time(), exit=rc,
status="ok" if rc == 0 else "killed" if rc == -signal.SIGTERM else "failed")
+ if signs(meta["kind"], meta["args"]):
+ # slackrepo exits 0 whatever its items did: their results tell
+ results = _try(lambda: _results_since(cfg, meta["start"]))
+ if results is not None:
+ meta["results"] = results
+ if rc == 0 and set(results.values()) & {"failed", "aborted", "bad"}:
+ meta["status"] = "failed"
write_meta(d, meta)
return None
@@ -502,6 +537,7 @@ def cmd_stats(cfg):
"slackpkg": _slackpkg(),
"packages": _try(lambda: _packages(cfg)),
"orphans": _try(lambda: _orphans(cfg)),
+ "prunable": _try(lambda: len(_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)),