diff --git a/scripts/common.py b/scripts/common.py index a0018a25..80bdb2b4 100644 --- a/scripts/common.py +++ b/scripts/common.py @@ -958,6 +958,12 @@ def resolve_local_file( valid.append((path, m, size)) except (zipfile.BadZipFile, OSError): pass + # The archive whose member carries the declared md5 is the one: + # neogeo.zip is held twice, each with its own sfix.sfix, and the + # first by name was returned as a mismatch while the other matched. + for path, _m, _size in sorted(valid, key=lambda c: "/.variants/" in c[0]): + if any(check_inside_zip(path, zipped_file, md5) == "ok" for md5 in md5_list): + return path, "zip_exact" if valid: primary = [c[0] for c in valid if "/.variants/" not in c[0]] return (primary[0] if primary else valid[0][0]), "hash_mismatch" diff --git a/tests/test_resolution_evidence.py b/tests/test_resolution_evidence.py index 80e2855b..4677c0bf 100644 --- a/tests/test_resolution_evidence.py +++ b/tests/test_resolution_evidence.py @@ -275,5 +275,29 @@ class SeveralAcceptedCrc32(unittest.TestCase): ) +class TheMatchingArchiveForAMember(unittest.TestCase): + """neogeo.zip is held twice with different sfix.sfix members. For an + entry pinning the second's member md5, the name step returned the first + as a mismatch and the md5 platform excluded a file the repo holds.""" + + def test_the_archive_whose_member_matches(self): + with tempfile.TemporaryDirectory() as tmp: + paths = [] + for folder, member in (("a", b"first"), ("b", b"second")): + path = Path(tmp) / folder / "neogeo.zip" + path.parent.mkdir() + with zipfile.ZipFile(path, "w") as handle: + handle.writestr("sfix.sfix", member) + handle.writestr("000-lo.lo", b"lo") + paths.append(path) + files = {hashlib.sha1(p.read_bytes()).hexdigest(): {"path": str(p), "name": "neogeo.zip"} + for p in paths} + db = {"files": files, "indexes": {"by_name": {"neogeo.zip": list(files)}, + "by_md5": {}, "by_crc32": {}, "by_path_suffix": {}}} + entry = {"name": "neogeo.zip", "zipped_file": "sfix.sfix", + "md5": hashlib.md5(b"second").hexdigest()} + self.assertEqual(common.resolve_local_file(entry, db), (str(paths[1]), "zip_exact")) + + if __name__ == "__main__": unittest.main()