From 39e6afbeb21cc10e0406422d5366bdb244699b89 Mon Sep 17 00:00:00 2001 From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com> Date: Fri, 6 Nov 2026 04:00:47 +0100 Subject: [PATCH] fix: a size kept in bios_db.json is not removed When the truth accepts the BiosDB hash but none of its sizes fits, the MiSTer render keeps the entry's size beside the hash, and the report still counted a size removed. A size the truth does not state is no longer reported as changed. --- scripts/exporter/misterfpga_exporter.py | 4 ++++ tests/test_exporters.py | 26 +++++++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/scripts/exporter/misterfpga_exporter.py b/scripts/exporter/misterfpga_exporter.py index c84fc7ad4..5d8b7b5e3 100644 --- a/scripts/exporter/misterfpga_exporter.py +++ b/scripts/exporter/misterfpga_exporter.py @@ -83,6 +83,10 @@ class Exporter(BaseExporter): written = getattr(self, "_written", None) if written is not None and id(fe) not in written: return False + if field_name == "size" and not fe.size(): + # The render writes a size only when the truth states one, and + # otherwise keeps MiSTer's beside the hash: nothing is removed. + return False return super().states(fe, field_name) def written(self, fe: NativeFile, field_name: str) -> str: diff --git a/tests/test_exporters.py b/tests/test_exporters.py index 6a21dd740..f84b4e624 100644 --- a/tests/test_exporters.py +++ b/tests/test_exporters.py @@ -1944,6 +1944,32 @@ class MisterDatabaseComesBackAsWritten(unittest.TestCase): self.assertEqual(len(exporter.withheld()), 1) self.assertEqual(exporter.validate(systems, produced), []) + def test_a_kept_size_is_not_reported_removed(self): + """The truth accepts MiSTer's hash and states other sizes, so no + size of its own fits the entry. The render keeps MiSTer's size, and + the report counted it removed.""" + database = {"db_id": "bios_db", "files": { + "games/X/boot.rom": {"hash": "a" * 32, "size": 1000, "url": "u"}, + }} + original = json.dumps(database) + scraped = {"systems": {"x": {"files": [{ + "name": "boot.rom", "destination": "X/boot.rom", "md5": "a" * 32, + "size": 1000, + }]}}} + truth = {"systems": {"x": {"files": [{ + "name": "boot.rom", "path": "X/boot.rom", "md5": "a" * 32, + "size": [2000, 3000], "_cores": ["x"], + }]}}} + exporter = discover_exporters()["misterfpga"]() + systems, report = build_native_model(truth, scraped) + produced = exporter.render(systems, report, {"bios_db.json": original}, scraped) + written = json.loads(produced["bios_db.json"])["files"]["games/X/boot.rom"] + self.assertEqual(written["size"], 1000) + self.assertNotIn( + "size_removed", + [c["kind"] for c in landed_changes(exporter, systems).records], + ) + def test_an_accepted_hash_is_not_swapped_for_another(self): """The url serves MiSTer's dump, and the truth accepts it among two. The first accepted md5 went in its place with no change reported,