mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-10-20 18:59:07 -05:00
fix: a refused file is held, not present
On a hash platform the builder leaves out a file whose declared hash the local copy contradicts, but the README coverage added every UNTESTED file to the present count. RetroDECK read 2,008/2,008 for a pack carrying 2,007. verify now lists the destinations the builder refuses, and the coverage subtracts them.
This commit is contained in:
1 parent
16f6ef8cbf
commit
1ea6b9d070
4 files changed
+65
-3
No files matched your search
@@ -95,7 +95,7 @@ Full list with per-file details: **[https://abdess.github.io/retrobios/](https:/
|
||||
| Recalbox | 351/351 | 2,788/2,806 | MD5 hash |
|
||||
| RetroArch | 526/526 | 5,277/5,309 | file presence |
|
||||
| RetroBat | 348/348 | 7,255/7,417 | MD5 hash |
|
||||
| RetroDECK | 2,008/2,008 | 5,323/5,377 | MD5 hash |
|
||||
| RetroDECK | 2,007/2,008 | 5,323/5,377 | MD5 hash |
|
||||
| RetroPie * | 532/532 | 9,195/9,339 | file presence |
|
||||
| RomM | 383/383 | 61/788 | MD5 hash |
|
||||
|
||||
@@ -180,4 +180,4 @@ The scripts and tooling are released under the [MIT License](LICENSE).
|
||||
The BIOS and firmware files are not covered by that license: they are third-party system software, preserved and provided for personal backup, archival, and interoperability with emulation software. [NOTICE](NOTICE) sets out their status and how to ask for a file to be removed.
|
||||
The reasoning, and where it is weakest, is in the [FAQ](https://abdess.github.io/retrobios/wiki/faq/#is-this-legal).
|
||||
|
||||
*Auto-generated on 2026-10-19T05:42:39Z*
|
||||
*Auto-generated on 2026-10-19T20:59:35Z*
|
||||
@@ -60,7 +60,9 @@ def compute_coverage(
|
||||
untested = sc.get("untested", 0)
|
||||
missing = sc.get("missing", 0)
|
||||
total = result["total_files"]
|
||||
present = ok + untested
|
||||
# An UNTESTED file the builder refuses (its declared hash contradicted on
|
||||
# a hash platform) is held, not packed.
|
||||
present = ok + untested - len(result.get("excluded_files", []))
|
||||
pct = (present / total * 100) if total > 0 else 0
|
||||
undeclared = result.get("undeclared_files", [])
|
||||
# Held is not packed: a file the platform has no folder for, or one below
|
||||
|
||||
@@ -1045,6 +1045,7 @@ def verify_platform(
|
||||
)
|
||||
|
||||
shipped: dict[str, str] = {}
|
||||
shipped_keys: set[str] = set()
|
||||
results_at: dict[str, list[dict]] = {}
|
||||
for sys_id, system in verify_systems.items():
|
||||
for file_entry in system.get("files", []):
|
||||
@@ -1111,6 +1112,7 @@ def verify_platform(
|
||||
f"{base_dest}/{destination}" if base_dest else destination,
|
||||
local_path,
|
||||
)
|
||||
shipped_keys.add(_dest_key(file_entry, sys_id))
|
||||
if _twin_unmet(result, held_by):
|
||||
continue
|
||||
|
||||
@@ -1191,6 +1193,14 @@ def verify_platform(
|
||||
for s in file_severity.values():
|
||||
counts[s] = counts.get(s, 0) + 1
|
||||
|
||||
# Held but refused: on a hash platform the builder leaves out a file whose
|
||||
# declared hash the local copy contradicts. Counted apart, so a coverage
|
||||
# figure never calls present what the pack does not carry.
|
||||
excluded = sorted(
|
||||
dest for dest, status in file_status.items()
|
||||
if status == Status.UNTESTED and dest not in shipped_keys
|
||||
)
|
||||
|
||||
# Count by file status (ok/untested/missing)
|
||||
status_counts: dict[str, int] = {}
|
||||
for s in file_status.values():
|
||||
@@ -1229,6 +1239,7 @@ def verify_platform(
|
||||
"total_files": total,
|
||||
"severity_counts": counts,
|
||||
"status_counts": status_counts,
|
||||
"excluded_files": excluded,
|
||||
"undeclared_files": undeclared,
|
||||
"exclusion_notes": exclusions,
|
||||
"region_fallbacks": sorted(region_fallbacks),
|
||||
|
||||
@@ -425,5 +425,54 @@ class TheCollectionTotalNamesTheCollection(unittest.TestCase):
|
||||
self.assertEqual(generate_site.COLLECTION_FILES_LABEL, "Files collected")
|
||||
|
||||
|
||||
class RefusedFilesAreNotPresent(unittest.TestCase):
|
||||
"""RetroDECK's dsifirmware.bin is held, but its declared hash contradicts
|
||||
the local copy, so the md5 builder leaves it out. The README still
|
||||
printed 2,008/2,008 for a pack that carries 2,007."""
|
||||
|
||||
def test_the_coverage_subtracts_a_refused_file(self):
|
||||
import os
|
||||
|
||||
import common
|
||||
import generate_db
|
||||
import generate_readme
|
||||
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
previous = os.getcwd()
|
||||
os.chdir(tmp)
|
||||
self.addCleanup(os.chdir, previous)
|
||||
for d in ("bios/X", "platforms", "emulators"):
|
||||
Path(d).mkdir(parents=True)
|
||||
files = {}
|
||||
for name in ("good.bin", "wrong.bin"):
|
||||
payload = name.encode()
|
||||
Path(f"bios/X/{name}").write_bytes(payload)
|
||||
sha1 = hashlib.sha1(payload).hexdigest()
|
||||
files[sha1] = {
|
||||
"path": f"bios/X/{name}", "name": name, "size": len(payload),
|
||||
"sha1": sha1, "md5": hashlib.md5(payload).hexdigest(),
|
||||
"sha256": hashlib.sha256(payload).hexdigest(), "crc32": "00000001",
|
||||
}
|
||||
db = {"files": files, "indexes": generate_db.build_indexes(files, {})}
|
||||
config = {
|
||||
"platform": "Hashy", "verification_mode": "md5", "base_destination": "bios",
|
||||
"systems": {"sys": {"files": [
|
||||
{"name": "good.bin", "destination": "good.bin",
|
||||
"md5": hashlib.md5(b"good.bin").hexdigest()},
|
||||
{"name": "wrong.bin", "destination": "wrong.bin", "md5": "f" * 32},
|
||||
]}},
|
||||
}
|
||||
Path("platforms/hashy.yml").write_text(yaml.dump(config))
|
||||
Path("platforms/_registry.yml").write_text(
|
||||
yaml.dump({"platforms": {"hashy": {"status": "active"}}})
|
||||
)
|
||||
common._platform_config_cache.clear()
|
||||
self.addCleanup(common._platform_config_cache.clear)
|
||||
coverage = generate_readme.compute_coverage(
|
||||
"hashy", "platforms", db, emulators_dir="emulators"
|
||||
)
|
||||
self.assertEqual((coverage["present"], coverage["total"]), (1, 2))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in new issue
Block a user