diff --git a/scripts/generate_pack.py b/scripts/generate_pack.py index 60555ff5..ec6175fb 100644 --- a/scripts/generate_pack.py +++ b/scripts/generate_pack.py @@ -3704,6 +3704,18 @@ def generate_manifest( "user_provided", None, ) + # The pack writes the instructions in the slot's place + # and holds it: one more member than the files listed. + instructions = file_entry.get( + "instructions", "Please provide this file manually." + ) + pack_only_sizes.append(len( + f"File needed: {file_entry['name']}\n\n{instructions}\n".encode() + )) + seen_destinations.add(dedup_key) + _register_path(dedup_key, seen_destinations, seen_parents) + if case_insensitive: + seen_lower.add(dedup_key.lower()) continue local_path, status = settle( diff --git a/tests/test_pack_counts.py b/tests/test_pack_counts.py index 1390839a..78b1615c 100644 --- a/tests/test_pack_counts.py +++ b/tests/test_pack_counts.py @@ -142,6 +142,40 @@ class ManifestStatesWhatThePackHolds(PackCountFixture): ), ) + def test_a_file_the_user_provides_counts_its_instructions(self): + """The pack writes INSTRUCTIONS_.txt in a user_provided slot; + the manifest counted none, so the archive held one member more than + pack_files said and release_record refused it.""" + platform = {**PLATFORM, "systems": {"demo-system": { + **PLATFORM["systems"]["demo-system"], + "files": PLATFORM["systems"]["demo-system"]["files"] + [ + {"name": "keys.bin", "destination": "keys.bin", + "storage": "user_provided", "instructions": "Dump your own."}, + ], + }}} + (self.platforms / "demo.yml").write_text(yaml.dump(platform)) + common._platform_config_cache.clear() + self.addCleanup(common._platform_config_cache.clear) + out = self.root / "dist" + out.mkdir() + zip_path = builder.generate_pack( + "demo", str(self.platforms), self.db, str(self.bios), str(out), + emulators_dir=str(self.emulators), + emu_profiles=self.profiles, data_registry=self.registry, + offline=True, + ) + with zipfile.ZipFile(zip_path) as archive: + members = archive.infolist() + self.assertIn("INSTRUCTIONS_keys.bin.txt", {m.filename for m in members}) + manifest = self._manifest() + self.assertEqual( + manifest["pack_files"], len({m.filename for m in members} | {"manifest.json"}) + ) + self.assertEqual( + manifest["pack_size"], + sum(m.file_size for m in members if m.filename not in builder.PACK_DOCUMENTS), + ) + def test_the_installer_count_is_left_alone(self): """install.py refuses a manifest whose total is not its list.""" manifest = self._manifest()