fix: hold the MAME clone step to name rules

This commit is contained in:
Abdessamad Derraz committed 2026-10-17 18:21:27 +02:00
1 parent 425a0de0e5
commit dce9c6e8f1
2 files changed
+51 -4

No files matched your search

+12 -4
View File
@@ -1335,12 +1335,20 @@ def resolve_local_file(
if os.path.exists(path):
return path, "zip_exact"
# MAME clone fallback: if a file was deduped, resolve via canonical
if _depth < 3 and not has_strong_hash:
# MAME clone fallback: if a file was deduped, resolve via canonical. The
# clone name is a name step like the others: an unsourceable entry skips
# it, and the size the code checks travels with it (dedup only merges
# identical bytes, so the canonical copy has the clone's size).
if _depth < 3 and not has_strong_hash and not unsourceable:
clone_map = get_mame_clone_map(db.get("bios_dir"))
canonical = clone_map.get(name)
if canonical and canonical != name:
canonical_entry = {"name": canonical}
canonical_entry = {
field: file_entry[field]
for field in ("size", "min_size", "max_size", "validation")
if field in file_entry
}
canonical_entry["name"] = canonical
result = resolve_local_file(
canonical_entry,
db,
@@ -1349,7 +1357,7 @@ def resolve_local_file(
_depth=_depth + 1,
data_dir_registry=data_dir_registry,
)
if result[0]:
if result[0] and result[1] != "hash_mismatch":
return result[0], "mame_clone"
# Data directory fallback: scan data/ caches for matching filename
+39
View File
@@ -2936,3 +2936,42 @@ class ADataDirectoryCopyPassesTheNameChecks(unittest.TestCase):
def test_another_adler32_is_a_contradiction(self):
status = self.resolve(validation=["adler32"], known_hash_adler32="0xdeadbeef")[1]
self.assertEqual(status, "hash_mismatch")
class AMameCloneNameIsANameStep(unittest.TestCase):
"""The clone fallback relaunched resolution on the bare canonical name:
an unsourceable entry and a size the code checks were both served the
parent set."""
def setUp(self):
self.tmp = Path(tempfile.mkdtemp(dir=TMP_ROOT))
self.addCleanup(lambda: __import__("shutil").rmtree(self.tmp, True))
bios = self.tmp / "bios" / "Arcade"
bios.mkdir(parents=True)
parent = bios / "parent.zip"
parent.write_bytes(b"PARENTSET")
(self.tmp / "_mame_clones.json").write_text(
json.dumps({"parent.zip": {"clones": ["clone.zip"]}})
)
sha1 = hashlib.sha1(parent.read_bytes()).hexdigest()
self.db = {
"bios_dir": str(self.tmp / "bios"),
"files": {sha1: {"path": str(parent), "name": "parent.zip",
"sha1": sha1, "size": 9}},
"indexes": {"by_name": {"parent.zip": [sha1]}, "by_md5": {},
"by_path_suffix": {}, "by_crc32": {}},
}
def resolve(self, **fields):
return resolve_local_file({"name": "clone.zip", **fields}, self.db)
def test_a_clone_resolves_to_its_parent(self):
self.assertEqual(self.resolve()[1], "mame_clone")
def test_an_unsourceable_entry_is_not_served_the_parent(self):
self.assertEqual(self.resolve(unsourceable="not held"), (None, "not_found"))
def test_a_size_the_parent_contradicts_is_not_served(self):
self.assertEqual(
self.resolve(size=5, validation=["size"]), (None, "not_found")
)