fix: report contradicted hashes in existence verify

This commit is contained in:
Abdessamad Derraz committed 2026-10-06 12:05:56 +02:00
1 parent 500535b7a6
commit 5b341dbe54
4 files changed
+45 -7

No files matched your search

+2 -7
View File
@@ -73,6 +73,7 @@ from nativemode import (
reads_file_contents, reads_file_contents,
) )
from validation import ( from validation import (
existence_discrepancy,
destination_owners, destination_owners,
validated_choice, validated_choice,
inner_rom_check, inner_rom_check,
@@ -908,15 +909,9 @@ def generate_pack(
# their code never reads the bytes. An upstream hash that # their code never reads the bytes. An upstream hash that
# contradicts a local dump is reported, not acted on. # contradicts a local dump is reported, not acted on.
if status == "hash_mismatch" and local_path: if status == "hash_mismatch" and local_path:
declared = file_entry.get("md5", "") or file_entry.get(
"sha1", ""
)
actual = compute_hashes(local_path)
file_reasons.setdefault( file_reasons.setdefault(
dedup_key, dedup_key,
f"packed per {platform_display} existence check; " existence_discrepancy(file_entry, local_path, platform_display),
f"declared hash {declared}, file md5 "
f"{actual['md5']} sha1 {actual['sha1']}",
) )
file_status.setdefault(dedup_key, "ok") file_status.setdefault(dedup_key, "ok")
+12
View File
@@ -559,3 +559,15 @@ def validated_choice(
return better, None return better, None
reason, emulators = check reason, emulators = check
return local_path, f"{', '.join(emulators)} says {reason}" return local_path, f"{', '.join(emulators)} says {reason}"
def existence_discrepancy(file_entry: dict, local_path: str, platform_display: str) -> str:
"""What an existence platform is told when its declared hash contradicts
the file it loads: the file is kept, the gap is said out loud. The pack
and verify both print this one line."""
declared = file_entry.get("md5", "") or file_entry.get("sha1", "")
actual = compute_hashes(local_path)
return (
f"packed per {platform_display} existence check; declared hash {declared}, "
f"file md5 {actual['md5']} sha1 {actual['sha1']}"
)
+12
View File
@@ -69,6 +69,7 @@ from nativemode import (
reads_file_contents, reads_file_contents,
) )
from validation import ( from validation import (
existence_discrepancy,
destination_owners, destination_owners,
validated_choice, validated_choice,
agnostic_substitute, agnostic_substitute,
@@ -124,6 +125,8 @@ def verify_entry_existence(
db: dict | None = None, db: dict | None = None,
destination: str = "", destination: str = "",
owners: dict | None = None, owners: dict | None = None,
resolve_status: str = "",
platform_display: str = "",
) -> dict: ) -> dict:
"""RetroArch verification: path_is_valid() -file exists = OK.""" """RetroArch verification: path_is_valid() -file exists = OK."""
name = file_entry.get("name", "") name = file_entry.get("name", "")
@@ -131,6 +134,13 @@ def verify_entry_existence(
if not local_path: if not local_path:
return {"name": name, "status": Status.MISSING, "required": required} return {"name": name, "status": Status.MISSING, "required": required}
result = {"name": name, "status": Status.OK, "required": required} result = {"name": name, "status": Status.OK, "required": required}
if resolve_status == "hash_mismatch":
# The frontend reads no bytes, so the file stays; the declared hash
# it contradicts is reported, as the pack does.
result["discrepancy"] = existence_discrepancy(
file_entry, local_path, platform_display
)
return result
if not validation_index: if not validation_index:
return result return result
if db: if db:
@@ -874,6 +884,8 @@ def verify_platform(
db, db,
destination, destination,
validation_owners, validation_owners,
resolve_status,
config.get("platform", ""),
) )
elif digest_algorithm(mode) == "sha1": elif digest_algorithm(mode) == "sha1":
result = verify_entry_sha1(file_entry, local_path) result = verify_entry_sha1(file_entry, local_path)
+19
View File
@@ -115,5 +115,24 @@ class CoreArchivesAreCounted(unittest.TestCase):
self.assertIn("1 required missing", out.getvalue()) self.assertIn("1 required missing", out.getvalue())
self.assertIn("neogeo.zip", out.getvalue()) self.assertIn("neogeo.zip", out.getvalue())
class ExistenceReportsWhatThePackReports(unittest.TestCase):
def test_a_contradicted_hash_is_a_discrepancy(self):
"""30 RetroArch entries printed DISCREPANCY in the pack, nothing in verify."""
import tempfile # noqa: PLC0415
sys.path.insert(0, str(REPO_ROOT / "scripts"))
import verify # noqa: PLC0415
with tempfile.TemporaryDirectory(dir=REPO_ROOT / "tmp") as tmp:
path = Path(tmp) / "aes.zip"
path.write_bytes(b"local dump")
entry = {"name": "aes.zip", "md5": "9d2ff2333e23910cf56f7f785609d36a"}
result = verify.verify_entry_existence(
entry, str(path), resolve_status="hash_mismatch", platform_display="RetroArch"
)
self.assertEqual(result["status"], verify.Status.OK)
self.assertIn("declared hash 9d2ff233", result["discrepancy"])
if __name__ == "__main__": if __name__ == "__main__":
unittest.main() unittest.main()