From 8001b9d86d02c8f0df2b1d82aa3fc59a3d537230 Mon Sep 17 00:00:00 2001 From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com> Date: Sun, 18 Oct 2026 16:06:35 +0200 Subject: [PATCH] fix: compute verify's gap report once --- scripts/packextras.py | 16 +++++++++++----- scripts/verify.py | 10 ++++++++-- tests/test_hidden_extras.py | 29 +++++++++++++++++++++++++++++ 3 files changed, 48 insertions(+), 7 deletions(-) diff --git a/scripts/packextras.py b/scripts/packextras.py index 4e84b5bb..2e1f33bd 100644 --- a/scripts/packextras.py +++ b/scripts/packextras.py @@ -155,6 +155,7 @@ def hidden_extras( target_cores: set[str] | None = None, region_drops: set[str] | None = None, placed: set[str] | None = None, + report: list[dict] | None = None, ) -> dict[tuple[str, str, str], str]: """Report entries the builder holds and still leaves out, with the reason. @@ -189,7 +190,7 @@ def hidden_extras( hidden: dict[tuple[str, str, str], str] = {} for fe in _collect_emulator_extras( config, emulators_dir, db, set(shipped), base_dest, profiles, - target_cores=target_cores, + target_cores=target_cores, undeclared=report, ): dest = sanitize_pack_path(fe.get("destination", fe.get("name", ""))) if not dest or (region_drops and dest in region_drops): @@ -603,9 +604,13 @@ def _collect_emulator_extras( unplaceable: list[dict] | None = None, baseline_claims: dict[str, dict] | None = None, absent: list[dict] | None = None, + undeclared: list[dict] | None = None, ) -> list[dict]: """Collect core requirement files from emulator profiles not in the platform pack. + ``undeclared`` is the gap report when the caller already holds it, + computed with the same arguments (verify's own pass). + ``absent`` receives, placed like the others, the entries the collection does not hold: the region pass groups them as it groups the platform's own missing files, so the report withdraws the ones a request excludes. @@ -650,10 +655,11 @@ def _collect_emulator_extras( # under an alias still get packed at the emulator's expected path. yaml_names = platform_declarations(config, db, enrich=False) - undeclared = find_undeclared_files( - config, emulators_dir, db, emu_profiles, target_cores=target_cores, - include_all=include_all, declared_names=yaml_names, - ) + if undeclared is None: + undeclared = find_undeclared_files( + config, emulators_dir, db, emu_profiles, target_cores=target_cores, + include_all=include_all, declared_names=yaml_names, + ) # A destination two cores claim goes to the one that names its content: # hypseus-singe asks for gamecontrollerdb.txt by name alone and took the # BIOS root before Solarus, which pins its own by sha1. Profile order diff --git a/scripts/verify.py b/scripts/verify.py index dad280a6..979e4cb8 100644 --- a/scripts/verify.py +++ b/scripts/verify.py @@ -787,10 +787,13 @@ def _mark_hidden( shipped: dict[str, str], target_cores: set[str] | None, region_drops: set[str] | None = None, + report: list[dict] | None = None, ) -> set[str]: """What the builder holds but cannot place beside the files it packed. Returns the full destinations the builder fills with a core's file. + ``report`` is the gap report the caller already computed with the + builder's arguments; without it the builder's pass computes its own. """ from packextras import hidden_extras @@ -799,7 +802,7 @@ def _mark_hidden( config, emulators_dir, db, emu_profiles if emu_profiles is not None else load_emulator_profiles(emulators_dir), - shipped, target_cores, region_drops, placed, + shipped, target_cores, region_drops, placed, report, ) for u in undeclared: reason = hidden.get( @@ -1128,6 +1131,9 @@ def verify_platform( target_cores=target_cores, declared_names=platform_declarations(config, db, enrich=False), ) + # The builder's own pass reads the same report: computed once here and + # handed over as it stands now, before the markings below. + report_for_builder = [dict(u) for u in undeclared] if region_drops: undeclared = [ u @@ -1140,7 +1146,7 @@ def verify_platform( _mark_unplaced(config, undeclared, profiles) placed = _mark_hidden( config, undeclared, emulators_dir, db, emu_profiles, shipped, target_cores, - region_drops, + region_drops, report_for_builder, ) if not reads_file_contents(mode): # An existence frontend is satisfied by any file at the path, and the diff --git a/tests/test_hidden_extras.py b/tests/test_hidden_extras.py index 7c142070..9e0f82ac 100644 --- a/tests/test_hidden_extras.py +++ b/tests/test_hidden_extras.py @@ -110,5 +110,34 @@ class TheReportSaysSo(unittest.TestCase): self.assertIs(entry.get("in_pack"), False) + +class TheGapReportIsComputedOnce(unittest.TestCase): + """verify_platform ran find_undeclared_files twice with the same + arguments, once itself and once through hidden_extras: every + resolution twice, 8% of verify --all.""" + + def test_one_call_per_platform(self): + if not (REPO_ROOT / "database.json").exists(): + self.skipTest("database.json is not built") + from unittest import mock + + previous = os.getcwd() + os.chdir(REPO_ROOT) + try: + import verify + from common import load_database, load_emulator_profiles, load_platform_config + + db = load_database("database.json") + profiles = load_emulator_profiles("emulators") + config = load_platform_config("emudeck", "platforms") + with mock.patch.object( + verify, "find_undeclared_files", wraps=verify.find_undeclared_files + ) as counted: + verify.verify_platform(config, db, "emulators", profiles) + finally: + os.chdir(previous) + self.assertEqual(counted.call_count, 1) + + if __name__ == "__main__": unittest.main()