From 69b8ab1434f13a834abe0f5fb1d701f180468729 Mon Sep 17 00:00:00 2001 From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com> Date: Thu, 6 Aug 2026 10:39:58 +0200 Subject: [PATCH] feat: resolve files by sha256 index --- scripts/common.py | 14 ++++++++++++++ tests/test_e2e.py | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/scripts/common.py b/scripts/common.py index cff66d06..23f9f2f2 100644 --- a/scripts/common.py +++ b/scripts/common.py @@ -429,6 +429,20 @@ def resolve_local_file( if os.path.exists(path): return path, "exact" + # 1b. SHA256 exact match (profiles hashed from sources that publish + # sha256, e.g. MesenCE). A full sha256 is a strong identifier. + sha256_raw = str(file_entry.get("sha256", "") or "") + if sha256_raw: + by_sha256 = db.get("indexes", {}).get("by_sha256", {}) + for cand in sha256_raw.split(","): + cand = cand.strip().lower() + if len(cand) == 64: + match = by_sha256.get(cand) + if match and match in files_db: + path = files_db[match]["path"] + if os.path.exists(path): + return path, "exact" + # 2. MD5 direct lookup (skip for zipped_file: md5 is inner ROM, not container) # Guard: only accept if the found file's name matches the requested name # (or is a .variants/ derivative). Prevents cross-contamination when an diff --git a/tests/test_e2e.py b/tests/test_e2e.py index 1cd33854..21e1d976 100644 --- a/tests/test_e2e.py +++ b/tests/test_e2e.py @@ -4845,6 +4845,46 @@ struct BurnDriver BurnDrvneogeo = { self.assertFalse(_hash_matches("0" * 32, full)) self.assertFalse(_hash_matches("", full)) + def test_216_resolve_by_sha256(self): + """resolve_local_file matches files by declared sha256.""" + import tempfile + + from common import resolve_local_file + + with tempfile.TemporaryDirectory() as tmpdir: + path = os.path.join(tmpdir, "SNES_dsp1.rom") + with open(path, "wb") as fh: + fh.write(b"dsp firmware bytes") + import hashlib as hl + + sha256 = hl.sha256(b"dsp firmware bytes").hexdigest() + db = { + "files": { + "sha1x": {"name": "SNES_dsp1.rom", "path": path}, + }, + "indexes": { + "by_md5": {}, + "by_name": {"SNES_dsp1.rom": ["sha1x"]}, + "by_sha256": {sha256: "sha1x"}, + "by_crc32": {}, + "by_path_suffix": {}, + }, + } + # Name differs, only sha256 identifies the content + entry = {"name": "dsp1.rom", "sha256": sha256} + local, status = resolve_local_file(entry, db) + self.assertEqual(local, path) + self.assertEqual(status, "exact") + # Multi-hash list also resolves + entry = {"name": "dsp1.rom", "sha256": f"{'0' * 64},{sha256}"} + local, status = resolve_local_file(entry, db) + self.assertEqual(local, path) + # Unknown sha256 falls through to not_found + entry = {"name": "dsp1.rom", "sha256": "f" * 64} + local, status = resolve_local_file(entry, db) + self.assertIsNone(local) + self.assertEqual(status, "not_found") + def test_215_check_member_hash_inside_zip(self): """zipped_file entries verify the ROM inside the ZIP, not the ZIP.""" import hashlib as hl