fix: name a target by its canonical name

This commit is contained in:
Abdessamad Derraz committed 2026-10-10 08:09:00 +02:00
1 parent e6905f48e7
commit 707c81d2cf
3 files changed
+115 -13

No files matched your search

+46 -13
View File
@@ -239,6 +239,50 @@ def list_registered_platforms(
return platforms
def _target_overrides(platform_name: str, targets_dir: str) -> dict:
overrides_file = os.path.join(targets_dir, "_overrides.yml")
if not os.path.exists(overrides_file):
return {}
with open(overrides_file) as f:
all_overrides = yaml_load(f) or {}
return all_overrides.get(platform_name, {}).get("targets", {})
def _target_alias_index(targets: dict, overrides: dict) -> dict[str, str]:
"""Every name a target answers to, mapped to the name its file uses."""
alias_index: dict[str, str] = {}
for tname in targets:
alias_index[tname] = tname
for alias in overrides.get(tname, {}).get("aliases", []):
alias_index[alias] = tname
return alias_index
def canonical_target_name(
platforms: list[str], target: str, platforms_dir: str = "platforms"
) -> str:
"""The name a target is filed under, whichever alias was typed.
`switch`, `nx` and `nintendo-switch` named three packs of one target, and
--verify-packs looked for a name no build had written. The typed name is
kept when no platform knows it or when platforms file it differently.
"""
targets_dir = os.path.join(platforms_dir, "targets")
found: set[str] = set()
for platform_name in platforms:
target_file = os.path.join(targets_dir, f"{platform_name}.yml")
if not os.path.exists(target_file):
continue
with open(target_file) as f:
targets = (yaml_load(f) or {}).get("targets", {})
canonical = _target_alias_index(
targets, _target_overrides(platform_name, targets_dir)
).get(target)
if canonical:
found.add(canonical)
return found.pop() if len(found) == 1 else target
def load_target_config(
platform_name: str,
target: str,
@@ -260,19 +304,8 @@ def load_target_config(
data = yaml_load(f) or {}
targets = data.get("targets", {})
overrides_file = os.path.join(targets_dir, "_overrides.yml")
overrides = {}
if os.path.exists(overrides_file):
with open(overrides_file) as f:
all_overrides = yaml_load(f) or {}
overrides = all_overrides.get(platform_name, {}).get("targets", {})
alias_index: dict[str, str] = {}
for tname in targets:
alias_index[tname] = tname
for alias in overrides.get(tname, {}).get("aliases", []):
alias_index[alias] = tname
overrides = _target_overrides(platform_name, targets_dir)
alias_index = _target_alias_index(targets, overrides)
canonical = alias_index.get(target)
if canonical is None:
+11
View File
@@ -45,6 +45,7 @@ from common import (
group_identical_platforms,
list_emulator_profiles,
list_platform_system_ids,
canonical_target_name,
list_registered_platforms,
list_system_ids,
load_data_dir_registry,
@@ -2766,6 +2767,16 @@ def main():
packresolve.set_offline(bool(args.offline))
_refuse_unapplied_flags(args, parser)
if args.target:
# Named once, by the name the target is filed under: every artifact
# name below derives from it.
args.target = canonical_target_name(
[args.platform]
if args.platform
else list_registered_platforms(args.platforms_dir, include_archived=True),
args.target,
args.platforms_dir,
)
# Quick-exit modes: --verify-packs alone = verify existing packs only
# Combined with --all-variants, generation runs first then verify
+58
View File
@@ -0,0 +1,58 @@
"""A hardware target names its artifacts by the name it is filed under.
`switch`, `nx` and `nintendo-switch` are one RetroArch target. The tag came
from the name as typed, so one target gave three pack and manifest names,
and `--verify-packs --target nx` looked for a pack nobody had built.
"""
from __future__ import annotations
import subprocess
import sys
import tempfile
import unittest
from pathlib import Path
REPO_ROOT = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(REPO_ROOT / "scripts"))
from common import canonical_target_name # noqa: E402
class AliasesResolveToOneName(unittest.TestCase):
def test_retroarch_switch_aliases(self):
platforms = str(REPO_ROOT / "platforms")
for typed in ("switch", "nx", "nintendo-switch"):
with self.subTest(typed=typed):
self.assertEqual(
canonical_target_name(["retroarch"], typed, platforms),
"nintendo-switch",
)
def test_an_unknown_name_is_left_for_the_target_check(self):
self.assertEqual(
canonical_target_name(["retroarch"], "bogus", str(REPO_ROOT / "platforms")),
"bogus",
)
class TheBuilderNamesByTheCanonicalTarget(unittest.TestCase):
def test_an_alias_writes_the_canonical_manifest(self):
if not (REPO_ROOT / "database.json").exists():
self.skipTest("database.json is not built")
(REPO_ROOT / "tmp").mkdir(exist_ok=True)
with tempfile.TemporaryDirectory(dir=REPO_ROOT / "tmp") as out:
proc = subprocess.run(
[sys.executable, "scripts/generate_pack.py", "--platform", "retroarch",
"--target", "nx", "--manifest", "--offline", "--output-dir", out],
cwd=REPO_ROOT, capture_output=True, text=True, timeout=600, check=False,
)
self.assertEqual(proc.returncode, 0, proc.stderr)
self.assertEqual(
sorted(p.name for p in Path(out).glob("*.json")),
["retroarch_nintendoswitch.json"],
)
if __name__ == "__main__":
unittest.main()