From 76b41741ec22ced162c7b431f5c2d76915d48f97 Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Wed, 21 Oct 2026 05:08:19 +0200
Subject: [PATCH] fix: count bundled files apart on the gaps page
The summary, the provenance table and the per-emulator Missing column
summed the report's gap_missing, which counts files the emulator's own
package installs: 1,356 files to source where 609 are. They get their
own row and column now.
---
scripts/generate_site.py | 46 +++++++++++++++++++++++++++++----------
tests/test_site_render.py | 28 ++++++++++++++++++++++++
2 files changed, 63 insertions(+), 11 deletions(-)
diff --git a/scripts/generate_site.py b/scripts/generate_site.py
index 3dd6d410..b947ea0d 100644
--- a/scripts/generate_site.py
+++ b/scripts/generate_site.py
@@ -3828,7 +3828,9 @@ def generate_gap_analysis(
gap_report = build_emulator_gap_report(profiles, coverages, db, data_names)
report_all = gap_report
- src_totals: dict[str, int] = {"bios": 0, "data": 0, "large_file": 0, "missing": 0}
+ src_totals: dict[str, int] = {
+ "bios": 0, "data": 0, "large_file": 0, "bundled": 0, "missing": 0,
+ }
total_undeclared = 0
emulator_gaps = []
@@ -3836,8 +3838,8 @@ def generate_gap_analysis(
if data["gaps"] == 0:
continue
total_undeclared += data["gaps"]
- for key in src_totals:
- src_totals[key] += data.get(f"gap_{key}", 0)
+ for key, count in _gap_sources(data).items():
+ src_totals[key] += count
emulator_gaps.append((emu_name, data))
@@ -3855,9 +3857,10 @@ def generate_gap_analysis(
"## Core complement",
"",
f"Files loaded by emulators but not declared by any platform. "
- f"{total_undeclared:,} files across {len(emulator_gaps)} emulators, "
+ f"{total_undeclared:,} files across {_count(len(emulator_gaps), 'emulator')}, "
f"{total_available:,} available ({pct_available}), "
- f"{src_totals['missing']} to source.",
+ f"{src_totals['bundled']:,} installed with their emulator, "
+ f"{src_totals['missing']:,} to source.",
"",
"This counts every profiled emulator, including those no platform "
"ships yet, so it reaches past what the pack tables above measure: "
@@ -3873,17 +3876,20 @@ def generate_gap_analysis(
f"| data/ | {src_totals['data']} | Data directories (buildbot, GitHub) |",
f"| release | {src_totals['large_file']} "
"| GitHub release assets (large files) |",
+ f"| bundled | {src_totals['bundled']} "
+ "| Installed with the emulator's own package, not collected |",
f"| missing | {src_totals['missing']} | Not available, needs sourcing |",
"",
"### Per emulator",
"",
- "| Emulator | Undeclared | bios | data | release | Missing |",
- "|----------|----------:|-----:|-----:|--------:|--------:|",
+ "| Emulator | Undeclared | bios | data | release | Bundled | Missing |",
+ "|----------|----------:|-----:|-----:|--------:|--------:|--------:|",
])
for emu_name, data in sorted(emulator_gaps, key=lambda x: -x[1]["gaps"]):
display = data["emulator"]
- m = data.get("gap_missing", 0)
+ sources = _gap_sources(data)
+ m = sources["missing"]
missing_str = (
f'{m}'
if m > 0
@@ -3892,9 +3898,10 @@ def generate_gap_analysis(
lines.append(
f"| [{display}](emulators/{emu_name}.md) "
f"| {data['gaps']} "
- f"| {data.get('gap_bios', 0)} "
- f"| {data.get('gap_data', 0)} "
- f"| {data.get('gap_large_file', 0)} "
+ f"| {sources['bios']} "
+ f"| {sources['data']} "
+ f"| {sources['large_file']} "
+ f"| {sources['bundled']} "
f"| {missing_str} |"
)
lines.append("")
@@ -4056,6 +4063,23 @@ def _core_scope_note(config: dict, profiles: dict) -> str:
return f" (all libretro, plus {_count(others, 'other core')})"
+def _gap_sources(data: dict) -> dict[str, int]:
+ """Where each undeclared file of one emulator comes from.
+
+ A file the emulator's own package installs is not one to find. The
+ report's gap_missing counts it, and the gaps page announced 1,356 files
+ to source where 609 are, with a red badge on emulators that have none.
+ """
+ counts = {"bios": 0, "data": 0, "large_file": 0, "bundled": 0, "missing": 0}
+ for gap in data.get("gap_details") or []:
+ source = gap.get("source", "")
+ if source == "missing" and gap.get("bundled"):
+ source = "bundled"
+ if source in counts:
+ counts[source] += 1
+ return counts
+
+
def _render_xref_by_platform(
coverages: dict, unique: dict
) -> list[str]:
diff --git a/tests/test_site_render.py b/tests/test_site_render.py
index 1d1861ff..d551ad1b 100644
--- a/tests/test_site_render.py
+++ b/tests/test_site_render.py
@@ -111,5 +111,33 @@ class EveryPageAddressesPlatformsAsPeers(unittest.TestCase):
self.assertEqual(found, [])
+class BundledFilesAreNotToSource(unittest.TestCase):
+ """The gaps page summed the report's gap_missing, bundled files included:
+ 1,356 files to source where 609 were, and a red badge of 13 on ZQuest
+ Classic, whose 13 missing files all come with its own package."""
+
+ def test_the_summary_and_the_row_count_only_what_must_be_found(self):
+ import generate_site
+
+ gap = {"required": True, "source_ref": "x", "in_repo": False}
+ report = {"zq": {
+ "emulator": "ZQuest Classic", "gaps": 4, "gap_missing": 3, "gap_bios": 1,
+ "unsourceable": [],
+ "gap_details": [
+ {**gap, "name": "a.dll", "source": "missing", "bundled": True},
+ {**gap, "name": "b.dll", "source": "missing", "bundled": True},
+ {**gap, "name": "c.bin", "source": "missing"},
+ {**gap, "name": "d.bin", "source": "bios", "in_repo": True},
+ ],
+ }}
+ page = generate_site.generate_gap_analysis(
+ {"zq": {"emulator": "ZQuest Classic", "files": []}}, {},
+ {"files": {}, "indexes": {}}, gap_report=report)
+ self.assertIn("2 installed with their emulator, 1 to source.", page)
+ self.assertIn("| missing | 1 | Not available, needs sourcing |", page)
+ self.assertIn("| [ZQuest Classic](emulators/zq.md) | 4 | 1 | 0 | 0 | 2 | "
+ '1 |', page)
+
+
if __name__ == "__main__":
unittest.main()