fix: run the read-only tools from the repo root

Only verify.py and generate_pack.py moved to the repository root. From
any other folder slots, region_audit, provenance_report and bundled_only
said database.json was missing and to rebuild it, identity and
list_platforms named a missing folder, and game_rules ended on a
FileNotFoundError traceback. work_from_repo_root moves to common.py and
the eight tools call it: defaults are read from the root, a path the
user typed from where it was typed.
This commit is contained in:
Abdessamad Derraz committed 2026-11-06 15:09:35 +01:00
1 parent bf10ebaa82
commit 1b4b31fb32
11 files changed
+95 -24

No files matched your search

+3
View File
@@ -116,6 +116,9 @@ def main() -> int:
parser.add_argument("--json", action="store_true", help="print the list as JSON")
parser.add_argument("--strict", action="store_true", help="exit 1 while a file is listed")
args = parser.parse_args()
from common import work_from_repo_root # noqa: PLC0415
work_from_repo_root(args, parser, ["db", "emulators_dir", "platforms_dir", "install_dir"])
rows = bundled_only(
load_database(args.db), load_emulator_profiles(args.emulators_dir),
+26
View File
@@ -9,6 +9,7 @@ from __future__ import annotations
from collections.abc import Callable, Iterable
from collections import Counter
import argparse
import filecmp
import hashlib
import functools
@@ -670,6 +671,31 @@ def suggest_names(
return f"{listing_flag} lists all {total}."
def work_from_repo_root(
args: argparse.Namespace, parser: argparse.ArgumentParser, path_flags: list[str]
) -> None:
"""Run from the repository root, whichever directory the command started in.
database.json records every file from the root and the data registry
names its caches the same way, so a run from scripts/ ended on a
FileNotFoundError traceback. A path the caller typed is read from where
they typed it, a default from the root.
"""
root = Path(__file__).resolve().parent.parent
if Path.cwd().resolve() == root:
return
for flag in path_flags:
value = getattr(args, flag, None)
if value and value != parser.get_default(flag):
# A Path stays a Path for the code that joins onto it.
setattr(args, flag, type(value)(os.path.abspath(value)))
os.chdir(root)
if getattr(args, "platform", None):
# Read before the move, the registry was not there to map
# "RetroArch" to its slug.
args.platform = platform_arg(args.platform)
def platform_arg(value: str) -> str:
"""--platform as typed, mapped to the registry's slug when it names one.
+3
View File
@@ -1191,6 +1191,9 @@ def main() -> None:
"--list-emulators", action="store_true", help="List available emulators"
)
args = parser.parse_args()
from common import work_from_repo_root # noqa: PLC0415
work_from_repo_root(args, parser, ["emulators_dir", "platforms_dir", "db"])
if args.list_emulators:
ignored = [flag for flag, on in (
("--emulator", args.emulator), ("--platform", args.platform),
+3
View File
@@ -247,6 +247,9 @@ def main() -> int:
help="profiles the rules are checked against (default emulators)")
parser.add_argument("--json", action="store_true", help="print the summary as JSON")
args = parser.parse_args()
from common import work_from_repo_root # noqa: PLC0415
work_from_repo_root(args, parser, ["regions", "extras", "headers", "emulators_dir"])
regions = load_yaml(args.regions)
extras = load_yaml(args.extras)
+3
View File
@@ -146,6 +146,9 @@ def main() -> int:
"--strict", action="store_true", help="exit non-zero when any is found"
)
args = parser.parse_args()
from common import work_from_repo_root # noqa: PLC0415
work_from_repo_root(args, parser, ["bios_dir"])
from common import require_directory # noqa: PLC0415
require_directory(args.bios_dir)
+4 -1
View File
@@ -26,7 +26,10 @@ def list_platforms() -> list[str]:
def main() -> None:
parser = argparse.ArgumentParser(allow_abbrev=False, description="List available platforms")
parser.parse_args()
args = parser.parse_args()
from common import work_from_repo_root # noqa: PLC0415
work_from_repo_root(args, parser, [])
platforms = list_platforms()
+3
View File
@@ -384,6 +384,9 @@ def main() -> int:
"(the pipeline writes derivable.json)",
)
args = parser.parse_args()
from common import work_from_repo_root # noqa: PLC0415
work_from_repo_root(args, parser, ["db", "provenance_dir", "emulators_dir", "write_derivable"])
if args.write_derivable and not args.derive:
parser.error("--write-derivable records what --derive finds: pass both")
+3
View File
@@ -201,6 +201,9 @@ def main() -> int:
)
parser.add_argument("--json", action="store_true", help="Machine-readable output")
args = parser.parse_args()
from common import work_from_repo_root # noqa: PLC0415
work_from_repo_root(args, parser, ["db", "emulators_dir"])
db = load_database(args.db)
profiles = load_emulator_profiles(args.emulators_dir)
+3
View File
@@ -1009,6 +1009,9 @@ def main() -> int:
"without it the run reports them and exits 0",
)
args = parser.parse_args()
from common import work_from_repo_root # noqa: PLC0415
work_from_repo_root(args, parser, ["db", "platforms_dir", "emulators_dir"])
import contextlib
+1 -23
View File
@@ -41,6 +41,7 @@ from common import (
_foreign_tree,
_owner_tokens,
platform_arg,
work_from_repo_root,
target_listing_line,
suggest_names,
system_index,
@@ -130,29 +131,6 @@ DEFAULT_EMULATORS_DIR = "emulators"
REPO_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
def work_from_repo_root(
args: argparse.Namespace, parser: argparse.ArgumentParser, path_flags: list[str]
) -> None:
"""Run from the repository root, whichever directory the command started in.
database.json records every file from the root and the data registry
names its caches the same way, so a run from scripts/ ended on a
FileNotFoundError traceback. A path the caller typed is read from where
they typed it, a default from the root.
"""
if os.path.realpath(os.getcwd()) == os.path.realpath(REPO_ROOT):
return
for flag in path_flags:
value = getattr(args, flag, None)
if value and value != parser.get_default(flag):
setattr(args, flag, os.path.abspath(value))
os.chdir(REPO_ROOT)
if getattr(args, "platform", None):
# Read before the move, the registry was not there to map
# "RetroArch" to its slug.
args.platform = platform_arg(args.platform)
# Status model: aligned with Batocera BiosStatus (batocera-systems:967-969)