mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-11-06 01:53:56 -06:00
fix: same bytes under two paths agree in slots
A data directory cache and a bios/ copy of one file were judged by path, so 56 bluemsx destinations on AmberELEC and EmuELEC read as contradicted.
This commit is contained in:
1 parent
b873c6a9fb
commit
35ad19ff02
4 files changed
+48
-2466
No files matched your search
File diff suppressed because it is too large.
Load diff
+1
-1233
File diff suppressed because it is too large.
Load diff
+21
-1
@@ -22,6 +22,7 @@ from typing import TYPE_CHECKING
|
||||
|
||||
import nativemode
|
||||
from common import (
|
||||
compute_hashes,
|
||||
platform_arg,
|
||||
archive_entry,
|
||||
build_zip_contents_index,
|
||||
@@ -759,12 +760,18 @@ def find_collisions(
|
||||
def _satisfies(profile: Claim, platform: Claim, db: dict) -> bool:
|
||||
"""Whether the two layers agree on what ships at this destination.
|
||||
|
||||
They agree when they resolve to the same file, when the platform's own
|
||||
They agree when they resolve to the same bytes, when the platform's own
|
||||
hash list accepts the profile's file, or when the profile's accepts the
|
||||
platform's. A contradiction needs both lists to reject the other side.
|
||||
"""
|
||||
if profile.local_path == platform.local_path:
|
||||
return True
|
||||
# Two paths can hold one content: AmberELEC's bluemsx declarations
|
||||
# resolve into the data/bluemsx cache, the profile's into bios/.
|
||||
if profile.local_path and platform.local_path:
|
||||
shipped = _content_sha1(platform.local_path, db)
|
||||
if shipped is not None and shipped == _content_sha1(profile.local_path, db):
|
||||
return True
|
||||
members = profile.entry.get("members")
|
||||
if members and platform.local_path:
|
||||
return holds_required_members(platform.local_path, members)
|
||||
@@ -821,6 +828,19 @@ def _record_at(path: str, db: dict) -> dict | None:
|
||||
_PATH_INDEX: dict[int, tuple[dict, dict[str, dict]]] = {}
|
||||
|
||||
|
||||
def _content_sha1(path: str, db: dict) -> str | None:
|
||||
"""The sha1 of the file at path, from the database or read from disk.
|
||||
|
||||
A data directory cache is not in the database, so its files are hashed.
|
||||
"""
|
||||
record = _record_at(path, db)
|
||||
if record is not None:
|
||||
return record.get("sha1")
|
||||
if not os.path.isfile(path):
|
||||
return None
|
||||
return compute_hashes(path, frozenset({"sha1"}))["sha1"]
|
||||
|
||||
|
||||
def _accepted_by_all(path: str, entries: list[dict], db: dict) -> bool:
|
||||
"""Whether every declaration's own hashes accept the file at path."""
|
||||
record = _record_at(path, db)
|
||||
|
||||
@@ -936,6 +936,32 @@ class ARecordIsFoundByItsPathOnce(unittest.TestCase):
|
||||
self.assertEqual(Counted.walks, 1)
|
||||
|
||||
|
||||
class TwoPathsHoldingOneContentAgree(unittest.TestCase):
|
||||
"""AmberELEC's bluemsx declarations resolve into the data/bluemsx cache,
|
||||
the profile into bios/. Neither declares a hash and the bytes are the
|
||||
same, yet the paths differed and 56 destinations read as contradicted."""
|
||||
|
||||
def test_same_bytes_under_two_paths_satisfy(self):
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
cache = Path(tmp, "data", "MSX2EXT.rom")
|
||||
stored = Path(tmp, "bios", "MSX2EXT.rom")
|
||||
other = Path(tmp, "bios", "other.rom")
|
||||
for path, payload in ((cache, b"rom"), (stored, b"rom"), (other, b"xyz")):
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
path.write_bytes(payload)
|
||||
db = {"files": {}}
|
||||
platform = Claim("platform", "Machines/MSX2EXT.rom", "MSX2EXT.rom",
|
||||
local_path=str(cache), status="path_exact")
|
||||
same = Claim("profile", "Machines/MSX2EXT.rom", "MSX2EXT.rom",
|
||||
emulator="bluemsx", local_path=str(stored),
|
||||
status="path_exact")
|
||||
different = Claim("profile", "Machines/MSX2EXT.rom", "MSX2EXT.rom",
|
||||
emulator="bluemsx", local_path=str(other),
|
||||
status="path_exact")
|
||||
self.assertTrue(slots._satisfies(same, platform, db))
|
||||
self.assertFalse(slots._satisfies(different, platform, db))
|
||||
|
||||
|
||||
class TheSlotsSummaryClosesTheRun(unittest.TestCase):
|
||||
"""The totals came before the collision section and ignored it, and the
|
||||
help said the default run fails on conflicts the pack should settle,
|
||||
|
||||
Reference in new issue
Block a user