From ff3428e1f10aa7c36136ba3d22e99c4cd7d87272 Mon Sep 17 00:00:00 2001 From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com> Date: Sun, 18 Oct 2026 19:46:03 +0200 Subject: [PATCH] fix: resolve manifest core files like the pack The manifest resolved core files without the data directories: blueMSX's pack carried its own MSX2P.rom while the manifest named another dump for the installer. --- scripts/generate_pack.py | 14 +++++++++++--- tests/test_core_file_fills_declaration.py | 23 +++++++++++++++++++++++ 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/scripts/generate_pack.py b/scripts/generate_pack.py index b5591495..fcfb75fc 100644 --- a/scripts/generate_pack.py +++ b/scripts/generate_pack.py @@ -3448,6 +3448,7 @@ def _attach_claims( dest: str, manifest_dest: str, repo_root: str, + data_registry: dict | None = None, ) -> None: """Every other core that reads this destination, in the order the builder meets them: a pack built without the earlier cores, or without the @@ -3470,7 +3471,8 @@ def _attach_claims( continue claim_path, claim_status = resolve_file( claim, db, bios_dir, zip_contents, - dest_hint=claim.get("destination", ""), offline=offline, + dest_hint=claim.get("destination", ""), + data_dir_registry=data_registry, offline=offline, ) if claim_status in ("not_found", "external", "user_provided") or not claim_path: # Nothing held for this core: narrowed to it without the cores @@ -3590,6 +3592,7 @@ def _manifest_core_entries( required_only: bool = False, validation_index: dict | None = None, owners: dict | None = None, + data_registry: dict | None = None, ) -> int: """Add the files a platform's cores need but its list does not name. @@ -3623,12 +3626,16 @@ def _manifest_core_entries( continue dest_hint = fe.get("destination", "") + # Resolved with the data directories, as the builder resolves the + # same extra: without them blueMSX's MSX2P.rom named a different + # dump than the one its pack carried. local_path, status = resolve_file( fe, db, bios_dir, zip_contents, dest_hint=dest_hint, + data_dir_registry=data_registry, offline=offline, ) if status in ("not_found", "external", "user_provided") or not local_path: @@ -3679,7 +3686,7 @@ def _manifest_core_entries( _attach_claims( entry, fe.get("other_claims", []), db, bios_dir, zip_contents, offline, required_only, validation_index, owners, dest, - manifest_dest, repo_root, + manifest_dest, repo_root, data_registry, ) manifest_files.append(entry) @@ -4149,7 +4156,7 @@ def generate_manifest( zip_contents, offline, region_drops, case_insensitive, seen_destinations, seen_lower, seen_parents, manifest_files, omitted_by_destination, record_omission, pack_only_sizes, selection, - required_only, manifest_validation, manifest_owners, + required_only, manifest_validation, manifest_owners, data_registry, ) for key, (entry, full_dest, dest) in platform_entries.items(): declared = declared_by.get(full_dest, set()) @@ -4160,6 +4167,7 @@ def generate_manifest( _attach_claims( entry, claims, db, bios_dir, zip_contents, offline, required_only, manifest_validation, manifest_owners, dest, dest, repo_root, + data_registry, ) # A platform omission narrows like a platform file: by the systems # declaring it, which can be fewer than the ones whose cores read it. diff --git a/tests/test_core_file_fills_declaration.py b/tests/test_core_file_fills_declaration.py index afe8bb1d..c107a2fd 100644 --- a/tests/test_core_file_fills_declaration.py +++ b/tests/test_core_file_fills_declaration.py @@ -353,5 +353,28 @@ class ANamelessWhitelistEntry(unittest.TestCase): self.assertIn("2/3 files OK", out.getvalue()) +class TheManifestResolvesLikeThePack(unittest.TestCase): + """The builder resolved core files with the data directories and the + manifest without: blueMSX's pack carried its own MSX2P.rom while the + manifest named another dump for the installer to place.""" + + def test_every_platform_resolution_reads_the_data_directories(self): + import ast + + source = (REPO_ROOT / "scripts" / "generate_pack.py").read_text(encoding="utf-8") + missing = [] + for fn in ast.walk(ast.parse(source)): + if not isinstance(fn, ast.FunctionDef) or fn.name == "generate_md5_pack": + continue + for node in ast.walk(fn): + if ( + isinstance(node, ast.Call) + and getattr(node.func, "id", None) == "resolve_file" + and "data_dir_registry" not in {k.arg for k in node.keywords} + ): + missing.append(f"{fn.name}:{node.lineno}") + self.assertEqual(missing, []) + + if __name__ == "__main__": unittest.main()