mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-10-10 21:43:23 -05:00
fix: read the build mode per emulator when arbitrating
This commit is contained in:
1 parent
da04df6d6f
commit
7b93285e1d
4 files changed
+123
-8
No files matched your search
@@ -616,7 +616,11 @@ def generate_pack(
|
||||
# emulator's file satisfies both sides and nothing is traded away.
|
||||
mode = config.get("verification_mode", "existence")
|
||||
for conflict in slots.find_conflicts(
|
||||
config, platform_profiles, db, base_dest
|
||||
config,
|
||||
platform_profiles,
|
||||
db,
|
||||
base_dest,
|
||||
{str(c) for c in config.get("standalone_cores", [])},
|
||||
):
|
||||
decision = slots.arbitrate(conflict, mode)
|
||||
if decision.serves_both and decision.winner.local_path:
|
||||
|
||||
+41
-6
@@ -112,17 +112,42 @@ def platform_claims(config: dict, db: dict, base_dest: str = "") -> list[Claim]:
|
||||
|
||||
|
||||
def profile_claims(
|
||||
profiles: dict, db: dict, base_dest: str = ""
|
||||
profiles: dict,
|
||||
db: dict,
|
||||
base_dest: str = "",
|
||||
standalone_cores: set[str] | None = None,
|
||||
) -> list[Claim]:
|
||||
"""What each emulator profile says belongs at each destination it names."""
|
||||
"""What each emulator profile says belongs at each destination it names.
|
||||
|
||||
A file can exist in one build of an emulator and not the other, and the
|
||||
two builds read from different directories. The mode is decided per
|
||||
emulator, not per pack: a platform runs some of its emulators as libretro
|
||||
cores and others standalone, naming the latter in ``standalone_cores``.
|
||||
An entry the standalone build alone loads does not address a platform
|
||||
running that emulator as a core, and where it does, the destination is
|
||||
``standalone_path``. This is the gate verify already applies.
|
||||
"""
|
||||
standalone_cores = standalone_cores or set()
|
||||
claims: list[Claim] = []
|
||||
for emu_name, profile in sorted(profiles.items()):
|
||||
if profile.get("type") in ("launcher", "alias"):
|
||||
continue
|
||||
is_standalone = emu_name in standalone_cores or bool(
|
||||
standalone_cores & {str(c) for c in profile.get("cores", [])}
|
||||
)
|
||||
for entry in profile.get("files") or []:
|
||||
if not isinstance(entry, dict):
|
||||
continue
|
||||
dest = entry.get("path") or entry.get("name") or ""
|
||||
entry_mode = entry.get("mode")
|
||||
if entry_mode == "standalone" and not is_standalone:
|
||||
continue
|
||||
if entry_mode == "libretro" and is_standalone:
|
||||
continue
|
||||
dest = (
|
||||
(entry.get("standalone_path") or entry.get("path"))
|
||||
if is_standalone
|
||||
else entry.get("path")
|
||||
) or entry.get("name") or ""
|
||||
if not dest:
|
||||
continue
|
||||
full = f"{base_dest}/{dest}" if base_dest else dest
|
||||
@@ -142,7 +167,11 @@ def profile_claims(
|
||||
|
||||
|
||||
def find_conflicts(
|
||||
config: dict, profiles: dict, db: dict, base_dest: str = ""
|
||||
config: dict,
|
||||
profiles: dict,
|
||||
db: dict,
|
||||
base_dest: str = "",
|
||||
standalone_cores: set[str] | None = None,
|
||||
) -> list[Conflict]:
|
||||
"""Destinations where a proven profile claim contradicts what ships.
|
||||
|
||||
@@ -158,7 +187,7 @@ def find_conflicts(
|
||||
# is agreement, not contradiction. Only a destination where no profile
|
||||
# claim at all matches what ships is a disagreement.
|
||||
by_slot: dict[str, list[Claim]] = {}
|
||||
for claim in profile_claims(profiles, db, base_dest):
|
||||
for claim in profile_claims(profiles, db, base_dest, standalone_cores):
|
||||
key = _normalize(claim.destination)
|
||||
platform = by_dest.get(key)
|
||||
if platform is None or not platform.is_proven or not claim.is_proven:
|
||||
@@ -334,7 +363,13 @@ def scan_platform(
|
||||
config = load_platform_config(platform, platforms_dir)
|
||||
keys = resolve_platform_cores(config, profiles)
|
||||
relevant = {k: profiles[k] for k in keys if k in profiles}
|
||||
return find_conflicts(config, relevant, db, config.get("base_destination", ""))
|
||||
return find_conflicts(
|
||||
config,
|
||||
relevant,
|
||||
db,
|
||||
config.get("base_destination", ""),
|
||||
{str(c) for c in config.get("standalone_cores", [])},
|
||||
)
|
||||
|
||||
|
||||
def main() -> int:
|
||||
|
||||
+7
-1
@@ -804,7 +804,13 @@ def verify_platform(
|
||||
name: emu_profiles[name]
|
||||
for name in resolve_platform_cores(config, emu_profiles)
|
||||
}
|
||||
for conflict in slots.find_conflicts(config, arbitrated, db, base_dest):
|
||||
for conflict in slots.find_conflicts(
|
||||
config,
|
||||
arbitrated,
|
||||
db,
|
||||
base_dest,
|
||||
{str(c) for c in config.get("standalone_cores", [])},
|
||||
):
|
||||
decision = slots.arbitrate(conflict, mode)
|
||||
if decision.serves_both and decision.winner.local_path:
|
||||
key = conflict.destination
|
||||
|
||||
@@ -318,6 +318,76 @@ class TestSelfContradictingDestinations(unittest.TestCase):
|
||||
self.assertIn("JAP/IPL.bin", line)
|
||||
|
||||
|
||||
class TestBuildModeDecidesWhoClaims(unittest.TestCase):
|
||||
"""A platform runs some emulators as cores and others standalone."""
|
||||
|
||||
def _config(self, standalone=None) -> dict:
|
||||
config = {
|
||||
"systems": {
|
||||
"console": {
|
||||
"files": [
|
||||
{"name": "IPL.bin", "destination": "GC/JAP/IPL.bin",
|
||||
"md5": "m" * 32}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
if standalone:
|
||||
config["standalone_cores"] = standalone
|
||||
return config
|
||||
|
||||
def _profile(self, mode=None, standalone_path=None) -> dict:
|
||||
entry = {"name": "IPL.bin", "path": "GC/JAP/IPL.bin"}
|
||||
if mode:
|
||||
entry["mode"] = mode
|
||||
if standalone_path:
|
||||
entry["standalone_path"] = standalone_path
|
||||
return {"ares": {"cores": ["ares"], "files": [entry]}}
|
||||
|
||||
def test_a_standalone_only_file_does_not_claim_a_core_slot(self):
|
||||
conflicts = slots.find_conflicts(
|
||||
self._config(), self._profile(mode="standalone"), REGIONS_DB
|
||||
)
|
||||
self.assertEqual(conflicts, [])
|
||||
|
||||
def test_it_claims_when_the_platform_runs_that_emulator_standalone(self):
|
||||
conflicts = slots.find_conflicts(
|
||||
self._config(standalone=["ares"]),
|
||||
self._profile(mode="standalone"),
|
||||
REGIONS_DB,
|
||||
standalone_cores={"ares"},
|
||||
)
|
||||
self.assertEqual(len(conflicts), 1)
|
||||
|
||||
def test_a_libretro_only_file_is_silent_in_standalone_mode(self):
|
||||
conflicts = slots.find_conflicts(
|
||||
self._config(standalone=["ares"]),
|
||||
self._profile(mode="libretro"),
|
||||
REGIONS_DB,
|
||||
standalone_cores={"ares"},
|
||||
)
|
||||
self.assertEqual(conflicts, [])
|
||||
|
||||
def test_standalone_mode_reads_the_standalone_destination(self):
|
||||
claims = slots.profile_claims(
|
||||
self._profile(standalone_path="elsewhere/IPL.bin"),
|
||||
REGIONS_DB,
|
||||
standalone_cores={"ares"},
|
||||
)
|
||||
self.assertEqual(claims[0].destination, "elsewhere/IPL.bin")
|
||||
|
||||
def test_the_mode_follows_a_core_alias_not_only_the_profile_name(self):
|
||||
profile = {"ares_core": {"cores": ["ares"],
|
||||
"files": [{"name": "IPL.bin",
|
||||
"path": "GC/JAP/IPL.bin",
|
||||
"mode": "standalone"}]}}
|
||||
conflicts = slots.find_conflicts(
|
||||
self._config(standalone=["ares"]), profile, REGIONS_DB,
|
||||
standalone_cores={"ares"},
|
||||
)
|
||||
self.assertEqual(len(conflicts), 1)
|
||||
|
||||
|
||||
class TestProvenEvidence(unittest.TestCase):
|
||||
"""What counts as proof that a claim is about content, not about a name."""
|
||||
|
||||
|
||||
Reference in new issue
Block a user