fix: keep retrodeck md5 lists as arrays

This commit is contained in:
Abdessamad Derraz committed 2026-10-16 15:42:18 +02:00
1 parent 3a0ae494d3
commit ffeee246ff
2 files changed
+82 -3

No files matched your search

+10 -3
View File
@@ -34,7 +34,8 @@ def _systems_of(entry: dict) -> list[str]:
def _md5_set(value: object) -> set[str]:
return {m.strip().lower() for m in str(value or "").split(",") if m.strip()}
values = value if isinstance(value, list) else str(value or "").split(",")
return {str(m).strip().lower() for m in values if str(m).strip()}
def _paths_key(entry: dict) -> tuple[str, ...]:
@@ -136,9 +137,11 @@ class Exporter(BaseExporter):
def _entry(fe: NativeFile) -> OrderedDict:
entry: OrderedDict[str, object] = OrderedDict()
entry["filename"] = fe.name
md5 = ",".join(fe.hashes("md5"))
# Several accepted dumps stay a JSON array, as RetroDECK writes them:
# a comma-joined string reads back as one value that is no md5.
md5 = fe.hashes("md5")
if md5:
entry["md5"] = md5
entry["md5"] = md5 if len(md5) > 1 else md5[0]
sha256 = fe.hash("sha256")
if sha256:
entry["sha256"] = sha256
@@ -241,6 +244,10 @@ class Exporter(BaseExporter):
(field, value) for field, value in by_key[keys[0]].items()
if field in cls.carries() and not (field == "system" and declared)
)
if _md5_set(entry.get("md5")) == _md5_set(combined.get("md5")):
combined["md5"] = entry.get("md5")
elif isinstance(entry.get("md5"), list) and isinstance(combined.get("md5"), str):
combined["md5"] = [combined["md5"]]
merged.append(combined)
corrected.update(keys)
+72
View File
@@ -627,6 +627,78 @@ class RommExport(unittest.TestCase):
self.assertTrue(all(k.startswith("psx:") for k in data))
class RetrodeckExport(unittest.TestCase):
A, B, C = "a" * 32, "b" * 32, "c" * 32
def _render(self, declared, accepted):
"""Export one file RetroDECK lists as an md5 array."""
truth = {
"systems": {
"atari-400-800": {
"files": [
{
"name": "ATARIOSB.ROM",
"path": "ATARIOSB.ROM",
"md5": accepted,
"required": True,
"_cores": ["atari800"],
}
]
}
}
}
scraped = {
"systems": {
"atari-400-800": {
"native_id": "atari800",
"files": [
{
"name": "ATARIOSB.ROM",
"destination": "bios/ATARIOSB.ROM",
"native_system": "atari800",
"md5": ",".join(declared),
"component": "retroarch",
"required": True,
}
],
}
}
}
original = json.dumps({
"retroarch": {
"bios": [
{
"filename": "ATARIOSB.ROM",
"md5": declared,
"system": "atari800",
"required": "Required",
}
]
}
})
systems, report = build_native_model(truth, scraped)
exporter = discover_exporters()["retrodeck"]()
produced = exporter.render(
systems, report, {"retroarch/component_manifest.json": original}, None
)
(entry,) = json.loads(produced["retroarch/component_manifest.json"])[
"retroarch"
]["bios"]
return entry["md5"]
def test_an_unchanged_md5_array_is_left_as_written(self):
"""The same dumps in another order are no correction."""
self.assertEqual(
self._render([self.A, self.B], [self.B, self.A]), [self.A, self.B]
)
def test_a_corrected_md5_array_stays_an_array(self):
"""A comma-joined string reads back as one value that is no md5."""
written = self._render([self.A, self.B], [self.A, self.C])
self.assertIsInstance(written, list)
self.assertEqual(set(written), {self.A, self.B, self.C})
class BatoceraExport(unittest.TestCase):
def _render(self, originals):
systems, report = model()