aboutsummaryrefslogtreecommitdiffstats
path: root/remote/sbb-remote
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-10-20 12:50:18 +0200
committerDanilo M. <danix@danix.xyz>2026-10-20 12:50:18 +0200
commitc7acbfc7d9146a4440f45f3efd4246935c2ffd19 (patch)
tree1537582ac26f90f2931f6257e5307170af3af9f5 /remote/sbb-remote
parent2c3c98575d366fe5645d7d3fd606b7184006ef09 (diff)
downloadsb-builder-c7acbfc7d9146a4440f45f3efd4246935c2ffd19.tar.gz
sb-builder-c7acbfc7d9146a4440f45f3efd4246935c2ffd19.zip
sbb-remote 0.7.0: phantom deps list, suggestions, fix-current
The list moves to phantom_deps_file (/etc/sb-builder/phantom-deps, mkhint's format), edited with phantom-add/phantom-remove. phantom-list also suggests every REQUIRES name no package of the repo has, with who needs it: SBo drops a package when it enters the official tree. The fix-current job (and fix-current-now, inline for sbshadow) is mkhint -F: listed deps merged into DELREQUIRES, .bak first, add only. manifest_packages is neovim alone: openvino lives in the overlay now. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'remote/sbb-remote')
-rwxr-xr-xremote/sbb-remote104
1 files changed, 100 insertions, 4 deletions
diff --git a/remote/sbb-remote b/remote/sbb-remote
index 5183b77..c37b44c 100755
--- a/remote/sbb-remote
+++ b/remote/sbb-remote
@@ -40,7 +40,7 @@ import time
import tomllib
import urllib.request
-VERSION = "0.6.0"
+VERSION = "0.7.0"
DEFAULTS = {
"state_dir": "/var/lib/sb-builder",
"repo_dir": "/var/lib/sbopkg/SBo-danix",
@@ -53,7 +53,8 @@ DEFAULTS = {
"default_hintdir": "",
"genreprc": "/root/.genreprc",
"slackrepo_logdir": "/var/log/slackrepo/SBo-danix",
- "manifest_packages": ["neovim", "openvino"], # bundled deps: left to mkhint until phase 4b
+ "manifest_packages": ["neovim"], # bundled deps: left to mkhint until phase 4b
+ "phantom_deps_file": "/etc/sb-builder/phantom-deps", # deps -current ships: DELREQUIREd
}
FLAGS = ("--yes", "--no")
JOB_ID = re.compile(r"^\d{8}-\d{6}-[a-z]+(-[a-z]+)*(-\d+)?$")
@@ -196,14 +197,18 @@ def hint_args(cfg, kind, args):
def _self_job(kind):
"""A job kind run by this file itself (_hint), argv-free like the others."""
def build(cfg, args):
- hint_args(cfg, kind, args)
+ if kind == "fix-current":
+ if args:
+ raise Error("fix-current takes no arguments")
+ else:
+ hint_args(cfg, kind, args)
return [sys.executable, os.path.abspath(__file__), "_hint", kind, *args], {}
return build
KINDS = {"sbpull": kind_sbpull, "sbshadow": kind_sbshadow,
"slackrepo": kind_slackrepo, "publish": kind_publish,
- **{k: _self_job(k) for k in ("hint-update", "hint-new")}}
+ **{k: _self_job(k) for k in ("hint-update", "hint-new", "fix-current")}}
def signs(kind, args):
@@ -757,8 +762,95 @@ def _save(target, text):
_write(target, text)
+# ── phantom deps: what -current ships, DELREQUIREd from the SBo packages ─────
+
+def phantom_deps(cfg):
+ """The listed names, file order; a missing file is an empty list."""
+ text = _read(cfg["phantom_deps_file"]) or ""
+ return list(dict.fromkeys(n for n in (ln.split("#")[0].strip() for ln in text.splitlines()) if n))
+
+
+def _set_phantom(cfg, names, add):
+ names = list(names)
+ if not names or not all(PKGNAME.match(n) for n in names):
+ raise Error("expected package names")
+ text = _read(cfg["phantom_deps_file"]) or ""
+ have = phantom_deps(cfg)
+ if add:
+ text += "".join(f"{n}\n" for n in dict.fromkeys(names) if n not in have)
+ else: # drop the names' lines, comments and the rest kept as written
+ text = "".join(ln for ln in text.splitlines(keepends=True)
+ if ln.split("#")[0].strip() not in names)
+ _write(cfg["phantom_deps_file"], text)
+ return {"deps": phantom_deps(cfg)}
+
+
+def cmd_phantom_add(cfg, *names):
+ return _set_phantom(cfg, names, True)
+
+
+def cmd_phantom_remove(cfg, *names):
+ return _set_phantom(cfg, names, False)
+
+
+def _requires(cfg, pkgs):
+ """{pkg: REQUIRES words without %README%}."""
+ out = {}
+ for pkg, path in pkgs.items():
+ info = _read(os.path.join(cfg["repo_dir"], path, pkg + ".info")) or ""
+ out[pkg] = [r for r in hint_tokens(info, "REQUIRES") if r != "%README%"]
+ return out
+
+
+def cmd_phantom_list(cfg):
+ """The list, and suggestions: REQUIRES names no package of the repo has (SBo
+ drops a package when it enters the official tree), with who needs them."""
+ pkgs = _pkgmap(cfg)
+ listed = set(phantom_deps(cfg))
+ needed = {}
+ for pkg, reqs in sorted(_requires(cfg, pkgs).items()):
+ for r in reqs:
+ if r not in pkgs and r not in listed:
+ needed.setdefault(r, []).append(pkg)
+ return {"deps": phantom_deps(cfg),
+ "suggestions": [{"name": n, "needed_by": needed[n]} for n in sorted(needed)]}
+
+
+def merge_delrequires(text, deps):
+ """text with deps added to DELREQUIRES, or None when all are there already."""
+ have = hint_tokens(text, "DELREQUIRES")
+ add = [d for d in dict.fromkeys(deps) if d not in have]
+ return hint_set(text, "DELREQUIRES", " ".join(have + add)) if add else None
+
+
+def cmd_fix_current_now(cfg):
+ """mkhint -F: listed deps into the DELREQUIRES of whoever requires them (add only)."""
+ ok, failed = [], []
+ listed = phantom_deps(cfg)
+ pkgs = _pkgmap(cfg)
+ for pkg, reqs in sorted(_requires(cfg, pkgs).items()):
+ deps = [d for d in listed if d in reqs]
+ if not deps:
+ continue
+ try:
+ _, target = _hint_target(cfg, pkg, pkgs)
+ text = merge_delrequires(_read(target) or "", deps)
+ if text is not None:
+ _save(target, text)
+ print(f"{pkg}: DELREQUIRES {' '.join(deps)}", flush=True)
+ ok.append(pkg)
+ except (Error, OSError) as e:
+ print(f"{pkg}: failed: {e}", flush=True)
+ failed.append([pkg, str(e)])
+ print("SBB-RESULT " + json.dumps({"ok": ok, "failed": failed}), flush=True)
+ if failed:
+ raise Error(f"{len(failed)} failed")
+
+
def cmd_hint(cfg, kind=None, *args):
"""Body of the hint jobs: log lines, then SBB-RESULT {"ok": [...], "failed": [[pkg, why]]}."""
+ if kind == "fix-current":
+ return cmd_fix_current_now(cfg)
if kind not in ("hint-update", "hint-new"):
raise Error(f"unknown hint job: {kind}")
ok, failed = [], []
@@ -900,6 +992,10 @@ COMMANDS = {
"hint-revert": cmd_hint_revert,
"hint-delete": cmd_hint_delete,
"job-result": cmd_job_result,
+ "phantom-list": cmd_phantom_list,
+ "phantom-add": cmd_phantom_add,
+ "phantom-remove": cmd_phantom_remove,
+ "fix-current-now": cmd_fix_current_now,
"_run": cmd_run,
"_hint": cmd_hint,
}