fix: refuse an unknown --system before the refresh

The platform's systems are known once its config is loaded. The filter ran inside the build, after the output lock and a refresh of every data directory, and ended on a WARNING with exit 1. It is now a usage error before any work.
This commit is contained in:
Abdessamad Derraz committed 2026-10-21 10:08:17 +02:00
1 parent a6eda07b8a
commit fb40b903ca
2 files changed
+64

No files matched your search

+36
View File
@@ -2314,6 +2314,39 @@ def generate_target_manifests(targets_dir: str, output_dir: str) -> None:
print(f"Generated {count} target manifest(s) in {output_dir}")
def _refuse_unknown_systems(
system_filter: list[str],
platforms: list[str],
platforms_dir: str,
parser: argparse.ArgumentParser,
) -> None:
"""Refuse a --system no selected platform declares, before any work.
The name is known once the config is loaded. Checked inside the build, a
typo cost the lock and a refresh of every data directory first, then
ended on a WARNING and exit 1.
"""
from common import _norm_system_id
wanted = {_norm_system_id(s) for s in system_filter}
declared: set[str] = set()
for name in platforms:
systems = load_platform_config(name, platforms_dir).get("systems", {})
if any(sid in system_filter or _norm_system_id(sid) in wanted for sid in systems):
return
declared.update(systems)
where = f"--platform {platforms[0]}" if len(platforms) == 1 else "--all"
hint = suggest_names(
system_filter,
sorted(declared),
f"--platform {platforms[0]} --list-systems" if len(platforms) == 1
else "--platform <name> --list-systems",
)
parser.error(
f"--system {','.join(system_filter)} matches no system of {where}. {hint}"
)
def _refuse_for_verify_packs(args: argparse.Namespace, parser: argparse.ArgumentParser) -> None:
"""What --verify-packs cannot be combined with, refused before any lock.
@@ -3332,6 +3365,9 @@ def _main(held: contextlib.ExitStack) -> None:
parser.error("Specify --platform or --all")
return
if system_filter:
_refuse_unknown_systems(system_filter, platforms, args.platforms_dir, parser)
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
+28
View File
@@ -6296,6 +6296,34 @@ class ATargetTypoIsAnErrorInEveryTool(unittest.TestCase):
self.assertIn("verify.py --platform retroarch --list-targets", output)
class AnUnknownSystemIsRefusedBeforeAnyWork(unittest.TestCase):
"""generate_pack checked --system inside the build: a typo took the
output lock and refreshed every data directory, then ended on a WARNING."""
def test_refused_before_the_lock_and_the_refresh(self):
with tempfile.TemporaryDirectory(dir=ROOT / "tmp") as tmp:
out = Path(tmp) / "never"
with mock.patch.dict(os.environ, {"RETROBIOS_OFFLINE": ""}):
proc = subprocess.run(
[sys.executable, "scripts/generate_pack.py", "--platform", "batocera",
"--system", "playstaton-nothing", "--output-dir", str(out)],
cwd=ROOT, capture_output=True, text=True, timeout=120,
)
self.assertEqual(proc.returncode, 2, proc.stdout + proc.stderr)
self.assertIn("error: --system playstaton-nothing matches no system", proc.stderr)
self.assertFalse(out.exists())
def test_a_known_system_passes_the_early_check(self):
import argparse
import generate_pack
parser = argparse.ArgumentParser()
generate_pack._refuse_unknown_systems(
["sony-playstation"], ["retroarch"], str(ROOT / "platforms"), parser
)
class NoArchiveRepeatsAMemberName(unittest.TestCase):
"""s8k_cpu.zip held three member names twice (MAME reuses them across
two ROM_SYSTEM_BIOS of one device). Every pack build printed raw zipfile