feat: file cards name the packs that install them

A card named only the platforms whose own list declares the file. A RetroBat user looking up scph5501.bin found every platform but RetroBat, whose pack installs it for six cores. The cards now read the install manifests and add each pack that places the file, with the destination it gives it.
This commit is contained in:
Abdessamad Derraz committed 2026-10-20 04:56:23 +02:00
1 parent 91403aa149
commit 17e35d1af9
3 files changed
+62

No files matched your search

+19
View File
@@ -341,6 +341,9 @@ class FileConsumers:
# Where each platform puts the file in its BIOS directory.
self.platform_destinations: dict[str, dict[str, set[str]]] = {}
self.emulators: dict[str, set[str]] = {}
# Where each platform's pack installs the file, its cores' files
# included: the platform's own list names a fraction of them.
self.installed: dict[str, dict[str, set[str]]] = {}
def sha1_of(self, entry: dict, dest: str = "", owner: str = "") -> str | None:
"""The collected file an entry resolves to, or None.
@@ -378,6 +381,22 @@ class FileConsumers:
name, set()
).add(where)
def add_manifests(self, install_dir: str | Path) -> None:
"""Read what each install manifest places, alternatives included."""
for path in sorted(Path(install_dir).glob("*.json")):
try:
manifest = json.loads(path.read_text(encoding="utf-8"))
except (OSError, json.JSONDecodeError) as exc:
print(f"WARNING: {path}: {exc}", file=sys.stderr)
continue
platform = str(manifest.get("platform") or path.stem)
for entry in manifest.get("files") or []:
for sha1 in {entry.get("sha1"), *(
alt.get("sha1") for alt in entry.get("alternatives") or []
)} - {None, ""}:
self.installed.setdefault(sha1, {}).setdefault(
platform, set()).add(str(entry.get("dest", "")))
def path_of(self, sha1: str) -> str:
"""The collection path the database records for a file."""
return str(self._db.get("files", {}).get(sha1, {}).get("path", ""))
+19
View File
@@ -2325,6 +2325,18 @@ def _platform_links(sha1: str, consumers: FileConsumers) -> list[str]:
return links
def _installed_links(sha1: str, consumers: FileConsumers, declared: set[str]) -> list[str]:
"""Each pack installing the file that its platform's list does not name,
with the place the pack gives it."""
links = []
for platform, dests in sorted(getattr(consumers, "installed", {}).get(sha1, {}).items()):
if platform in declared:
continue
where = ", ".join(_code(d) for d in sorted(dests) if d)
links.append(f"[{platform}](../platforms/{platform}.md)" + (f" {where}" if where else ""))
return links
def _system_file_card(f: dict, consumers: FileConsumers) -> list[str]:
"""One file of a system page: hashes, who reads it, its provenance."""
name = f["name"]
@@ -2364,6 +2376,12 @@ def _system_file_card(f: dict, consumers: FileConsumers) -> list[str]:
# that platform puts the file: from the card, retrodeck sent the
# reader to the top of a 2,000-file page.
lines.append(f"- Platforms: {', '.join(_platform_links(sha1_full, consumers))}")
installed = _installed_links(sha1_full, consumers, set(plats))
if installed:
# The packs that carry the file for their cores: a RetroBat user
# looking up scph5501.bin found every platform but RetroBat, whose
# pack installs it for six cores.
lines.append(f"- Also installed by: {', '.join(installed)}")
if emus:
lines.append(f"- Emulators: {', '.join(_emulator_link(e, '../') for e in emus)}")
provenance = f.get("provenance", {})
@@ -4117,6 +4135,7 @@ def _build_file_consumers(db: dict, coverages: dict, profiles: dict) -> FileCons
consumers = FileConsumers(db, build_zip_contents_index(db))
consumers.add_platforms({name: cov["config"] for name, cov in coverages.items()})
consumers.add_emulators(profiles)
consumers.add_manifests(Path(__file__).resolve().parent.parent / "install")
return consumers
+24
View File
@@ -678,5 +678,29 @@ class AFileHasAnAddressByContent(unittest.TestCase):
self.assertIn("../../files/?sha1=" + "ab" * 20, card)
class ACardNamesThePacksThatInstallIt(unittest.TestCase):
"""A file card named only the platforms whose own list declares the
file: a RetroBat user found no RetroBat on scph5501.bin, which its pack
installs for six cores."""
def test_a_manifest_destination_reaches_the_card(self):
import json as _json
from cross_reference import FileConsumers
from generate_site import _installed_links
with tempfile.TemporaryDirectory(dir=ROOT / "tmp") as tmp:
Path(tmp, "retrobat.json").write_text(_json.dumps({
"platform": "retrobat",
"files": [{"dest": "scph5501.bin", "sha1": "b" * 40,
"alternatives": [{"sha1": "a" * 40}]}],
}))
consumers = FileConsumers({"files": {}})
consumers.add_manifests(tmp)
links = _installed_links("a" * 40, consumers, set())
self.assertEqual(links, ["[retrobat](../platforms/retrobat.md) `scph5501.bin`"])
self.assertEqual(_installed_links("a" * 40, consumers, {"retrobat"}), [])
if __name__ == "__main__":
unittest.main()