fix: name the path of a file read at two places

MyMinUI printed the same MISSING line twice for Bios/FBN/ and Bios/NG/
sfiii2a.zip (finding 78).
This commit is contained in:
Abdessamad Derraz committed 2026-11-05 11:41:46 +01:00
1 parent 666883ad53
commit f3fe6f58b4
2 files changed
+35 -8

No files matched your search

+23 -8
View File
@@ -1747,13 +1747,20 @@ def _print_detail_entries(details: list[dict], seen: set[str], verbose: bool) ->
print(f" {line}")
def _print_undeclared_entry(u: dict, prefix: str, verbose: bool) -> None:
"""Print a single undeclared file entry with its validation checks."""
def _print_undeclared_entry(
u: dict, prefix: str, verbose: bool, repeated: frozenset[str] = frozenset()
) -> None:
"""Print a single undeclared file entry with its validation checks.
A name in ``repeated`` is read at more than one path, and the line names
the path: two identical lines told no one there were two slots to fill.
"""
name = u["path"] if u["name"] in repeated and u.get("path") else u["name"]
arc_count = u.get("archive_file_count")
if arc_count:
name_label = f"{u['name']} ({arc_count} file{'s' if arc_count != 1 else ''})"
name_label = f"{name} ({arc_count} file{'s' if arc_count != 1 else ''})"
else:
name_label = u["name"]
name_label = name
print(f" {prefix}: {u['emulator']} needs {name_label}")
checks = u.get("checks", [])
if checks:
@@ -1801,6 +1808,12 @@ def _core_required_missing(bios_files: list[dict]) -> list[dict]:
]
def _repeated_names(entries: list[dict]) -> frozenset[str]:
"""Names more than one of ``entries`` carries."""
counts = Counter(u["name"] for u in entries)
return frozenset(name for name, count in counts.items() if count > 1)
def _omission_reasons(entries: list[dict]) -> str:
"""Each reason a held file was left out, with its count when several.
@@ -1855,13 +1868,14 @@ def _print_undeclared_section(result: dict, verbose: bool) -> None:
)
# The missing files follow the line that counts them: printed after the
# held-but-not-packed line, they read as files installed with their emulator.
repeated = _repeated_names(req_not_in_repo + req_hle_not_in_repo + opt_not_in_repo)
for u in req_not_in_repo:
_print_undeclared_entry(u, "MISSING (required)", verbose)
_print_undeclared_entry(u, "MISSING (required)", verbose, repeated)
for u in req_hle_not_in_repo:
_print_undeclared_entry(u, "MISSING (required, HLE fallback)", verbose)
_print_undeclared_entry(u, "MISSING (required, HLE fallback)", verbose, repeated)
if verbose:
for u in opt_not_in_repo:
_print_undeclared_entry(u, "MISSING (optional)", verbose)
_print_undeclared_entry(u, "MISSING (optional)", verbose, repeated)
if bundled:
names = ", ".join(sorted({u["name"] for u in bundled}))
print(f" Bundled with their emulator, not collected: {names}")
@@ -1880,8 +1894,9 @@ def _print_undeclared_section(result: dict, verbose: bool) -> None:
listed = "" if verbose or not gd_missing else " (--verbose lists them)"
print(f" Game data: {gd_packed} in pack, {len(gd_missing)} missing{listed}")
if verbose:
repeated = _repeated_names(gd_missing)
for u in gd_missing:
_print_undeclared_entry(u, "MISSING (game data)", verbose)
_print_undeclared_entry(u, "MISSING (game data)", verbose, repeated)
if gd_unplaced:
print(
f" Game data held but not packed: {len(gd_unplaced)} "
+12
View File
@@ -202,6 +202,18 @@ class HeldButNotPackedNamesEachReason(unittest.TestCase):
self.assertIn("MISSING (required): FinalBurn Neo needs sfiii2a.zip", lines[1])
self.assertTrue(lines[2].startswith(" Core files held but not packed: "), lines)
def test_one_name_read_at_two_paths_prints_both_paths(self):
"""MyMinUI printed 'FinalBurn Neo needs sfiii2a.zip' twice, word for
word, for Bios/FBN/ and Bios/NG/."""
base = {"name": "sfiii2a.zip", "emulator": "FinalBurn Neo", "required": True,
"in_repo": False, "category": "bios"}
lone = dict(base, name="other.zip", path="Bios/FBN/other.zip")
text = self._printed([dict(base, path="Bios/FBN/sfiii2a.zip"),
dict(base, path="Bios/NG/sfiii2a.zip"), lone])
self.assertIn("FinalBurn Neo needs Bios/FBN/sfiii2a.zip", text)
self.assertIn("FinalBurn Neo needs Bios/NG/sfiii2a.zip", text)
self.assertIn("FinalBurn Neo needs other.zip\n", 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)