fix: read extract folders from the registry

This commit is contained in:
Abdessamad Derraz committed 2026-10-06 12:44:32 +02:00
1 parent 908d75a86c
commit a7de9b9c9c
4 files changed
+126 -33

No files matched your search

+12
View File
@@ -148,6 +148,7 @@ platforms:
retroarch:
config: retroarch.yml
status: active
extract_to: system/
logo: https://raw.githubusercontent.com/libretro/RetroArch/master/media/retroarch-vector_invader-only.svg
scraper: libretro
source_url: https://raw.githubusercontent.com/libretro/libretro-database/master/dat/System.dat
@@ -182,6 +183,7 @@ platforms:
batocera:
config: batocera.yml
status: active
extract_to: /userdata/bios/
logo: https://raw.githubusercontent.com/batocera-linux/batocera-emulationstation/master/resources/splash_batocera.svg
scraper: batocera
source_url: https://raw.githubusercontent.com/batocera-linux/batocera.linux/master/package/batocera/core/batocera-scripts/scripts/batocera-systems
@@ -407,6 +409,7 @@ platforms:
recalbox:
config: recalbox.yml
status: active
extract_to: /recalbox/share/bios/
logo: https://raw.githubusercontent.com/homarr-labs/dashboard-icons/main/svg/recalbox.svg
scraper: recalbox
source_url: https://gitlab.com/recalbox/recalbox/-/raw/master/board/recalbox/fsoverlay/recalbox/share_init/system/.emulationstation/es_bios.xml
@@ -620,6 +623,7 @@ platforms:
retrobat:
config: retrobat.yml
status: active
extract_to: bios/
logo: https://raw.githubusercontent.com/RetroBat-Official/retrobat/main/system/resources/retrobat_logo_notext.png
scraper: retrobat
source_url: https://raw.githubusercontent.com/RetroBat-Official/emulatorlauncher/master/batocera-systems/Resources/batocera-systems.json
@@ -808,6 +812,7 @@ platforms:
emudeck:
config: emudeck.yml
status: active
extract_to: ~/Emulation/bios/
logo: https://raw.githubusercontent.com/dragoonDorise/EmuDeck/main/icons/EmuDeck.png
scraper: emudeck
source_url: https://raw.githubusercontent.com/dragoonDorise/EmuDeck/main/functions/checkBIOS.sh
@@ -838,6 +843,7 @@ platforms:
lakka:
config: lakka.yml
status: active
extract_to: /storage/system/
logo: https://raw.githubusercontent.com/libretro/retroarch-assets/master/src/xmb/flatui/lakka.svg
scraper: libretro
inherits_from: retroarch
@@ -854,6 +860,7 @@ platforms:
retrodeck:
config: retrodeck.yml
status: active
extract_to: ~/retrodeck/
logo: https://raw.githubusercontent.com/RetroDECK/RetroDECK/main/res/icon.svg
scraper: retrodeck
source_url: https://github.com/RetroDECK/components
@@ -898,6 +905,7 @@ platforms:
romm:
config: romm.yml
status: active
extract_to: library/bios/
logo: https://avatars.githubusercontent.com/u/168586850
scraper: romm
source_url: https://raw.githubusercontent.com/rommapp/romm/master/backend/models/fixtures/known_bios_files.json
@@ -945,6 +953,7 @@ platforms:
rocknix:
config: rocknix.yml
status: active
extract_to: /storage/roms/bios/
logo: https://avatars.githubusercontent.com/u/152618023
scraper: rocknix
cores: all_libretro
@@ -959,6 +968,7 @@ platforms:
retropie:
config: retropie.yml
status: archived
extract_to: ~/RetroPie/BIOS/
logo: https://avatars.githubusercontent.com/u/11378204
scraper: retropie
source: https://github.com/RetroPie/RetroPie-Setup
@@ -975,6 +985,7 @@ platforms:
bizhawk:
config: bizhawk.yml
status: active
extract_to: Firmware/
logo: https://avatars.githubusercontent.com/u/11743303
scraper: bizhawk
source_url: https://raw.githubusercontent.com/TASEmulators/BizHawk/master/src/BizHawk.Emulation.Common/Database/FirmwareDatabase.cs
@@ -1039,6 +1050,7 @@ platforms:
misterfpga:
config: misterfpga.yml
status: active
extract_to: /media/fat/games/
logo: https://avatars.githubusercontent.com/u/47264183
scraper: misterfpga
source_url: https://raw.githubusercontent.com/ajgowans/BiosDB_MiSTer/db/bios_db.json.zip
+32 -15
View File
@@ -118,6 +118,35 @@ def release_totals(platform_name: str, record: dict) -> tuple[int | None, int |
return pack["files"], pack["extracted_size"]
def extract_targets(platforms_dir: str) -> list[tuple[str, str]]:
"""(display name, folder) per registered platform, where its pack extracts.
Read from the registry so the README, the site and the pack guide answer
from one place. Sorted by display name.
"""
rows = [
(load_platform_config(key, platforms_dir).get("platform", key), entry["extract_to"])
for key, entry in load_platform_registry(platforms_dir).items()
if entry.get("extract_to")
]
return sorted(rows, key=lambda row: row[0].casefold())
def extract_notes(platforms_dir: str) -> list[str]:
"""A pack whose entries carry their own root extracts above the BIOS folder."""
folders = dict(extract_targets(platforms_dir))
notes = []
for key in sorted(load_platform_registry(platforms_dir)):
config = load_platform_config(key, platforms_dir)
display = config.get("platform", key)
if config.get("base_destination") == "" and display in folders:
notes.append(
f"The {display} pack already carries its own `bios/` folder, so it"
f" extracts into `{folders[display]}` rather than into the BIOS folder."
)
return notes
def download_table(
coverages: dict,
archived: set[str],
@@ -365,18 +394,7 @@ def generate_readme(db: dict, platforms_dir: str) -> str:
# a pack whose entries already carry their own root (RetroDECK) extracts
# one level above it.
extract_paths = {
"RetroArch": "`system/`",
"Lakka": "`/storage/system/`",
"Batocera": "`/userdata/bios/`",
"BizHawk": "`Firmware/`",
"Recalbox": "`/recalbox/share/bios/`",
"RetroBat": "`bios/`",
"RetroPie": "`~/RetroPie/BIOS/`",
"RetroDECK": "`~/retrodeck/`",
"EmuDeck": "`~/Emulation/bios/`",
"RomM": "`bios/{platform_slug}/`",
"ROCKNIX": "`/storage/roms/bios/`",
"MiSTer FPGA": "`/media/fat/games/`",
display: f"`{folder}`" for display, folder in extract_targets(platforms_dir)
}
archived = {
name
@@ -390,12 +408,11 @@ def generate_readme(db: dict, platforms_dir: str) -> str:
)
)
for note in extract_notes(platforms_dir):
lines.extend(["", note])
if archived:
lines.extend(
[
"",
"The RetroDECK pack already contains its own `bios/` folder, so it"
" extracts into `~/retrodeck/` rather than into the BIOS folder.",
"",
"\\* Archived: the configuration is kept and packs are still built,"
" but upstream is no longer scraped on a schedule.",
+22 -18
View File
@@ -51,7 +51,13 @@ from nativemode import reads_file_contents
yaml = require_yaml()
from generate_readme import compute_coverage, contributing_text, release_totals
from generate_readme import (
compute_coverage,
contributing_text,
extract_notes,
extract_targets,
release_totals,
)
from profile_sync import source_ref_values, split_source_ref
from provenance_report import build_report
import release_record
@@ -200,7 +206,11 @@ def _timestamp() -> str:
def generate_home(
db: dict, coverages: dict, profiles: dict, registry: dict | None = None
db: dict,
coverages: dict,
profiles: dict,
registry: dict | None = None,
platforms_dir: str = "platforms",
) -> str:
total_files = db.get("total_files", 0)
total_size = db.get("total_size", 0)
@@ -318,22 +328,14 @@ def generate_home(
"",
" | Platform | Extract to |",
" |----------|-----------|",
" | RetroArch | `system/` |",
" | Batocera | `/userdata/bios/` |",
" | BizHawk | `Firmware/` |",
" | EmuDeck | `~/Emulation/bios/` |",
" | Lakka | `/storage/system/` |",
" | MiSTer FPGA | `/media/fat/games/` |",
" | ROCKNIX | `/storage/roms/bios/` |",
" | Recalbox | `/recalbox/share/bios/` |",
" | RetroBat | `bios/` |",
" | RetroDECK | `~/retrodeck/` |",
" | RetroPie | `~/RetroPie/BIOS/` |",
" | RomM | `bios/{platform_slug}/` |",
*(
f" | {display} | `{folder}` |"
for display, folder in extract_targets(platforms_dir)
),
"",
" The RetroDECK pack already carries its own `bios/` folder, so it "
"extracts one level above it. Every other pack extracts straight into "
"the BIOS folder. [Full instructions per setup](which-pack.md).",
*(f" {note}" for note in extract_notes(platforms_dir)),
" Every other pack extracts straight into the BIOS folder."
" [Full instructions per setup](which-pack.md).",
"",
]
)
@@ -3608,7 +3610,9 @@ def main():
# Generate home
print("Generating home page...")
write_if_changed(
str(docs / "index.md"), generate_home(db, coverages, profiles, registry)
str(docs / "index.md"), generate_home(
db, coverages, profiles, registry, args.platforms_dir
)
)
stats = compute_stats(db, coverages, profiles)
+60
View File
@@ -0,0 +1,60 @@
"""Where a pack extracts is read from the registry, by the README and the site.
Both kept a hand table keyed by display name. RomM's row said
`bios/{platform_slug}/` while the pack already carries one folder per slug
at its root, so following it nested every file one level too deep. The
README's RetroDECK sentence sat inside the archived-platforms block and
would have vanished the day RetroPie became active again.
"""
from __future__ import annotations
import sys
import unittest
from pathlib import Path
REPO_ROOT = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(REPO_ROOT / "scripts"))
from common import load_platform_config, load_platform_registry
from generate_readme import extract_notes, extract_targets
PLATFORMS = str(REPO_ROOT / "platforms")
class ExtractTargets(unittest.TestCase):
def test_every_registered_platform_says_where_it_extracts(self):
registry = load_platform_registry(PLATFORMS)
missing = sorted(k for k, v in registry.items() if not v.get("extract_to"))
self.assertEqual(missing, [])
self.assertEqual(len(extract_targets(PLATFORMS)), len(registry))
def test_a_folder_names_no_placeholder(self):
"""The pack lays out the per-system folders itself."""
templated = [d for d, folder in extract_targets(PLATFORMS) if "{" in folder]
self.assertEqual(templated, [])
def test_a_pack_with_its_own_root_is_explained_whatever_is_archived(self):
rooted = sorted(
load_platform_config(key, PLATFORMS).get("platform", key)
for key in load_platform_registry(PLATFORMS)
if load_platform_config(key, PLATFORMS).get("base_destination") == ""
)
explained = sorted(
display for display in rooted
if any(note.startswith(f"The {display} pack") for note in extract_notes(PLATFORMS))
)
self.assertTrue(rooted)
self.assertEqual(explained, rooted)
def test_no_generator_keeps_its_own_table(self):
"""The which-pack page describes setups per OS; these two were the
per-platform copies of the registry."""
readme = (REPO_ROOT / "scripts" / "generate_readme.py").read_text(encoding="utf-8")
site = (REPO_ROOT / "scripts" / "generate_site.py").read_text(encoding="utf-8")
self.assertNotIn('"RetroDECK": "`~/retrodeck/`"', readme)
self.assertNotIn('" | RetroDECK | `~/retrodeck/` |"', site)
if __name__ == "__main__":
unittest.main()