fix: keep one dump per exported hash record

This commit is contained in:
Abdessamad Derraz committed 2026-10-17 19:26:46 +02:00
1 parent d165005a78
commit e9f9260301
4 files changed
+66 -6

No files matched your search

+23
View File
@@ -123,6 +123,29 @@ class NativeFile:
values = self.hashes(field_name)
return values[0] if values else ""
def record_hash(self, field_name: str) -> str:
"""One value of a record whose fields all describe one dump.
A clrmamepro rom line or a RomM entry carries a single crc, md5 and
sha1: taking each field's first accepted value wrote syscard2.pce
with the v2.0 crc (the truth's first) beside the v2.1 md5 and sha1
(System.dat's), a record no file satisfies. When the two sides
agree on the dump, the platform's record is kept whole, its value
chosen among those the truth accepts; a field only the truth names
is written when it names one value, which is then that dump's.
"""
source = self._identity_source()
truth_values = _hash_values(self.truth or {}, field_name)
platform_values = _hash_values(self.platform or {}, field_name)
if source == "truth":
return truth_values[0] if truth_values else ""
if source == "platform" or not truth_values:
return platform_values[0] if platform_values else ""
if platform_values:
accepted = [v for v in platform_values if v in truth_values]
return (accepted or truth_values)[0]
return truth_values[0] if len(truth_values) == 1 else ""
@property
def required(self) -> bool:
if self.truth is not None and self.truth.get("required") is not None:
+3 -3
View File
@@ -128,13 +128,13 @@ class Exporter(BaseExporter):
entry: OrderedDict[str, str] = OrderedDict()
# The fixture states every value as a string, size included.
entry["size"] = str(fe.size())
crc = fe.hash("crc32")
crc = fe.record_hash("crc32")
if crc:
entry["crc"] = crc
md5 = fe.hash("md5")
md5 = fe.record_hash("md5")
if md5:
entry["md5"] = md5
sha1 = fe.hash("sha1")
sha1 = fe.record_hash("sha1")
if sha1:
entry["sha1"] = sha1
output[f"{system.native_id}:{fe.name}"] = entry
+3 -3
View File
@@ -153,13 +153,13 @@ class Exporter(BaseExporter):
size = fe.size()
if size:
parts.append(f"size {size}")
crc = fe.hash("crc32")
crc = fe.record_hash("crc32")
if crc:
parts.append(f"crc {crc.upper()}")
md5 = fe.hash("md5")
md5 = fe.record_hash("md5")
if md5:
parts.append(f"md5 {md5}")
sha1 = fe.hash("sha1")
sha1 = fe.record_hash("sha1")
if sha1:
parts.append(f"sha1 {sha1}")
rendered.setdefault(name, f"\trom ( {' '.join(parts)} )")
+37
View File
@@ -1352,3 +1352,40 @@ class UpstreamFidelity(unittest.TestCase):
if __name__ == "__main__":
unittest.main()
class ARecordDescribesOneDump(unittest.TestCase):
"""syscard2.pce: System.dat states v2.1 (crc 283b74e0, md5, sha1),
geargrafx accepts three crcs with v2.0's first. Field by field, the
export wrote v2.0's crc beside v2.1's md5 and sha1."""
def test_the_platform_record_stays_whole_when_the_truth_accepts_it(self):
from exporter.baseline import NativeFile
fe = NativeFile(
name="syscard2.pce", destination="syscard2.pce", native_system="pce",
platform={"crc32": "283b74e0", "md5": "3cdd6614" + "0" * 24,
"sha1": "88da02e2" + "0" * 32},
truth={"crc32": ["52520bc6", "283b74e0", "ff2a5ec3"]},
)
self.assertEqual(fe.hash("crc32"), "52520bc6")
self.assertEqual(fe.record_hash("crc32"), "283b74e0")
self.assertEqual(fe.record_hash("md5"), "3cdd6614" + "0" * 24)
def test_a_field_only_the_truth_names_is_written_when_unambiguous(self):
from exporter.baseline import NativeFile
one = NativeFile(name="a", destination="a", native_system="s",
platform={"crc32": "11111111"},
truth={"crc32": "11111111", "md5": "a" * 32})
two = NativeFile(name="a", destination="a", native_system="s",
platform={"crc32": "11111111"},
truth={"crc32": "11111111", "md5": ["a" * 32, "b" * 32]})
self.assertEqual(one.record_hash("md5"), "a" * 32)
self.assertEqual(two.record_hash("md5"), "")
def test_single_record_writers_use_it(self):
for module in ("systemdat_exporter.py", "romm_exporter.py"):
source = (Path(__file__).resolve().parent.parent / "scripts" / "exporter" / module).read_text()
with self.subTest(module=module):
self.assertNotRegex(source, r'= fe\.hash\("(crc32|md5|sha1)"\)')