mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-11-09 03:23:47 -06:00
fix: hand RetroDECK manifests back as written
With nothing to correct, nine of ten manifests still changed: a final newline was added where the original ends without one, "md5": null was written 39 times where no md5 key was, and PPSSPP's single bios object became a list rebuilt from our data. A manifest now ends as the original does, keeps no key it did not have, and a single object stays one while nothing is added. An empty truth gives back every cached manifest byte for byte.
This commit is contained in:
1 parent
85c2433c98
commit
3ed5f68b82
2 files changed
+56
-5
No files matched your search
@@ -222,6 +222,9 @@ class Exporter(BaseExporter):
|
|||||||
|
|
||||||
merged: list[OrderedDict] = []
|
merged: list[OrderedDict] = []
|
||||||
corrected: set[tuple[str, str]] = set()
|
corrected: set[tuple[str, str]] = set()
|
||||||
|
# PPSSPP writes its one BIOS as an object, not a list of one.
|
||||||
|
if isinstance(existing, dict):
|
||||||
|
existing = [existing]
|
||||||
entries = [e for e in existing if isinstance(e, dict)] if isinstance(existing, list) else []
|
entries = [e for e in existing if isinstance(e, dict)] if isinstance(existing, list) else []
|
||||||
# A name and system declared several times are several revisions (the
|
# A name and system declared several times are several revisions (the
|
||||||
# 64DD IPL USA and Dev): one entry of ours corrects the revision it
|
# 64DD IPL USA and Dev): one entry of ours corrects the revision it
|
||||||
@@ -260,7 +263,12 @@ class Exporter(BaseExporter):
|
|||||||
if field in cls.carries() and field not in by_key[keys[0]]:
|
if field in cls.carries() and field not in by_key[keys[0]]:
|
||||||
combined.pop(field, None)
|
combined.pop(field, None)
|
||||||
if _md5_set(entry.get("md5")) == _md5_set(combined.get("md5")):
|
if _md5_set(entry.get("md5")) == _md5_set(combined.get("md5")):
|
||||||
combined["md5"] = entry.get("md5")
|
# Their own spelling, and no key where they wrote none: an
|
||||||
|
# equal empty set wrote "md5": null 39 times.
|
||||||
|
if "md5" in entry:
|
||||||
|
combined["md5"] = entry["md5"]
|
||||||
|
else:
|
||||||
|
combined.pop("md5", None)
|
||||||
elif isinstance(entry.get("md5"), list) and isinstance(combined.get("md5"), str):
|
elif isinstance(entry.get("md5"), list) and isinstance(combined.get("md5"), str):
|
||||||
combined["md5"] = [combined["md5"]]
|
combined["md5"] = [combined["md5"]]
|
||||||
merged.append(combined)
|
merged.append(combined)
|
||||||
@@ -322,8 +330,11 @@ class Exporter(BaseExporter):
|
|||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
container, key = holder
|
container, key = holder
|
||||||
container[key] = self._merge(
|
written = container.get(key)
|
||||||
container.get(key), entries, additions, appended
|
merged = self._merge(written, entries, additions, appended)
|
||||||
|
# A single object stays one while nothing is added to it.
|
||||||
|
container[key] = (
|
||||||
|
merged[0] if isinstance(written, dict) and len(merged) == 1 else merged
|
||||||
)
|
)
|
||||||
break
|
break
|
||||||
# A declared entry whose revision the platform does not hold is
|
# A declared entry whose revision the platform does not hold is
|
||||||
@@ -334,7 +345,10 @@ class Exporter(BaseExporter):
|
|||||||
and (str(fe.name), str(fe.native_system)) in appended
|
and (str(fe.name), str(fe.native_system)) in appended
|
||||||
)
|
)
|
||||||
|
|
||||||
produced[path] = json.dumps(manifest, indent=2, ensure_ascii=False) + "\n"
|
# Nine of ten manifests end without a newline: the file ends as
|
||||||
|
# theirs does.
|
||||||
|
ending = "\n" if original.endswith("\n") else ""
|
||||||
|
produced[path] = json.dumps(manifest, indent=2, ensure_ascii=False) + ending
|
||||||
|
|
||||||
return produced
|
return produced
|
||||||
|
|
||||||
@@ -366,7 +380,8 @@ class Exporter(BaseExporter):
|
|||||||
if holder is None:
|
if holder is None:
|
||||||
continue
|
continue
|
||||||
container, key = holder
|
container, key = holder
|
||||||
for entry in container[key]:
|
listed = container[key]
|
||||||
|
for entry in [listed] if isinstance(listed, dict) else listed:
|
||||||
declared.add(entry.get("filename", ""))
|
declared.add(entry.get("filename", ""))
|
||||||
placed.add((entry.get("filename", ""), _paths_key(entry)))
|
placed.add((entry.get("filename", ""), _paths_key(entry)))
|
||||||
if not component_value.get("name") and not component_value.get(
|
if not component_value.get("name") and not component_value.get(
|
||||||
|
|||||||
@@ -1420,6 +1420,42 @@ class BizhawkExport(unittest.TestCase):
|
|||||||
self.assertFalse(exporter.states(entry, "sha1"))
|
self.assertFalse(exporter.states(entry, "sha1"))
|
||||||
|
|
||||||
|
|
||||||
|
class RetrodeckManifestsComeBackAsWritten(unittest.TestCase):
|
||||||
|
"""With nothing to correct, a manifest is the platform's own bytes. The
|
||||||
|
export added a final newline to nine of ten, wrote "md5": null where no
|
||||||
|
md5 key was, and turned PPSSPP's single bios object into a list."""
|
||||||
|
|
||||||
|
def test_an_empty_truth_hands_back_every_manifest(self):
|
||||||
|
cache = UPSTREAM_CACHE / "retrodeck"
|
||||||
|
manifests = sorted(cache.glob("*/component_manifest.json"))
|
||||||
|
if not manifests:
|
||||||
|
self.skipTest("upstream cache not populated")
|
||||||
|
exporter = discover_exporters()["retrodeck"]()
|
||||||
|
config = native_layer(load_platform_config("retrodeck", str(REPO_ROOT / "platforms")))
|
||||||
|
systems, report = build_native_model({"systems": {}}, config)
|
||||||
|
originals = {f"{m.parent.name}/component_manifest.json": m.read_text(encoding="utf-8")
|
||||||
|
for m in manifests}
|
||||||
|
produced = exporter.render(systems, report, originals, config)
|
||||||
|
for path, text in produced.items():
|
||||||
|
with self.subTest(manifest=path):
|
||||||
|
self.assertEqual(text, originals[path])
|
||||||
|
|
||||||
|
def test_no_md5_key_is_made_up(self):
|
||||||
|
from exporter.retrodeck_exporter import Exporter # noqa: PLC0415
|
||||||
|
|
||||||
|
mine = OrderedDict([("filename", "bios.bin"), ("system", "xbox"), ("required", "Yes")])
|
||||||
|
(merged,) = Exporter._merge([OrderedDict(mine)], [OrderedDict(mine)])
|
||||||
|
self.assertNotIn("md5", merged)
|
||||||
|
|
||||||
|
def test_a_single_bios_object_stays_an_object(self):
|
||||||
|
from exporter.retrodeck_exporter import Exporter # noqa: PLC0415
|
||||||
|
|
||||||
|
theirs = OrderedDict([("filename", "ppge_atlas.zim"), ("system", "psp"),
|
||||||
|
("md5", "a" * 32)])
|
||||||
|
merged = Exporter._merge(OrderedDict(theirs), [])
|
||||||
|
self.assertEqual(merged, [theirs])
|
||||||
|
|
||||||
|
|
||||||
class RetrodeckExport(unittest.TestCase):
|
class RetrodeckExport(unittest.TestCase):
|
||||||
A, B, C = "a" * 32, "b" * 32, "c" * 32
|
A, B, C = "a" * 32, "b" * 32, "c" * 32
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user