fix: count each reason a held file is not packed

The first entry's reason stood for the whole count: 16 Lakka files
under one cause that 2 of them carried (findings 23 and 76).
This commit is contained in:
Abdessamad Derraz committed 2026-11-05 11:40:40 +01:00
1 parent 6e77da4b82
commit 5e4becf876
3 files changed
+57 -3

No files matched your search

+17 -2
View File
@@ -29,6 +29,7 @@ import contextlib
import json
import os
import sys
from collections import Counter
from collections.abc import Mapping
from pathlib import Path
@@ -1800,6 +1801,19 @@ def _core_required_missing(bios_files: list[dict]) -> list[dict]:
]
def _omission_reasons(entries: list[dict]) -> str:
"""Each reason a held file was left out, with its count when several.
Printing the first entry's reason for the whole count named one cause
for 412 RomM files when 20 carried it.
"""
counts = Counter(u.get("omitted", "not placed") for u in entries)
if len(counts) == 1:
return next(iter(counts))
ranked = sorted(counts.items(), key=lambda item: (-item[1], item[0]))
return ", ".join(f"{count} {reason}" for reason, count in ranked)
def _print_undeclared_section(result: dict, verbose: bool) -> None:
"""Print cross-reference section for undeclared files used by cores."""
undeclared = result.get("undeclared_files", [])
@@ -1843,7 +1857,8 @@ def _print_undeclared_section(result: dict, verbose: bool) -> None:
names = ", ".join(sorted({u["name"] for u in bundled}))
print(f" Bundled with their emulator, not collected: {names}")
if unplaced:
print(f" Core files held but not packed: {len(unplaced)} ({unplaced[0]['omitted']})")
print(f" Core files held but not packed: {len(unplaced)} "
f"({_omission_reasons(unplaced)})")
for u in req_not_in_repo:
_print_undeclared_entry(u, "MISSING (required)", verbose)
@@ -1869,7 +1884,7 @@ def _print_undeclared_section(result: dict, verbose: bool) -> None:
if gd_unplaced:
print(
f" Game data held but not packed: {len(gd_unplaced)} "
f"({gd_unplaced[0].get('omitted', 'not placed')})"
f"({_omission_reasons(gd_unplaced)})"
)
+38
View File
@@ -157,6 +157,44 @@ class EveryPlatformInTheSummaryCarriesItsCount(unittest.TestCase):
self.assertIn("3 warning (Lakka 2, ROCKNIX 1)", summary)
class HeldButNotPackedNamesEachReason(unittest.TestCase):
"""'Core files held but not packed: 16 (a packed file occupies its
directory)' on Lakka, where 14 of the 16 are installed with their
emulator: the first entry's reason stood for the whole count."""
@staticmethod
def _entry(name: str, reason: str, category: str = "bios") -> dict:
return {"name": name, "emulator": "x", "required": True, "in_repo": True,
"in_pack": False, "omitted": reason, "category": category}
def _printed(self, entries: list[dict]) -> str:
import contextlib # noqa: PLC0415
import io # noqa: PLC0415
out = io.StringIO()
with contextlib.redirect_stdout(out):
verify._print_undeclared_section({"undeclared_files": entries}, False)
return out.getvalue()
def test_each_reason_carries_its_count(self):
entries = [self._entry("a.rom", "a packed file occupies its directory")]
entries += [self._entry(f"{i}.rom", "installed with its emulator") for i in range(3)]
entries += [self._entry(f"g{i}", "installed with its emulator", "game_data")
for i in range(2)]
entries.append(self._entry("g9", "no platform slug for its system", "game_data"))
text = self._printed(entries)
self.assertIn(
"Core files held but not packed: 4 (3 installed with its emulator, "
"1 a packed file occupies its directory)", text)
self.assertIn(
"Game data held but not packed: 3 (2 installed with its emulator, "
"1 no platform slug for its system)", text)
def test_a_single_reason_reads_as_before(self):
text = self._printed([self._entry("a.rom", "installed with its emulator")] * 2)
self.assertIn("Core files held but not packed: 2 (installed with its emulator)", text)
class OneSpellingPerOption(unittest.TestCase):
"""verify.py -p batocera worked and slots.py -p batocera was refused."""
+2 -1
View File
@@ -117,7 +117,8 @@ RetroDECK: 2007/2008 OK, 1 untested [md5]
The run prints more `DISCREPANCY` lines than this excerpt shows. The core
and game data lines count what the emulator cores add beyond the platform's
own list. A file held but not packed is left out for the reason in parentheses.
own list. A file held but not packed is left out for the reason in parentheses, each
reason with its count when the files have several.
`--verbose` also lists the passing entries that an emulator validates, with
the check and the source lines behind it: