diff options
| author | Danilo M. <danix@danix.xyz> | 2026-10-20 12:50:18 +0200 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-10-20 12:50:18 +0200 |
| commit | c7acbfc7d9146a4440f45f3efd4246935c2ffd19 (patch) | |
| tree | 1537582ac26f90f2931f6257e5307170af3af9f5 /remote | |
| parent | 2c3c98575d366fe5645d7d3fd606b7184006ef09 (diff) | |
| download | sb-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')
| -rw-r--r-- | remote/config.example.toml | 3 | ||||
| -rwxr-xr-x | remote/sbb-remote | 104 |
2 files changed, 102 insertions, 5 deletions
diff --git a/remote/config.example.toml b/remote/config.example.toml index a77ace9..0fbe801 100644 --- a/remote/config.example.toml +++ b/remote/config.example.toml @@ -12,4 +12,5 @@ hintdir = "/etc/slackrepo/SBo-danix/hintfiles" default_hintdir = "" # searched after hintdir when set genreprc = "/root/.genreprc" # REPOSOWNERGPG names the signing key slackrepo_logdir = "/var/log/slackrepo/SBo-danix" -manifest_packages = ["neovim", "openvino"] # bundled deps: hint-update refuses them (phase 4b) +manifest_packages = ["neovim"] # bundled deps: hint-update refuses them (phase 4b) +phantom_deps_file = "/etc/sb-builder/phantom-deps" # deps -current ships; one per line, # comments 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, } |
