fix: write the cut md5 rule once

Six places read an md5 shorter than 32 digits, each with its own bound.
digest_verdict accepted any prefix down to one digit, while Batocera
compares the whole string (batocera-systems:1088). A cut value now names
a dump only when one held md5 starts with it (cut_md5_owner, read by the
scraper, the resolver and --from-md5), and every verdict compares whole
digests.
This commit is contained in:
Abdessamad Derraz committed 2026-11-06 15:18:38 +01:00
1 parent 8af7b0da13
commit ed6643022d
10 files changed
+71 -78

No files matched your search

+15
View File
@@ -11,6 +11,7 @@ import zipfile
import zlib
from pathlib import Path
from typing import BinaryIO
from collections.abc import Iterable
_ALL_ALGORITHMS = frozenset({"sha1", "md5", "sha256", "crc32", "adler32"})
@@ -130,6 +131,20 @@ def md5_composite_of(source: str | Path | BinaryIO) -> str:
h.update(zf.read(name))
return h.hexdigest()
def cut_md5_owner(cut: str, md5s: Iterable[str]) -> str | None:
"""The one md5 a value cut short starts, None when none or several do.
The single rule for a cut md5, read by the scraper, the resolver and
--from-md5. It names a dump, it never verifies one: Batocera compares
the whole string (batocera-systems:1088), so every verdict compares
exact digests.
"""
if not cut or len(cut) >= 32:
return None
found = {md5 for md5 in md5s if md5.startswith(cut)}
return found.pop() if len(found) == 1 else None
def parse_hash_list(raw: str | list | int | None) -> list[str]:
"""Normalize any hash field into its accepted values, lowercase.