mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-11-12 04:53:52 -06:00
feat: carry the board list in the pack
This commit is contained in:
1 parent
8d86b7b4f3
commit
ddafc2ff42
7 files changed
+238
-93
No files matched your search
+80
-64
@@ -2273,67 +2273,7 @@ def generate_target_manifests(targets_dir: str, output_dir: str) -> None:
|
||||
for yml_file in sorted(targets_path.glob("*.yml")):
|
||||
if yml_file.name.startswith("_"):
|
||||
continue
|
||||
with open(yml_file) as f:
|
||||
data = yaml_load(f) or {}
|
||||
targets = data.get("targets", {})
|
||||
if not isinstance(targets, dict):
|
||||
raise ValueError(f"{yml_file}: targets must be a mapping")
|
||||
|
||||
# The pack builder accepts the aliases declared in _overrides.yml, so
|
||||
# --target switch works there. Emitting only canonical names left the
|
||||
# installer rejecting the same word and, worse, carrying on with every
|
||||
# file instead: the user asked for a filter and got the full pack.
|
||||
overrides_path = targets_path / "_overrides.yml"
|
||||
alias_map: dict[str, list[str]] = {}
|
||||
platform_overrides: dict = {}
|
||||
if overrides_path.is_file():
|
||||
with open(overrides_path) as f:
|
||||
all_overrides = yaml_load(f) or {}
|
||||
platform_overrides = (
|
||||
all_overrides.get(yml_file.stem, {}).get("targets", {}) or {}
|
||||
)
|
||||
for tname, ovr in platform_overrides.items():
|
||||
names = [a for a in (ovr or {}).get("aliases", []) if isinstance(a, str)]
|
||||
if names:
|
||||
alias_map[tname] = names
|
||||
|
||||
result: dict[str, list[str] | None] = {}
|
||||
for target_name, target_info in targets.items():
|
||||
if not isinstance(target_name, str) or not target_name:
|
||||
raise ValueError(f"{yml_file}: target names must be non-empty strings")
|
||||
if not isinstance(target_info, dict):
|
||||
raise ValueError(f"{yml_file}: target {target_name!r} must be a mapping")
|
||||
cores = target_info.get("cores")
|
||||
if cores is None:
|
||||
result[target_name] = None
|
||||
continue
|
||||
if (
|
||||
not isinstance(cores, list)
|
||||
or any(not isinstance(core, str) or not core for core in cores)
|
||||
or len(cores) != len(set(cores))
|
||||
):
|
||||
raise ValueError(
|
||||
f"{yml_file}: target {target_name!r} cores must be unique "
|
||||
"non-empty strings"
|
||||
)
|
||||
# The builder's own reading, overrides included: a list published
|
||||
# another way makes the installer serve what the pack does not.
|
||||
# An empty list is a board with no core, not one with every core.
|
||||
resolved = load_target_config(
|
||||
yml_file.stem, target_name, str(targets_path.parent)
|
||||
)
|
||||
result[target_name] = None if resolved is None else sorted(resolved)
|
||||
|
||||
for target_name, names in alias_map.items():
|
||||
if target_name not in result:
|
||||
continue
|
||||
for alias in names:
|
||||
if alias in result:
|
||||
raise ValueError(
|
||||
f"{yml_file}: alias {alias!r} collides with a target name"
|
||||
)
|
||||
result[alias] = result[target_name]
|
||||
|
||||
result = target_list(yml_file)
|
||||
out_path = Path(output_dir) / f"{yml_file.stem}.json"
|
||||
write_text_atomic(out_path, json.dumps(result, indent=2, sort_keys=True) + "\n")
|
||||
count += 1
|
||||
@@ -2341,6 +2281,73 @@ def generate_target_manifests(targets_dir: str, output_dir: str) -> None:
|
||||
print(f"Generated {count} target manifest(s) in {output_dir}")
|
||||
|
||||
|
||||
def target_list(yml_file: Path) -> dict[str, list[str] | None]:
|
||||
"""A platform's cores per hardware target, as install/targets/ publishes
|
||||
them and a pack carries them: aliases included, overrides applied."""
|
||||
targets_path = yml_file.parent
|
||||
with open(yml_file) as f:
|
||||
data = yaml_load(f) or {}
|
||||
targets = data.get("targets", {})
|
||||
if not isinstance(targets, dict):
|
||||
raise ValueError(f"{yml_file}: targets must be a mapping")
|
||||
|
||||
# The pack builder accepts the aliases declared in _overrides.yml, so
|
||||
# --target switch works there. Emitting only canonical names left the
|
||||
# installer rejecting the same word and, worse, carrying on with every
|
||||
# file instead: the user asked for a filter and got the full pack.
|
||||
overrides_path = targets_path / "_overrides.yml"
|
||||
alias_map: dict[str, list[str]] = {}
|
||||
platform_overrides: dict = {}
|
||||
if overrides_path.is_file():
|
||||
with open(overrides_path) as f:
|
||||
all_overrides = yaml_load(f) or {}
|
||||
platform_overrides = (
|
||||
all_overrides.get(yml_file.stem, {}).get("targets", {}) or {}
|
||||
)
|
||||
for tname, ovr in platform_overrides.items():
|
||||
names = [a for a in (ovr or {}).get("aliases", []) if isinstance(a, str)]
|
||||
if names:
|
||||
alias_map[tname] = names
|
||||
|
||||
result: dict[str, list[str] | None] = {}
|
||||
for target_name, target_info in targets.items():
|
||||
if not isinstance(target_name, str) or not target_name:
|
||||
raise ValueError(f"{yml_file}: target names must be non-empty strings")
|
||||
if not isinstance(target_info, dict):
|
||||
raise ValueError(f"{yml_file}: target {target_name!r} must be a mapping")
|
||||
cores = target_info.get("cores")
|
||||
if cores is None:
|
||||
result[target_name] = None
|
||||
continue
|
||||
if (
|
||||
not isinstance(cores, list)
|
||||
or any(not isinstance(core, str) or not core for core in cores)
|
||||
or len(cores) != len(set(cores))
|
||||
):
|
||||
raise ValueError(
|
||||
f"{yml_file}: target {target_name!r} cores must be unique "
|
||||
"non-empty strings"
|
||||
)
|
||||
# The builder's own reading, overrides included: a list published
|
||||
# another way makes the installer serve what the pack does not.
|
||||
# An empty list is a board with no core, not one with every core.
|
||||
resolved = load_target_config(
|
||||
yml_file.stem, target_name, str(targets_path.parent)
|
||||
)
|
||||
result[target_name] = None if resolved is None else sorted(resolved)
|
||||
|
||||
for target_name, names in alias_map.items():
|
||||
if target_name not in result:
|
||||
continue
|
||||
for alias in names:
|
||||
if alias in result:
|
||||
raise ValueError(
|
||||
f"{yml_file}: alias {alias!r} collides with a target name"
|
||||
)
|
||||
result[alias] = result[target_name]
|
||||
return result
|
||||
|
||||
|
||||
def _resolve_systems(args: argparse.Namespace, parser: argparse.ArgumentParser) -> None:
|
||||
"""Turn --system into the platform's system ids, before any work.
|
||||
|
||||
@@ -2930,6 +2937,7 @@ def _run_platform_packs(
|
||||
# The install list of the same choices names each file's
|
||||
# systems: the pack records them, so a pack alone (a
|
||||
# handheld without Wi-Fi) can be narrowed by system.
|
||||
board_list = Path(args.platforms_dir) / "targets" / f"{representative}.yml"
|
||||
systems_for[os.path.basename(zip_path)] = pack_systems(generate_manifest(
|
||||
representative, args.platforms_dir, db, args.bios_dir,
|
||||
registry_path, emulators_dir=args.emulators_dir,
|
||||
@@ -2939,7 +2947,7 @@ def _run_platform_packs(
|
||||
offline=args.offline, required_only=required_only,
|
||||
data_registry=data_registry,
|
||||
no_game_data=getattr(args, "no_game_data", False),
|
||||
))
|
||||
), target_list(board_list) if board_list.is_file() else None)
|
||||
|
||||
print("\nVerifying packs and generating manifests...")
|
||||
skip_conf = bool(system_filter or args.split)
|
||||
@@ -4770,7 +4778,7 @@ def _manifest_core_index(
|
||||
|
||||
|
||||
|
||||
def pack_systems(install_manifest: dict) -> dict:
|
||||
def pack_systems(install_manifest: dict, targets: dict | None = None) -> dict:
|
||||
"""What a pack's manifest.json records of its systems, from the install
|
||||
list built with the same choices: each file's systems, by its path in
|
||||
the pack, and the names a person reads for them.
|
||||
@@ -4778,6 +4786,11 @@ def pack_systems(install_manifest: dict) -> dict:
|
||||
A pack recorded none: the installer refused --system with a pack alone
|
||||
("the file list comes from an older release") and offered no Choose
|
||||
systems, the route of a handheld without Wi-Fi.
|
||||
|
||||
The install list itself and the platform's cores per board (targets, as
|
||||
install/targets/ publishes them) ride along: with the pack alone, a
|
||||
board was never applied and --target was refused, and a Batocera RPi4
|
||||
card took 8.9 GB where its board reads 5.8.
|
||||
"""
|
||||
files = install_manifest.get("files", [])
|
||||
entries = [*files, *install_manifest.get("omitted_files", [])]
|
||||
@@ -4803,6 +4816,9 @@ def pack_systems(install_manifest: dict) -> dict:
|
||||
# the one the machine runs when it has the pack alone.
|
||||
if install_manifest.get("version"):
|
||||
systems["list_version"] = install_manifest["version"]
|
||||
systems["install_list"] = install_manifest
|
||||
if targets is not None:
|
||||
systems["targets"] = targets
|
||||
return systems
|
||||
|
||||
|
||||
@@ -4818,7 +4834,7 @@ def annotate_pack_systems(manifest: dict, systems: dict | None) -> None:
|
||||
for key in ("system_titles", "system_names"):
|
||||
if systems.get(key):
|
||||
manifest[key] = systems[key]
|
||||
for key in ("list_records", "list_version"):
|
||||
for key in ("list_records", "list_version", "install_list", "targets"):
|
||||
if key in systems:
|
||||
manifest[key] = systems[key]
|
||||
|
||||
|
||||
Reference in new issue
Block a user