fix: no collision where one file passes every declaration

This commit is contained in:
Abdessamad Derraz committed 2026-10-05 22:12:23 +02:00
1 parent c61d35c41e
commit f625039190
2 files changed
+43

No files matched your search

+32
View File
@@ -21,7 +21,9 @@ from dataclasses import dataclass, field
import nativemode
from common import (
build_zip_contents_index,
check_inside_zip,
load_data_dir_registry,
parse_md5_list,
resolution_is_hash_exact,
resolve_local_file,
runs_standalone,
@@ -415,10 +417,40 @@ def find_collisions(
if local and local not in resolved:
resolved.append(local)
if len(resolved) > 1 and not _same_file_family(resolved):
# A file every declaration accepts settles the path: RetroDECK
# declares ATARIOSB.ROM twice, the second with an md5 list that
# also names the first one's file.
if any(_accepted_by_all(path, entries, db) for path in resolved):
continue
collisions.append(Collision(destination=key, resolved=resolved))
return collisions
def _accepted_by_all(path: str, entries: list[dict], db: dict) -> bool:
"""Whether every declaration's own hashes accept the file at path."""
record = next(
(e for e in db.get("files", {}).values() if e.get("path") == path), None
)
if record is None:
return False
for entry in entries:
if entry.get("zipped_file"):
declared = parse_md5_list(entry.get("md5"))
if declared and not any(
check_inside_zip(path, entry["zipped_file"], m) == "ok" for m in declared
):
return False
continue
md5s = parse_md5_list(entry.get("md5"))
if md5s and str(record.get("md5", "")).lower() not in md5s:
return False
sha1 = entry.get("sha1")
sha1s = [sha1] if isinstance(sha1, str) else list(sha1 or [])
if sha1s and str(record.get("sha1", "")).lower() not in {h.lower() for h in sha1s}:
return False
return True
def _same_file_family(paths: list[str]) -> bool:
"""Whether the paths are one file and its own pinned variants.
+11
View File
@@ -369,6 +369,17 @@ class TestSelfContradictingDestinations(unittest.TestCase):
)
self.assertEqual(slots.find_collisions(config, REGIONS_DB), [])
def test_a_file_both_declarations_accept_settles_the_path(self):
"""RetroDECK: ATARIOSB.ROM under one system with one md5, under
another with a list naming that same md5; the shipped file passes
both, so --strict has nothing to correct there."""
config = self._config(
{"name": "IPL.bin", "destination": "disk.rom", "md5": "m" * 32},
{"name": "IPL.bin", "destination": "disk.rom",
"md5": f"{'n' * 32},{'m' * 32}"},
)
self.assertEqual(slots.find_collisions(config, REGIONS_DB), [])
def test_a_primary_and_its_pinned_variant_are_one_family(self):
self.assertTrue(
slots._same_file_family(