mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-10-10 13:33:24 -05:00
fix: fail a pack member the collection cannot name
This commit is contained in:
1 parent
2cdb98239e
commit
ed18e61580
2 files changed
+78
No files matched your search
@@ -31,6 +31,25 @@ from packresolve import resolve_file
|
||||
from common import resolve_platform_cores
|
||||
from common import sanitize_pack_path
|
||||
import zipfile
|
||||
def _members_are_held(data: bytes, by_md5: dict, db: dict) -> bool:
|
||||
"""Whether every member of an archive is a dump the collection holds."""
|
||||
import io
|
||||
|
||||
held_inside = build_zip_contents_index(db)
|
||||
try:
|
||||
with zipfile.ZipFile(io.BytesIO(data)) as archive:
|
||||
members = [i for i in archive.infolist() if not i.is_dir()]
|
||||
if not members:
|
||||
return False
|
||||
for info in members:
|
||||
digest = hashlib.md5(archive.read(info)).hexdigest()
|
||||
if digest not in by_md5 and digest not in held_inside:
|
||||
return False
|
||||
except (zipfile.BadZipFile, OSError):
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def verify_pack(
|
||||
zip_path: str, db: dict, data_registry: dict | None = None
|
||||
) -> tuple[bool, dict]:
|
||||
@@ -183,6 +202,19 @@ def verify_pack(
|
||||
except (zipfile.BadZipFile, OSError):
|
||||
continue
|
||||
|
||||
# An archive the builder assembled (a MAME clone set): every
|
||||
# member must be a dump the collection holds, loose or inside a
|
||||
# romset.
|
||||
if status == "untracked" and name.endswith(".zip"):
|
||||
if _members_are_held(zf.read(name), by_md5, db):
|
||||
status = "verified_members"
|
||||
file_name = os.path.basename(name)
|
||||
|
||||
if status == "untracked":
|
||||
# Bytes nothing recognises: written wrong, or a source that
|
||||
# no longer matches. Counted and passed, it went unseen.
|
||||
errors.append(f"{name}: content matches no collected file")
|
||||
|
||||
manifest["files"].append(
|
||||
{
|
||||
"path": name,
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
"""Every pack member is bytes the collection recognises.
|
||||
|
||||
A member whose sha1 and md5 matched nothing was counted `untracked` with
|
||||
zero errors and the pack passed, so bytes altered while the ZIP was written
|
||||
went unseen. Archives the builder assembles (MAME clone sets) are
|
||||
recognised by their members.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import hashlib
|
||||
import io
|
||||
import sys
|
||||
import tempfile
|
||||
import unittest
|
||||
import zipfile
|
||||
from pathlib import Path
|
||||
|
||||
REPO_ROOT = Path(__file__).resolve().parents[1]
|
||||
sys.path.insert(0, str(REPO_ROOT / "scripts"))
|
||||
|
||||
|
||||
class MembersMustBeKnown(unittest.TestCase):
|
||||
def test_unknown_bytes_are_an_error_and_assembled_sets_pass(self):
|
||||
from packverify import verify_pack
|
||||
|
||||
known = b"known rom" * 10
|
||||
md5 = hashlib.md5(known).hexdigest()
|
||||
inner = io.BytesIO()
|
||||
with zipfile.ZipFile(inner, "w") as zf:
|
||||
zf.writestr("rom.bin", known)
|
||||
db = {"files": {}, "indexes": {"by_md5": {md5: "s"}, "by_name": {}}}
|
||||
with tempfile.TemporaryDirectory(dir=REPO_ROOT / "tmp") as tmp:
|
||||
pack = Path(tmp) / "P_BIOS_Pack.zip"
|
||||
with zipfile.ZipFile(pack, "w") as zf:
|
||||
zf.writestr("clone.zip", inner.getvalue())
|
||||
zf.writestr("garbled.bin", b"no such dump")
|
||||
ok, manifest = verify_pack(str(pack), db)
|
||||
statuses = {f["path"]: f["status"] for f in manifest["files"]}
|
||||
self.assertEqual(statuses["clone.zip"], "verified_members")
|
||||
self.assertFalse(ok)
|
||||
self.assertTrue(any("garbled.bin" in e for e in manifest["errors"]))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in new issue
Block a user