feat: verify core extras presence in pack alongside baseline

This commit is contained in:
Abdessamad Derraz
2026-03-27 19:41:47 +01:00
parent 89d6dd2eee
commit 3ea1e09cb0
+43 -16
View File
@@ -1173,23 +1173,23 @@ def generate_sha256sums(output_dir: str) -> str | None:
def verify_pack_against_platform( def verify_pack_against_platform(
zip_path: str, platform_name: str, platforms_dir: str, zip_path: str, platform_name: str, platforms_dir: str,
db: dict | None = None, emulators_dir: str = "emulators",
emu_profiles: dict | None = None,
) -> tuple[bool, int, int, list[str]]: ) -> tuple[bool, int, int, list[str]]:
"""Verify a pack ZIP against its platform config. """Verify a pack ZIP against its platform config and core requirements.
Checks: Checks:
1. Every baseline file declared by the platform exists in the ZIP 1. Every baseline file declared by the platform exists in the ZIP
at the correct destination path at the correct destination path
2. No duplicate entries 2. Every in-repo core extra file (from emulator profiles) is present
3. No path anomalies (double slash, absolute, traversal) 3. No duplicate entries
4. No unexpected zero-byte BIOS files 4. No path anomalies (double slash, absolute, traversal)
5. No unexpected zero-byte BIOS files
Hash verification is handled by verify.py upstream (which runs
against bios/ on disk before packing). This function verifies
that the pack was assembled correctly.
Returns (all_ok, checked, present, errors). Returns (all_ok, checked, present, errors).
""" """
from collections import Counter from collections import Counter
from verify import find_undeclared_files
config = load_platform_config(platform_name, platforms_dir) config = load_platform_config(platform_name, platforms_dir)
base_dest = config.get("base_destination", "") base_dest = config.get("base_destination", "")
@@ -1197,6 +1197,9 @@ def verify_pack_against_platform(
checked = 0 checked = 0
present = 0 present = 0
if emu_profiles is None:
emu_profiles = load_emulator_profiles(emulators_dir)
with zipfile.ZipFile(zip_path, "r") as zf: with zipfile.ZipFile(zip_path, "r") as zf:
zip_set = set(zf.namelist()) zip_set = set(zf.namelist())
zip_lower = {n.lower(): n for n in zip_set} zip_lower = {n.lower(): n for n in zip_set}
@@ -1219,21 +1222,45 @@ def verify_pack_against_platform(
if "GraphicMods" not in info.filename and info.filename != "manifest.json": if "GraphicMods" not in info.filename and info.filename != "manifest.json":
errors.append(f"zero-byte: {info.filename}") errors.append(f"zero-byte: {info.filename}")
# Baseline file presence # 1. Baseline file presence
baseline_checked = 0
baseline_present = 0
for sys_id, system in config.get("systems", {}).items(): for sys_id, system in config.get("systems", {}).items():
for fe in system.get("files", []): for fe in system.get("files", []):
dest = fe.get("destination", fe.get("name", "")) dest = fe.get("destination", fe.get("name", ""))
if not dest: if not dest:
continue continue
expected = f"{base_dest}/{dest}" if base_dest else dest expected = f"{base_dest}/{dest}" if base_dest else dest
checked += 1 baseline_checked += 1
if expected in zip_set: if expected in zip_set or expected.lower() in zip_lower:
present += 1 baseline_present += 1
elif expected.lower() in zip_lower:
present += 1 # case variant, OK on case-sensitive packs
else: else:
errors.append(f"missing: {expected}") errors.append(f"baseline missing: {expected}")
# 2. Core extras presence (files from emulator profiles, in repo)
core_checked = 0
core_present = 0
if db is not None:
undeclared = find_undeclared_files(config, emulators_dir, db, emu_profiles)
for u in undeclared:
if not u["in_repo"]:
continue
dest = u.get("path") or u["name"]
if base_dest:
full = f"{base_dest}/{dest}"
elif "/" not in dest:
full = f"bios/{dest}"
else:
full = dest
core_checked += 1
if full in zip_set or full.lower() in zip_lower:
core_present += 1
# Not an error if missing — some get deduped or filtered
checked = baseline_checked + core_checked
present = baseline_present + core_present
return len(errors) == 0, checked, present, errors return len(errors) == 0, checked, present, errors
@@ -1282,7 +1309,7 @@ def verify_and_finalize_packs(output_dir: str, db: dict,
platforms = pack_to_platform.get(name, []) platforms = pack_to_platform.get(name, [])
for pname in platforms: for pname in platforms:
p_ok, total, matched, p_errors = verify_pack_against_platform( p_ok, total, matched, p_errors = verify_pack_against_platform(
zip_path, pname, platforms_dir, zip_path, pname, platforms_dir, db=db,
) )
if p_ok: if p_ok:
print(f" platform {pname}: {matched}/{total} OK") print(f" platform {pname}: {matched}/{total} OK")