fix: withhold a file only on the frontend digest

This commit is contained in:
Abdessamad Derraz committed 2026-10-06 04:21:47 +02:00
1 parent dbc8d63318
commit ac4776b2d0
4 files changed
+130

No files matched your search

+16
View File
@@ -75,6 +75,7 @@ from nativemode import (
)
from validation import (
agnostic_substitute,
frontend_digest_matches,
_build_validation_index,
check_file_validation,
filter_files_by_mode,
@@ -885,6 +886,11 @@ def generate_pack(
)
if not zip_ok:
continue
elif frontend_digest_matches(
file_entry, local_path, digest_algorithm(verification_mode)
):
status = "frontend_digest_exact"
file_status.setdefault(dedup_key, "ok")
else:
file_status[dedup_key] = "excluded"
file_reasons[dedup_key] = "hash mismatch"
@@ -3108,6 +3114,16 @@ def generate_manifest(
and _inner_rom_check(file_entry, local_path) == "ok"
):
status = "zip_exact"
if (
status == "hash_mismatch"
and local_path
and not file_entry.get("zipped_file")
and hash_mismatch_excludes_file(verification_mode)
and frontend_digest_matches(
file_entry, local_path, digest_algorithm(verification_mode)
)
):
status = "frontend_digest_exact"
# An existence platform never reads the bytes, so a declared
# hash the local dump contradicts is not a reason to withhold
# the file. Hash platforms would reject it, so they omit it.
+6
View File
@@ -17,6 +17,7 @@ from packpaths import _register_path
from ziptools import build_zip_contents_index
from ziptools import check_inside_zip
from nativemode import digest_algorithm
from validation import frontend_digest_matches
from nativemode import hash_mismatch_excludes_file
import hashlib
from common import filter_systems_by_target
@@ -406,6 +407,11 @@ def _intentional_hash_exclusion(
)
if status != "hash_mismatch":
return False
if not entry.get("zipped_file") and frontend_digest_matches(
entry, local_path, digest_algorithm(verification_mode)
):
# The frontend's own digest accepts it: the builder ships it.
return False
# A container can mismatch the outer declaration while still carrying
# the exact inner ROM requested by Batocera-style zipped_file entries.
+19
View File
@@ -431,3 +431,22 @@ def agnostic_substitute(
return held, prefix
break
return None
def frontend_digest_matches(file_entry: dict, local_path: str, algorithm: str) -> bool:
"""Whether the frontend's own digest accepts the file.
resolve_local_file calls a file `hash_mismatch` when any declared hash
disagrees, but a frontend compares one digest. RomM's list carries md5,
sha1 and crc32: a mistyped crc32 next to the right md5 must not withhold
a file RomM accepts. Same comparison as verify_entry_md5/_sha1.
"""
if algorithm == "md5":
declared = parse_md5_list(file_entry.get("md5"))
else:
value = file_entry.get(algorithm)
values = value if isinstance(value, list) else [value]
declared = [str(v).strip().lower() for v in values if v]
if not declared or not local_path:
return False
return compute_hashes(local_path)[algorithm].lower() in declared