mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-10-11 05:53:23 -05:00
refactor: one upstream name index for core lookups
This commit is contained in:
1 parent
994836938c
commit
ca86236c12
6 files changed
+121
-42
No files matched your search
+14
-11
@@ -54,6 +54,7 @@ import upstream # noqa: E402
|
||||
from common import ( # noqa: E402
|
||||
list_registered_platforms,
|
||||
load_emulator_profiles,
|
||||
upstream_profile_index,
|
||||
yaml_load,
|
||||
)
|
||||
from exporter import discover_exporters # noqa: E402
|
||||
@@ -364,14 +365,9 @@ def check_native(platforms_dir: Path, cache_dir: Path, truth_dir: Path) -> list[
|
||||
# --- targets ----------------------------------------------------------------
|
||||
|
||||
|
||||
def profile_name_index(profiles: dict[str, dict]) -> dict[str, str]:
|
||||
"""Upstream core name -> profile key, the index target filtering uses."""
|
||||
index: dict[str, str] = {}
|
||||
for key, profile in profiles.items():
|
||||
index.setdefault(key, key)
|
||||
for alias in profile.get("cores") or []:
|
||||
index.setdefault(str(alias), key)
|
||||
return index
|
||||
def profile_name_index(profiles: dict[str, dict]) -> dict[str, set[str]]:
|
||||
"""Upstream core name -> the profiles that claim it, as target filtering reads it."""
|
||||
return upstream_profile_index(profiles, include_aliases=True)
|
||||
|
||||
|
||||
def _removed_cores(overrides: dict, platform: str) -> dict[str, set[str]]:
|
||||
@@ -539,13 +535,20 @@ def coreinfo_gaps(
|
||||
Matching folds case: the buildbot serves lower-case names while a few
|
||||
.info files keep the project's own casing.
|
||||
"""
|
||||
index = {k.casefold(): v for k, v in profile_name_index(profiles).items()}
|
||||
index: dict[str, set[str]] = {}
|
||||
for key, claimants in profile_name_index(profiles).items():
|
||||
index.setdefault(key.casefold(), set()).update(claimants)
|
||||
unprofiled = [n for n in names if n.casefold() not in index]
|
||||
# A name only standalone profiles claim: libretro now builds a core
|
||||
# nothing in the collection describes as one.
|
||||
standalone = [
|
||||
(n, index[n.casefold()])
|
||||
(n, sorted(index[n.casefold()])[0])
|
||||
for n in names
|
||||
if n.casefold() in index
|
||||
and str(profiles[index[n.casefold()]].get("type", "")).strip() == "standalone"
|
||||
and all(
|
||||
str(profiles[c].get("type", "")).strip() == "standalone"
|
||||
for c in index[n.casefold()]
|
||||
)
|
||||
]
|
||||
return unprofiled, standalone
|
||||
|
||||
|
||||
+44
-21
@@ -1298,6 +1298,36 @@ def runs_standalone(
|
||||
)
|
||||
|
||||
|
||||
def upstream_profile_index(
|
||||
profiles: dict[str, dict], include_aliases: bool = False
|
||||
) -> dict[str, set[str]]:
|
||||
"""Every name a core is known by upstream -> the profiles that claim it.
|
||||
|
||||
A name can be claimed twice: the buildbot's `pcsx2` is the LRPS2 core,
|
||||
which lrps2.yml lists in `cores:`, and also the key of the standalone
|
||||
pcsx2 profile. A last-wins dict kept one of the two depending on file
|
||||
order, and a RetroArch target filter dropped LRPS2's files. Callers
|
||||
choose: a platform list prefers the exact key, a target filter keeps
|
||||
every claimant.
|
||||
"""
|
||||
index: dict[str, set[str]] = {}
|
||||
for name, profile in profiles.items():
|
||||
if not include_aliases and profile.get("type") == "alias":
|
||||
continue
|
||||
index.setdefault(name, set()).add(name)
|
||||
for core in profile.get("cores") or []:
|
||||
index.setdefault(str(core), set()).add(name)
|
||||
return index
|
||||
|
||||
|
||||
def preferred_profile(index: dict[str, set[str]], name: str) -> str | None:
|
||||
"""The profile a name designates: its own key first, else the first claimant."""
|
||||
claimants = index.get(name)
|
||||
if not claimants:
|
||||
return None
|
||||
return name if name in claimants else sorted(claimants)[0]
|
||||
|
||||
|
||||
def resolve_platform_cores(
|
||||
config: dict,
|
||||
profiles: dict[str, dict],
|
||||
@@ -1323,14 +1353,12 @@ def resolve_platform_cores(
|
||||
}
|
||||
elif isinstance(cores_config, list):
|
||||
core_set = {str(c) for c in cores_config}
|
||||
core_to_profile: dict[str, str] = {}
|
||||
for name, p in profiles.items():
|
||||
if p.get("type") == "alias":
|
||||
continue
|
||||
core_to_profile[name] = name
|
||||
for core_name in p.get("cores", []):
|
||||
core_to_profile[str(core_name)] = name
|
||||
result = {core_to_profile[c] for c in core_set if c in core_to_profile}
|
||||
index = upstream_profile_index(profiles)
|
||||
result = {
|
||||
profile
|
||||
for c in core_set
|
||||
if (profile := preferred_profile(index, c)) is not None
|
||||
}
|
||||
# Support "all_libretro" as a list element: combines all libretro
|
||||
# profiles with explicitly listed standalone cores (e.g. RetroDECK
|
||||
# ships RetroArch + standalone emulators)
|
||||
@@ -1355,13 +1383,10 @@ def resolve_platform_cores(
|
||||
# Upstream sources (buildbot, es_systems) may use different names
|
||||
# than our profile keys (e.g., mednafen_psx vs beetle_psx).
|
||||
# The profiles' cores: field lists these alternate names.
|
||||
upstream_to_profile: dict[str, str] = {}
|
||||
for name, p in profiles.items():
|
||||
upstream_to_profile[name] = name
|
||||
for alias in p.get("cores", []):
|
||||
upstream_to_profile[str(alias)] = name
|
||||
# Expand target_cores to profile keys
|
||||
expanded = {upstream_to_profile.get(c, c) for c in target_cores}
|
||||
index = upstream_profile_index(profiles, include_aliases=True)
|
||||
expanded = {
|
||||
profile for c in target_cores for profile in index.get(c, {c})
|
||||
}
|
||||
result = result & expanded
|
||||
return result
|
||||
|
||||
@@ -1467,12 +1492,10 @@ def filter_systems_by_target(
|
||||
return systems
|
||||
|
||||
# Build reverse index for target core name resolution
|
||||
upstream_to_profile: dict[str, str] = {}
|
||||
for name, p in profiles.items():
|
||||
upstream_to_profile[name] = name
|
||||
for alias in p.get("cores", []):
|
||||
upstream_to_profile[str(alias)] = name
|
||||
expanded_target = {upstream_to_profile.get(c, c) for c in target_cores}
|
||||
index = upstream_profile_index(profiles, include_aliases=True)
|
||||
expanded_target = {
|
||||
profile for c in target_cores for profile in index.get(c, {c})
|
||||
}
|
||||
|
||||
_norm_sid = _norm_system_id
|
||||
|
||||
|
||||
@@ -38,8 +38,10 @@ from common import (
|
||||
load_emulator_profiles,
|
||||
load_provenance_snapshots,
|
||||
parse_md5_list,
|
||||
preferred_profile,
|
||||
require_yaml,
|
||||
unique_emulator_profiles,
|
||||
upstream_profile_index,
|
||||
write_if_changed as _write_artifact,
|
||||
yaml_load,
|
||||
)
|
||||
@@ -3116,11 +3118,11 @@ def generate_cross_reference(
|
||||
k: v for k, v in profiles.items() if v.get("type") not in ("alias", "test")
|
||||
}
|
||||
|
||||
# Build core -> profile lookup by core name
|
||||
core_to_profile: dict[str, str] = {}
|
||||
for pname, p in unique.items():
|
||||
for core in p.get("cores", [pname]):
|
||||
core_to_profile[str(core)] = pname
|
||||
# Core name -> the profile it designates, the rule target filtering uses.
|
||||
index = upstream_profile_index(unique)
|
||||
core_to_profile: dict[str, str] = {
|
||||
core: preferred_profile(index, core) for core in index
|
||||
}
|
||||
|
||||
total_cores = len(unique)
|
||||
total_upstreams = len({
|
||||
|
||||
Reference in new issue
Block a user