fix: key the zip member index on all its inputs

This commit is contained in:
Abdessamad Derraz committed 2026-10-17 08:52:21 +02:00
1 parent d1807af791
commit 53625156d6
2 files changed
+31 -2

No files matched your search

+8 -2
View File
@@ -57,7 +57,7 @@ def zip_member_crcs(path: str) -> frozenset[str]:
return _member_crcs(path, mtime)
_zip_contents_cache: tuple[frozenset[tuple[str, float]], dict] | None = None
_zip_contents_cache: tuple[tuple, dict] | None = None
def build_zip_contents_index(db: dict, max_entry_size: int = 512 * 1024 * 1024) -> dict:
"""Build {inner_rom_md5: zip_file_sha1} for ROMs inside ZIP files.
@@ -74,7 +74,13 @@ def build_zip_contents_index(db: dict, max_entry_size: int = 512 * 1024 * 1024)
if path.endswith(".zip") and os.path.exists(path):
zip_entries.append((path, sha1))
fingerprint = frozenset((path, os.path.getmtime(path)) for path, _ in zip_entries)
# The bound and the sha1 each path carries are part of the answer: a
# second call with a smaller bound got members the first one admitted,
# and a regenerated database got the sha1 of the old one.
fingerprint = (
max_entry_size,
frozenset((path, os.path.getmtime(path), sha1) for path, sha1 in zip_entries),
)
if _zip_contents_cache is not None and _zip_contents_cache[0] == fingerprint:
return _zip_contents_cache[1]
+23
View File
@@ -2448,6 +2448,29 @@ class AnUnreadableDatabaseStopsTheScan(unittest.TestCase):
)
class TheZipIndexCacheKnowsItsInputs(unittest.TestCase):
"""build_zip_contents_index cached on (path, mtime) alone: a smaller
max_entry_size, or a database giving the same archive another sha1,
got the first call's index back."""
def test_the_bound_and_the_sha1_are_part_of_the_key(self):
from scripts import ziptools
with tempfile.TemporaryDirectory(dir=TMP_ROOT) as directory:
path = Path(directory) / "a.zip"
with zipfile.ZipFile(path, "w") as archive:
archive.writestr("big.bin", b"x" * 4096)
ziptools._zip_contents_cache = None
db = {"files": {"a" * 40: {"path": str(path)}}}
self.assertEqual(len(ziptools.build_zip_contents_index(db)), 1)
self.assertEqual(ziptools.build_zip_contents_index(db, max_entry_size=10), {})
other = {"files": {"b" * 40: {"path": str(path)}}}
self.assertEqual(
set(ziptools.build_zip_contents_index(other).values()), {"b" * 40}
)
ziptools._zip_contents_cache = None
class TheDatabaseCacheIsWrittenWhole(unittest.TestCase):
"""A crash while serializing left a truncated db_cache.json behind, and
the next run rehashed the whole collection from scratch."""