From c7acbfc7d9146a4440f45f3efd4246935c2ffd19 Mon Sep 17 00:00:00 2001 From: "Danilo M." Date: Tue, 20 Oct 2026 12:50:18 +0200 Subject: 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 --- tests/test_remote.py | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) (limited to 'tests') diff --git a/tests/test_remote.py b/tests/test_remote.py index 54c5614..57d492c 100644 --- a/tests/test_remote.py +++ b/tests/test_remote.py @@ -434,6 +434,71 @@ class HintJobsTest(Base): self.assertEqual(self.read(self.hint), 'VERSION="2.0"\nDOWNLOAD="no"\n') +class PhantomTest(Base): + def setUp(self): + super().setUp() + self.cfg["phantom_deps_file"] = os.path.join(self.tmp, "phantom-deps") + with open(self.cfg["phantom_deps_file"], "w") as f: + f.write("# deps needed on stable but not on -current\nrust-opt\n") + self.make_pkg("desktop/marco", 'VERSION="1"\nREQUIRES="zenity libfoo"\n') + self.make_pkg("games/steam", 'VERSION="1"\nREQUIRES="zenity"\n', + hint='DELREQUIRES="rust-opt"\n') + self.make_pkg("libs/libfoo", 'VERSION="1"\nREQUIRES="%README% rust-opt"\n') + + def read(self, path): + with open(path) as f: + return f.read() + + def test_list_and_suggestions(self): + self.assertEqual(sbb.cmd_phantom_list(self.cfg), { + "deps": ["rust-opt"], + "suggestions": [{"name": "zenity", "needed_by": ["marco", "steam"]}]}) + os.remove(self.cfg["phantom_deps_file"]) + self.assertEqual(sbb.cmd_phantom_list(self.cfg)["deps"], []) # missing file: empty list + + def test_add_remove_keep_comments(self): + self.assertEqual(sbb.cmd_phantom_add(self.cfg, "zenity", "rust-opt", "zenity"), + {"deps": ["rust-opt", "zenity"]}) + self.assertEqual(sbb.cmd_phantom_list(self.cfg)["suggestions"], []) + self.assertEqual(sbb.cmd_phantom_remove(self.cfg, "rust-opt"), {"deps": ["zenity"]}) + self.assertEqual(self.read(self.cfg["phantom_deps_file"]), + "# deps needed on stable but not on -current\nzenity\n") + for bad in ([], ["../x"], ["a b"]): + with self.subTest(bad=bad), self.assertRaises(sbb.Error): + sbb.cmd_phantom_add(self.cfg, *bad) + + def test_fix_current(self): + sbb.cmd_phantom_add(self.cfg, "zenity") + out = io.StringIO() + with contextlib.redirect_stdout(out): + sbb.cmd_fix_current_now(self.cfg) + lines = out.getvalue().splitlines() + self.assertEqual(json.loads(lines[-1].split(" ", 1)[1]), + {"ok": ["libfoo", "marco", "steam"], "failed": []}) + hints = self.cfg["hintdir"] + self.assertEqual(self.read(os.path.join(hints, "marco.hint")), 'DELREQUIRES="zenity"\n') + self.assertFalse(os.path.exists(os.path.join(hints, "marco.hint.bak"))) # new: revert deletes + self.assertEqual(self.read(os.path.join(hints, "steam.hint")), 'DELREQUIRES="rust-opt zenity"\n') + self.assertEqual(self.read(os.path.join(hints, "steam.hint.bak")), 'DELREQUIRES="rust-opt"\n') + self.assertIn("marco: DELREQUIRES zenity", lines) + out = io.StringIO() + with contextlib.redirect_stdout(out): + sbb.cmd_fix_current_now(self.cfg) # second run: nothing to do, no .bak churn + self.assertIn('{"ok": [], "failed": []}', out.getvalue()) + self.assertEqual(self.read(os.path.join(hints, "steam.hint.bak")), 'DELREQUIRES="rust-opt"\n') + + def test_merge_delrequires(self): + self.assertEqual(sbb.merge_delrequires('DELREQUIRES="a"\n', ["b", "a"]), 'DELREQUIRES="a b"\n') + self.assertIsNone(sbb.merge_delrequires('DELREQUIRES="a b"\n', ["b"])) + self.assertEqual(sbb.merge_delrequires("", ["b", "b"]), 'DELREQUIRES="b"\n') + + def test_job_kind(self): + me = [sys.executable, os.path.abspath(sbb.__file__), "_hint"] + self.assertEqual(sbb.KINDS["fix-current"](self.cfg, []), (me + ["fix-current"], {})) + with self.assertRaisesRegex(sbb.Error, "no arguments"): + sbb.KINDS["fix-current"](self.cfg, ["x"]) + + class MainTest(Base): def test_unknown_command(self): rc, data = self.run_main("nope") -- cgit v1.2.3