fix: skip a platform without the --system asked

--all --system built every pack asked for and exited 1 on a platform
that has no such system. The scope is now decided before the lock:
skipped under --all, refused under --platform (finding 15).
This commit is contained in:
Abdessamad Derraz committed 2026-11-05 11:49:41 +01:00
1 parent 7f31cf37cf
commit 1718813728
2 files changed
+80 -2

No files matched your search

+47 -2
View File
@@ -53,6 +53,7 @@ from common import (
list_platform_system_ids,
platform_system_names,
resolve_system_arg,
select_systems,
platform_scope_systems,
system_scope_error,
canonical_target_name,
@@ -2358,6 +2359,46 @@ def _resolve_systems(args: argparse.Namespace, parser: argparse.ArgumentParser)
parser.error(f"--system {args.system}: {exc}")
def _platforms_with_systems(
args: argparse.Namespace,
platforms: list[str],
system_filter: list[str],
emu_profiles: dict,
target_cores_cache: dict[str, set[str] | None],
) -> list[str]:
"""The platforms a --system list leaves a system to pack, before any lock.
Under --all a platform without one is out of scope, as a platform
without the target is: `--all --system sony-playstation-2` built every
PS2 pack and exited 1 on MiSTer, which has no PS2. Under --platform the
request is refused here, with its reason.
"""
kept = []
for name in platforms:
config = load_platform_config(name, args.platforms_dir)
tc = target_cores_cache.get(name) if args.target else None
if platform_scope_systems(config, emu_profiles, tc, system_filter):
kept.append(name)
continue
if not args.all:
reason = system_scope_error(config, name, system_filter, args.target)
print(f"ERROR: {reason}", file=sys.stderr)
sys.exit(1)
declared = select_systems(config.get("systems", {}), system_filter)
reason = (
system_scope_error(config, name, system_filter, args.target)
if declared and args.target
else f"no system {', '.join(system_filter)}"
)
print(f"INFO: Skipping {name}: {reason}")
if not kept:
where = f" on target {args.target}" if args.target else ""
print(f"ERROR: no platform packed here runs {', '.join(system_filter)}{where}",
file=sys.stderr)
sys.exit(1)
return kept
def _refuse_for_verify_packs(args: argparse.Namespace, parser: argparse.ArgumentParser) -> None:
"""What --verify-packs cannot be combined with, refused before any lock.
@@ -3478,6 +3519,12 @@ def _main(held: contextlib.ExitStack) -> None:
print(f"ERROR: {e}", file=sys.stderr)
sys.exit(1)
emu_profiles = load_emulator_profiles(args.emulators_dir)
if system_filter:
platforms = _platforms_with_systems(
args, platforms, system_filter, emu_profiles, target_cores_cache
)
data_registry = load_data_dir_registry(args.platforms_dir)
# The output directory is claimed before the data directory refresh: a
# refresh waits for every run that holds a cache, so a second build
@@ -3497,8 +3544,6 @@ def _main(held: contextlib.ExitStack) -> None:
if data_registry:
hold_data_dirs(held, data_registry)
emu_profiles = load_emulator_profiles(args.emulators_dir)
groups = group_identical_platforms(
platforms, args.platforms_dir, target_cores_cache if args.target else None
)
+33
View File
@@ -163,5 +163,38 @@ class ASplitBuildsOnlyTheTargetsSystems(unittest.TestCase):
self.assertIn("sony-playstation", systems)
class APlatformWithoutTheSystemIsOutOfScope(unittest.TestCase):
"""`--all --system sony-playstation-2` built the five PS2 packs and
exited 1 on 'no pack for misterfpga', which has no PS2."""
def _scope(self, **args):
import argparse
import generate_pack
from common import load_emulator_profiles
values = {"platforms_dir": str(REPO_ROOT / "platforms"), "target": None,
"all": True}
values.update(args)
out = io.StringIO()
with contextlib.redirect_stdout(out), contextlib.redirect_stderr(out):
kept = generate_pack._platforms_with_systems(
argparse.Namespace(**values), ["retroarch", "misterfpga"],
["sony-playstation-2"],
load_emulator_profiles(str(REPO_ROOT / "emulators")), {},
)
return kept, out.getvalue()
def test_all_skips_it(self):
kept, out = self._scope()
self.assertEqual(kept, ["retroarch"])
self.assertIn("INFO: Skipping misterfpga: no system sony-playstation-2", out)
def test_a_named_platform_is_refused(self):
with self.assertRaises(SystemExit) as ctx:
self._scope(all=False)
self.assertEqual(ctx.exception.code, 1)
if __name__ == "__main__":
unittest.main()