feat: record each export change before and after

The page named the entries a change touched and never the values, so
a maintainer could not check a correction. The report now carries
changes, one object per change with kind, entry, field, old and new,
read from the platform entry and from the value the render writes
(written() per format: record value for System.dat and RomM, one md5
where a single one is checked). The existing label lists are derived
from it. The page writes "md5 X becomes Y" and names each required
flag with its new value. A test parses the original and updated
System.dat and es_bios.xml and checks the list equals the diff.
This commit is contained in:
Abdessamad Derraz committed 2026-10-20 20:00:54 +02:00
1 parent 5cba005d67
commit 545e3f3ba1
9 files changed
+382 -28

No files matched your search

+11
View File
@@ -180,6 +180,17 @@ class BaseExporter(ABC):
return ""
return fe.hash(field_name)
def written(self, fe: NativeFile, field_name: str) -> str:
"""The value the render writes for one hash field, comma-joined.
The report gives each change its value before and after, so it reads
the value the way the render chooses it: one md5 where the format
checks one, every accepted value where it lists them.
"""
if field_name == self.SINGLE_HASH_FIELD:
return self.single_value(fe, field_name)
return ",".join(fe.hashes(field_name))
def states(self, fe: NativeFile, field_name: str) -> bool:
"""Whether the written file carries this entry's corrected field.
+4
View File
@@ -64,6 +64,10 @@ class Exporter(BaseExporter):
return False
return super().states(fe, field_name)
def written(self, fe: NativeFile, field_name: str) -> str:
"""An entry is checked against one md5, the first accepted."""
return fe.hash(field_name)
def _by_path(self, systems: dict[str, NativeSystem]) -> dict[str, object]:
indexed: dict[str, object] = {}
for system in systems.values():
+6
View File
@@ -90,6 +90,12 @@ class Exporter(BaseExporter):
return False
return super().writable(fe, require)
def written(self, fe: NativeFile, field_name: str) -> str:
"""md5 is a list of every accepted dump, sha256 a single value."""
if field_name == "sha256":
return fe.hash(field_name)
return super().written(fe, field_name)
def states(self, fe: NativeFile, field_name: str) -> bool:
if id(fe) in getattr(self, "_appended", ()):
return False
+6
View File
@@ -113,6 +113,7 @@ class Exporter(BaseExporter):
}
self._first_addition = {}
self.normalized: list[str] = []
self.normalized_values: list[tuple[NativeFile, str, str, str]] = []
for system in sorted(systems.values(), key=lambda s: s.native_id):
for fe in sorted(system.files, key=lambda f: f.name):
key = (fe.native_system, fe.name)
@@ -159,6 +160,10 @@ class Exporter(BaseExporter):
does not keep."""
return bool(_hash_values(fe.platform or {}, name)) and not fe.hashes(name)
def written(self, fe: NativeFile, field_name: str) -> str:
"""A record holds one value per field, the one record_hash names."""
return fe.record_hash(field_name)
def fills(self, fe: NativeFile, field_name: str) -> bool:
return self.states(fe, field_name) and self.record_fills(fe, field_name)
@@ -179,6 +184,7 @@ class Exporter(BaseExporter):
and name not in fe.corrections
):
self.normalized.append(f"{fe.native_system}/{fe.name} {name}")
self.normalized_values.append((fe, name, str(theirs), value))
entry[field] = value
def validate(
+4
View File
@@ -154,6 +154,10 @@ class Exporter(BaseExporter):
)
return lines
def written(self, fe: NativeFile, field_name: str) -> str:
"""A record holds one value per field, the one record_hash names."""
return fe.record_hash(field_name)
def fills(self, fe: NativeFile, field_name: str) -> bool:
return self.states(fe, field_name) and self.record_fills(fe, field_name)