mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-11-06 01:53:56 -06:00
fix: platform entries skip other emulators' trees
A platform entry names no profile, so bios/Other/<emulator>/ was never foreign to it. EmuELEC's ports/VVVVVV/data.zip resolved to xrick's data.zip, then to xrick's data directory copy. A system that lists its cores now takes no name match only another emulator's tree answers.
This commit is contained in:
1 parent
35ad19ff02
commit
402e688b01
4 files changed
+122
-20
No files matched your search
+17
-17
@@ -20,11 +20,11 @@
|
||||
}
|
||||
],
|
||||
"standalone_copies": [],
|
||||
"total_files": 5297,
|
||||
"total_size": 4143074421,
|
||||
"pack_files": 9169,
|
||||
"pack_size": 4257242836,
|
||||
"total_omitted": 197,
|
||||
"total_files": 5296,
|
||||
"total_size": 4141616981,
|
||||
"pack_files": 9168,
|
||||
"pack_size": 4255785396,
|
||||
"total_omitted": 198,
|
||||
"omitted_files": [
|
||||
{
|
||||
"dest": "FB Alpha 2012/hiscore.dat",
|
||||
@@ -2070,6 +2070,18 @@
|
||||
],
|
||||
"category": "game_data"
|
||||
},
|
||||
{
|
||||
"dest": "ports/VVVVVV/data.zip",
|
||||
"name": "data.zip",
|
||||
"system": "vvvvvv",
|
||||
"required": true,
|
||||
"reason": "not_found",
|
||||
"cores": null,
|
||||
"systems": [
|
||||
"vvvvvv"
|
||||
],
|
||||
"category": "game_data"
|
||||
},
|
||||
{
|
||||
"dest": "ports/diablo/diabdat.mpq",
|
||||
"name": "diabdat.mpq",
|
||||
@@ -8911,18 +8923,6 @@
|
||||
],
|
||||
"category": "game_data"
|
||||
},
|
||||
{
|
||||
"dest": "ports/VVVVVV/data.zip",
|
||||
"sha1": "ecfc092fe6371dbf38e238a8ba5f90785b5db52d",
|
||||
"sha256": "2a86458696e83eb924fc6c6fda3ca5d320ca90885bd6c2f32d121757ade389bb",
|
||||
"size": 1457440,
|
||||
"repo_path": "bios/Other/xrick/data.zip",
|
||||
"cores": null,
|
||||
"systems": [
|
||||
"vvvvvv"
|
||||
],
|
||||
"category": "game_data"
|
||||
},
|
||||
{
|
||||
"dest": "ports/xrick/data.zip",
|
||||
"sha1": "ecfc092fe6371dbf38e238a8ba5f90785b5db52d",
|
||||
|
||||
+32
-1
@@ -424,11 +424,24 @@ def load_platform_config(platform_name: str, platforms_dir: str = "platforms") -
|
||||
|
||||
# Each entry carries the system that declares it: a hashless name match is
|
||||
# narrowed to the maker folder that system names (resolve_local_file).
|
||||
# A system that names its own cores (EmuELEC, AmberELEC, KNULLI) also
|
||||
# passes them on, so another emulator's tree is foreign to its entries.
|
||||
# Fresh dicts, since a YAML anchor can share one entry between systems.
|
||||
config["systems"] = {
|
||||
sys_id: {
|
||||
**system,
|
||||
"files": [{**f, "platform_system": sys_id} for f in system["files"]],
|
||||
"files": [
|
||||
{
|
||||
**f,
|
||||
"platform_system": sys_id,
|
||||
**(
|
||||
{"platform_cores": list(system["cores"])}
|
||||
if system.get("cores")
|
||||
else {}
|
||||
),
|
||||
}
|
||||
for f in system["files"]
|
||||
],
|
||||
}
|
||||
if isinstance(system, dict) and system.get("files")
|
||||
else system
|
||||
@@ -1735,6 +1748,24 @@ def resolve_local_file(
|
||||
continue
|
||||
if os.path.exists(path) and path not in candidates:
|
||||
candidates.append(path)
|
||||
# A platform entry names no profile, but a system that lists its
|
||||
# cores says whose files it asks for. A name only another emulator's
|
||||
# tree answers is no evidence, and the data directories hold those
|
||||
# emulators' trees too: EmuELEC's VVVVVV data.zip was served xrick's
|
||||
# archive of the same name, then xrick's data directory copy.
|
||||
core_owners = {
|
||||
token
|
||||
for core in file_entry.get("platform_cores") or ()
|
||||
for token in _affinity_tokens(str(core))
|
||||
}
|
||||
if (
|
||||
not owners
|
||||
and core_owners
|
||||
and candidates
|
||||
and all(_foreign_tree(p, core_owners) for p in candidates)
|
||||
):
|
||||
candidates = []
|
||||
unsourceable = True
|
||||
if makers and candidates:
|
||||
candidates = [p for p in candidates if not other_maker(p, makers, db)]
|
||||
if not candidates:
|
||||
|
||||
@@ -1035,13 +1035,18 @@ def _split_contract(config: dict) -> tuple[dict, dict]:
|
||||
"""
|
||||
allowed = _contract_keys()
|
||||
contract = {key: value for key, value in config.items() if key in allowed}
|
||||
# platform_system is the resolver's copy of the key each entry sits under.
|
||||
# platform_system and platform_cores are the resolver's copies of the key
|
||||
# each entry sits under and of that system's cores.
|
||||
if isinstance(contract.get("systems"), dict):
|
||||
contract["systems"] = {
|
||||
sys_id: {
|
||||
**system,
|
||||
"files": [
|
||||
{k: v for k, v in f.items() if k != "platform_system"}
|
||||
{
|
||||
k: v
|
||||
for k, v in f.items()
|
||||
if k not in ("platform_system", "platform_cores")
|
||||
}
|
||||
for f in system["files"]
|
||||
],
|
||||
}
|
||||
|
||||
@@ -148,6 +148,72 @@ class AbsentFileIsNotReplacedByAHomonym(unittest.TestCase):
|
||||
self.assertEqual(self._resolve(), (None, "not_found"))
|
||||
|
||||
|
||||
class APlatformEntryTakesNoOtherEmulatorsTree(unittest.TestCase):
|
||||
"""A platform declaration names no profile, so another emulator's tree
|
||||
was never foreign to it: EmuELEC's ports/VVVVVV/data.zip was served
|
||||
xrick's data.zip, Rick Dangerous sounds, then xrick's data directory
|
||||
copy. A system that lists its cores says whose files it asks for."""
|
||||
|
||||
def setUp(self):
|
||||
import tempfile
|
||||
|
||||
import generate_db
|
||||
|
||||
self._tmp = tempfile.TemporaryDirectory()
|
||||
self._cwd = os.getcwd()
|
||||
os.chdir(self._tmp.name)
|
||||
payload = b"rick dangerous"
|
||||
target = Path("bios/Other/xrick/data.zip")
|
||||
target.parent.mkdir(parents=True)
|
||||
target.write_bytes(payload)
|
||||
cache = Path("data/xrick/data.zip")
|
||||
cache.parent.mkdir(parents=True)
|
||||
cache.write_bytes(payload)
|
||||
sha1 = hashlib.sha1(payload).hexdigest()
|
||||
files = {sha1: {
|
||||
"path": str(target), "name": "data.zip", "size": len(payload),
|
||||
"sha1": sha1, "md5": hashlib.md5(payload).hexdigest(),
|
||||
"sha256": hashlib.sha256(payload).hexdigest(), "crc32": "0",
|
||||
}}
|
||||
self.db = {"files": files, "indexes": generate_db.build_indexes(files, {})}
|
||||
self.registry = {"xrick": {"local_cache": "data/xrick"}}
|
||||
|
||||
def tearDown(self):
|
||||
os.chdir(self._cwd)
|
||||
self._tmp.cleanup()
|
||||
|
||||
def _resolve(self, **fields):
|
||||
entry = {"name": "data.zip", "destination": "ports/VVVVVV/data.zip",
|
||||
"platform_system": "vvvvvv", **fields}
|
||||
return resolve_local_file(
|
||||
entry, self.db, {}, dest_hint=entry["destination"],
|
||||
data_dir_registry=self.registry,
|
||||
)
|
||||
|
||||
def test_a_system_naming_other_cores_gets_nothing(self):
|
||||
self.assertEqual(self._resolve(platform_cores=["VVVVVV"]), (None, "not_found"))
|
||||
|
||||
def test_the_owners_own_system_still_gets_it(self):
|
||||
self.assertEqual(
|
||||
self._resolve(platform_cores=["xrick"]),
|
||||
("bios/Other/xrick/data.zip", "name_exact"),
|
||||
)
|
||||
|
||||
def test_the_emuelec_entry_is_not_served_xrick(self):
|
||||
os.chdir(self._cwd)
|
||||
from common import load_platform_config
|
||||
|
||||
config = load_platform_config("emuelec", str(REPO_ROOT / "platforms"))
|
||||
entry = config["systems"]["vvvvvv"]["files"][0]
|
||||
self.assertEqual(entry["platform_cores"], ["VVVVVV"])
|
||||
db = load_database(str(REPO_ROOT / "database.json"))
|
||||
path, _status = resolve_local_file(
|
||||
entry, db, {}, dest_hint=entry["destination"],
|
||||
data_dir_registry=load_data_dir_registry(str(REPO_ROOT / "platforms")),
|
||||
)
|
||||
self.assertFalse(path and "xrick" in path, path)
|
||||
|
||||
|
||||
class SecondPassKeepsIdentity(unittest.TestCase):
|
||||
"""A copy of a covered file at another core's path keeps the entry's proof.
|
||||
|
||||
|
||||
Reference in new issue
Block a user