fix: resolve case collisions on case-insensitive filesystems

Move 17 case-colliding BIOS variants to .variants/ so Windows
and macOS clones no longer lose files. Existence-based platforms
keep the primary, MD5-based platforms resolve from .variants/.

Also fix resolve_local_file zipped_file resolution: when multiple
ZIPs share a name, verify the inner ROM exists before accepting
a candidate. Fixes adam_fdc.zip resolving to the wrong archive.
This commit is contained in:
Abdessamad Derraz
2026-03-20 20:02:42 +01:00
parent 3a7050a8cb
commit 27df5c8fb5
19 changed files with 513 additions and 497 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -244,8 +244,24 @@ def resolve_local_file(
pass pass
if db_md5.lower() in md5_set: if db_md5.lower() in md5_set:
return path, "exact" return path, "exact"
primary = [p for p, _ in candidates if "/.variants/" not in p] # When zipped_file is set, only accept candidates that contain it
return (primary[0] if primary else candidates[0][0]), "hash_mismatch" if zipped_file:
valid = []
for path, m in candidates:
try:
with zipfile.ZipFile(path) as zf:
inner_names = {n.casefold() for n in zf.namelist()}
if zipped_file.casefold() in inner_names:
valid.append((path, m))
except (zipfile.BadZipFile, OSError):
pass
if valid:
primary = [p for p, _ in valid if "/.variants/" not in p]
return (primary[0] if primary else valid[0][0]), "hash_mismatch"
# No candidate contains the zipped_file — fall through to step 5
else:
primary = [p for p, _ in candidates if "/.variants/" not in p]
return (primary[0] if primary else candidates[0][0]), "hash_mismatch"
# 5. zipped_file content match via pre-built index (last resort: # 5. zipped_file content match via pre-built index (last resort:
# matches inner ROM MD5 across ALL ZIPs in the repo, so only use # matches inner ROM MD5 across ALL ZIPs in the repo, so only use