fix: group core files under their pack path

On a platform that writes bios/ in front of its destinations (RetroDECK, AmberELEC, EmuELEC), a core extra was grouped, dropped and held under its bare destination while the platform's declaration of the same file used bios/<name>. Beetle PSX's scph5501.bin was kept by the --region japan pack while the declaration was dropped and the installer dropped the path. extra_region_key keys every extra with the platform's declared root, in the builder, the manifest selection, verify's replay and the omissions. The same key gives the declared entries the systems of the core files at their path: every --system case of RetroDECK differed between pack and installer before, none does now.
This commit is contained in:
Abdessamad Derraz committed 2026-11-06 09:00:06 +01:00
1 parent 8aa1a5fdad
commit 4efcb3da64
11 files changed
+2113 -19

No files matched your search

+14 -7
View File
@@ -1250,7 +1250,7 @@ def generate_pack(
if required_only and fe.get("required") is False:
continue
dest = sanitize_pack_path(fe.get("destination", fe["name"]))
if region_drops and dest in region_drops:
if region_drops and extra_region_key(fe, declared_root(config)) in region_drops:
continue
if not dest:
continue
@@ -4168,7 +4168,8 @@ def _manifest_core_entries(
dest = sanitize_pack_path(fe.get("destination", fe["name"]))
if not dest:
continue
if region_drops and dest in region_drops:
region_key = extra_region_key(fe, declared_root(config))
if region_drops and region_key in region_drops:
continue
full_dest = extra_full_destination(fe, extras_pfx)
if not full_dest:
@@ -4242,7 +4243,7 @@ def _manifest_core_entries(
entry, file_size = _manifest_entry(
local_path, manifest_dest, [source_emu] if source_emu else [],
db, repo_root,
selection.fields(dest, fe.get("name", "")),
selection.fields(region_key, fe.get("name", "")),
)
if entry is not None and save_root:
entry.update(save_entry_fields(fe))
@@ -4356,7 +4357,8 @@ def _manifest_selection(
else set()
)
return drops, SelectionIndex.build(
region_groups, region_index, pack_systems, extras, required_only
region_groups, region_index, pack_systems, extras, required_only,
extras_prefix=declared_root(config),
), held
@@ -4381,7 +4383,9 @@ def _record_absent(
if required_only and fe.get("required") is False:
continue
dest = sanitize_pack_path(fe.get("destination", fe.get("name", "")))
if not dest or (region_drops and dest in region_drops):
if not dest or (
region_drops and extra_region_key(fe, declared_root(config)) in region_drops
):
continue
full_dest = extra_full_destination(fe, extras_pfx)
if not full_dest:
@@ -4576,8 +4580,10 @@ def generate_manifest(
reason: str,
cores: list[str] | None,
) -> None:
bare = sanitize_pack_path(
file_entry.get("destination", file_entry.get("name", ""))
# A core extra (cores given) is keyed as the region pass keys it.
bare = (
sanitize_pack_path(file_entry.get("destination", file_entry.get("name", "")))
if cores is None else extra_region_key(file_entry, declared_root(config))
)
save_root = file_entry.get("root") == "save"
omitted_by_destination[full_destination] = {
@@ -5464,6 +5470,7 @@ from packpaths import ( # noqa: E402,F401
from packextras import ( # noqa: E402,F401
ExtraResolver,
extra_full_destination,
extra_region_key,
prefixed_destination,
save_entry_fields,
save_manifest_dest,
+10 -2
View File
@@ -19,7 +19,13 @@ from dataclasses import dataclass
import region as region_mod
from common import _norm_system_id, sanitize_pack_path
from packextras import _kept, _serving_system_ids, extra_region_groups, system_spellings
from packextras import (
_kept,
_serving_system_ids,
extra_region_groups,
extra_region_key,
system_spellings,
)
def _dest(entry: dict) -> str:
@@ -44,6 +50,7 @@ class SelectionIndex:
pack_systems: dict[str, dict],
extras: list[dict],
required_only: bool = False,
extras_prefix: str = "",
) -> SelectionIndex:
by_norm: dict[str, set[str]] = {}
for sys_id in pack_systems:
@@ -60,7 +67,8 @@ class SelectionIndex:
extra_groups: dict[str, set[str]] = {}
spellings = system_spellings(pack_systems)
for extra in extras:
dest = _dest(extra)
# Keyed as platform_region_groups keys it (extra_region_key).
dest = extra_region_key(extra, extras_prefix)
if not dest:
continue
extra_groups.setdefault(dest, set()).update(
+18 -2
View File
@@ -62,6 +62,20 @@ def prefixed_destination(dest: str, prefix: str) -> str:
return f"{prefix}/{dest}"
def extra_region_key(fe: dict, prefix: str) -> str:
"""The key a core extra is grouped, dropped and held under by --region.
Its destination with the BIOS directory the platform writes in front of
its own (declared_root): RetroDECK declares bios/scph5501.bin, and
Beetle PSX's scph5501.bin grouped bare was looked up under another key,
kept by the pack while the declaration of the same file was dropped,
and the installer, which records the path once, dropped it.
"""
return prefixed_destination(
sanitize_pack_path(fe.get("destination", fe.get("name", ""))), prefix
)
def save_entry_fields(fe: dict) -> dict:
"""What a manifest entry adds for a file read below the save directory.
@@ -364,6 +378,7 @@ def hidden_extras(
content[dest.lower()] = sha1_by_path.get(local)
lower = set(content) if case_insensitive else set()
prefix = _detect_extras_prefix(config, base_dest)
region_prefix = declared_root(config)
hidden: dict[tuple[str, str, str], str] = {}
packed_keys: set[tuple[str, str, str]] = set()
extras = _collect_emulator_extras(
@@ -377,7 +392,7 @@ def hidden_extras(
if required_only and fe.get("required") is False:
continue
dest = sanitize_pack_path(fe.get("destination", fe.get("name", "")))
if not dest or (region_drops and dest in region_drops):
if not dest or (region_drops and extra_region_key(fe, region_prefix) in region_drops):
continue
full = extra_full_destination(fe, prefix)
if not full:
@@ -1705,8 +1720,9 @@ def platform_region_groups(
)
held = {id(extra) for extra in extras}
spellings = system_spellings(systems)
region_prefix = declared_root(config)
for extra in _kept(extras + absent, required_only):
dest = sanitize_pack_path(extra.get("destination", extra.get("name", "")))
dest = extra_region_key(extra, region_prefix)
if not dest:
continue
name = extra.get("name", "")