diff --git a/install.ps1 b/install.ps1 index 93d06c52..9223fe84 100644 --- a/install.ps1 +++ b/install.ps1 @@ -8,7 +8,7 @@ param( $ErrorActionPreference = "Stop" $defaultInstallUrl = "https://raw.githubusercontent.com/Abdess/retrobios/main/install.py" -$defaultInstallSha256 = "d35dc1707a5f5d65fb614f45ed71f47e20e9ffcb4b28470e757cc66533c91ef2" +$defaultInstallSha256 = "4b5cd67a7077141c82a859231c3daba3dee11a62e022472191ea9f0a80e8fc61" $maximumInstallerBytes = 2MB $installerExit = 0 $installer = if ($PSScriptRoot) { Join-Path $PSScriptRoot "install.py" } else { $null } diff --git a/install.py b/install.py index d98c32be..35508a12 100644 --- a/install.py +++ b/install.py @@ -3469,7 +3469,8 @@ def main() -> None: "--system", action="append", metavar="NAME", - help="install only these systems (repeat or comma-separate; see --list-systems)", + help="install only these systems (repeat or comma-separate; see " + "--list-systems)", ) parser.add_argument( "--core", @@ -3518,6 +3519,7 @@ def main() -> None: "--version", action="version", version=f"retrobios installer {installer_id()} (ref {RELEASE_REF})", + help="print the installer version and exit", ) args = parser.parse_args() diff --git a/install.sh b/install.sh index 141ff853..98cd6de1 100755 --- a/install.sh +++ b/install.sh @@ -18,7 +18,7 @@ esac TEMP_INSTALLER="" TEMP_DIRECTORY="" DEFAULT_INSTALL_URL="https://raw.githubusercontent.com/Abdess/retrobios/main/install.py" -DEFAULT_INSTALL_SHA256="d35dc1707a5f5d65fb614f45ed71f47e20e9ffcb4b28470e757cc66533c91ef2" +DEFAULT_INSTALL_SHA256="4b5cd67a7077141c82a859231c3daba3dee11a62e022472191ea9f0a80e8fc61" MAX_INSTALLER_BYTES=2097152 cleanup() { diff --git a/scripts/auto_fetch.py b/scripts/auto_fetch.py index 3704a5c4..9fd93b9e 100644 --- a/scripts/auto_fetch.py +++ b/scripts/auto_fetch.py @@ -424,9 +424,18 @@ def main() -> None: parser.add_argument( "--dry-run", action="store_true", help="Don't download, just report" ) - parser.add_argument("--db", default=DEFAULT_DB) - parser.add_argument("--platforms-dir", default=DEFAULT_PLATFORMS_DIR) - parser.add_argument("--bios-dir", default=DEFAULT_BIOS_DIR) + parser.add_argument( + "--db", default=DEFAULT_DB, + help="database file to read (default: %(default)s)", + ) + parser.add_argument( + "--platforms-dir", default=DEFAULT_PLATFORMS_DIR, + help="platform YAML directory (default: %(default)s)", + ) + parser.add_argument( + "--bios-dir", default=DEFAULT_BIOS_DIR, + help="BIOS collection directory (default: %(default)s)", + ) parser.add_argument( "--create-issues", action="store_true", help="Output GitHub Issue bodies" ) diff --git a/scripts/check_buildbot_system.py b/scripts/check_buildbot_system.py index 61733317..bcd3b133 100644 --- a/scripts/check_buildbot_system.py +++ b/scripts/check_buildbot_system.py @@ -189,7 +189,10 @@ def main() -> None: dest="json_output", help="Machine-readable JSON output", ) - parser.add_argument("--registry", default=DEFAULT_REGISTRY) + parser.add_argument( + "--registry", default=DEFAULT_REGISTRY, + help="the data directory registry to check (default: %(default)s)", + ) args = parser.parse_args() report = check(args.registry) diff --git a/scripts/check_freshness.py b/scripts/check_freshness.py index 7f582294..cc2d059e 100644 --- a/scripts/check_freshness.py +++ b/scripts/check_freshness.py @@ -1166,14 +1166,36 @@ def main() -> int: parser = argparse.ArgumentParser(allow_abbrev=False, description=__doc__.split("\n\n")[0]) parser.add_argument("--only", help="comma-separated areas: " + ",".join(AREAS)) parser.add_argument("--json", action="store_true", help="machine-readable output") - parser.add_argument("--profiles", action="store_true", help="also run profile_sync (slow)") - parser.add_argument("--offline", action="store_true", help="no network, local ages only") + parser.add_argument( + "--profiles", action="store_true", + help="also run profile_sync (slow)", + ) + parser.add_argument( + "--offline", action="store_true", + help="no network, local ages only", + ) parser.add_argument("--jobs", type=int, default=4, help="parallel scrapers") - parser.add_argument("--cache-dir", default=upstream.CACHE_DIR) - parser.add_argument("--native-cache-dir", default=export_native.DEFAULT_CACHE) - parser.add_argument("--truth-dir", default="dist/truth") - parser.add_argument("--platforms-dir", default="platforms") - parser.add_argument("--emulators-dir", default="emulators") + parser.add_argument( + "--cache-dir", default=upstream.CACHE_DIR, + help="download cache directory (default: %(default)s)", + ) + parser.add_argument( + "--native-cache-dir", default=export_native.DEFAULT_CACHE, + help="where the platforms' own files are cached (default: %(default)s)", + ) + parser.add_argument( + "--truth-dir", default="dist/truth", + help="directory of the truth models generate_truth writes (default: " + "%(default)s)", + ) + parser.add_argument( + "--platforms-dir", default="platforms", + help="platform YAML directory (default: %(default)s)", + ) + parser.add_argument( + "--emulators-dir", default="emulators", + help="emulator profile directory (default: %(default)s)", + ) args = parser.parse_args() areas = tuple(a.strip() for a in args.only.split(",")) if args.only else AREAS diff --git a/scripts/check_release.py b/scripts/check_release.py index 8890e1a9..d43e2283 100644 --- a/scripts/check_release.py +++ b/scripts/check_release.py @@ -150,14 +150,20 @@ def fetch_sums(tag: str) -> str: def main() -> int: parser = argparse.ArgumentParser(allow_abbrev=False, description=__doc__.split("\n")[0]) - parser.add_argument("--record", default=str(RECORD), help="release record (release.json)") - parser.add_argument("--tag", help="release to check (default: the tag the record names)") + parser.add_argument( + "--record", default=str(RECORD), + help="release record (release.json)", + ) + parser.add_argument( + "--tag", + help="release to check (default: the tag the record names)", + ) parser.add_argument( "--sums", metavar="FILE", help=f"local {SUMS} the packs were listed in; its copy and signature on " f"the release must be these files (default: the list attached to the release)", ) - parser.add_argument("--json", action="store_true") + parser.add_argument("--json", action="store_true", help="JSON output") args = parser.parse_args() record = load_record(args.record) diff --git a/scripts/check_release_assets.py b/scripts/check_release_assets.py index 71896e43..a99dd776 100644 --- a/scripts/check_release_assets.py +++ b/scripts/check_release_assets.py @@ -319,9 +319,15 @@ def fetch_assets() -> dict[str, int]: def main() -> int: parser = argparse.ArgumentParser(allow_abbrev=False, description=__doc__.split("\n")[0]) - parser.add_argument("--db", default="database.json") - parser.add_argument("--gitignore", default=".gitignore") - parser.add_argument("--json", action="store_true") + parser.add_argument( + "--db", default="database.json", + help="database file to read (default: %(default)s)", + ) + parser.add_argument( + "--gitignore", default=".gitignore", + help="the .gitignore listing release-asset files (default: %(default)s)", + ) + parser.add_argument("--json", action="store_true", help="JSON output") parser.add_argument( "--notes", metavar="FILE", help="write the release page rendered from the collection to FILE", diff --git a/scripts/cross_reference.py b/scripts/cross_reference.py index c3c1f067..24951b49 100644 --- a/scripts/cross_reference.py +++ b/scripts/cross_reference.py @@ -788,9 +788,18 @@ def print_report( def main() -> None: parser = argparse.ArgumentParser(allow_abbrev=False, description="Emulator vs platform gap analysis") - parser.add_argument("--emulators-dir", default=DEFAULT_EMULATORS_DIR) - parser.add_argument("--platforms-dir", default=DEFAULT_PLATFORMS_DIR) - parser.add_argument("--db", default=DEFAULT_DB) + parser.add_argument( + "--emulators-dir", default=DEFAULT_EMULATORS_DIR, + help="emulator profile directory (default: %(default)s)", + ) + parser.add_argument( + "--platforms-dir", default=DEFAULT_PLATFORMS_DIR, + help="platform YAML directory (default: %(default)s)", + ) + parser.add_argument( + "--db", default=DEFAULT_DB, + help="database file to read (default: %(default)s)", + ) parser.add_argument("--emulator", "-e", help="Analyze single emulator") parser.add_argument( "--platform", "-p", type=platform_arg, help="Restrict analysis to one platform's cores" diff --git a/scripts/dedup.py b/scripts/dedup.py index 7005bdbb..78c2a903 100644 --- a/scripts/dedup.py +++ b/scripts/dedup.py @@ -317,7 +317,10 @@ def main() -> None: parser.add_argument( "--dry-run", action="store_true", help="Preview without deleting" ) - parser.add_argument("--bios-dir", default=DEFAULT_BIOS_DIR) + parser.add_argument( + "--bios-dir", default=DEFAULT_BIOS_DIR, + help="BIOS collection directory (default: %(default)s)", + ) args = parser.parse_args() require_directory(args.bios_dir) diff --git a/scripts/diff_truth.py b/scripts/diff_truth.py index a9a8cf20..ce765683 100644 --- a/scripts/diff_truth.py +++ b/scripts/diff_truth.py @@ -176,14 +176,22 @@ def main() -> None: "--json", action="store_true", dest="json_output", help="JSON output" ) output.add_argument( - "--format", choices=["terminal", "markdown"], default="terminal" + "--format", choices=["terminal", "markdown"], default="terminal", + help="report format (default: %(default)s)", ) output.add_argument( "--markdown", action="store_const", const="markdown", dest="format", help="same as --format markdown, the spelling validate_pr uses", ) - parser.add_argument("--truth-dir", default="dist/truth") - parser.add_argument("--platforms-dir", default="platforms") + parser.add_argument( + "--truth-dir", default="dist/truth", + help="directory of the truth models generate_truth writes (default: " + "%(default)s)", + ) + parser.add_argument( + "--platforms-dir", default="platforms", + help="platform YAML directory (default: %(default)s)", + ) parser.add_argument( "--target", help="read the models generate_truth --target wrote, each under the " diff --git a/scripts/export_native.py b/scripts/export_native.py index 92604aed..93800bf8 100644 --- a/scripts/export_native.py +++ b/scripts/export_native.py @@ -574,9 +574,19 @@ def main() -> None: group = parser.add_mutually_exclusive_group(required=True) group.add_argument("--all", action="store_true", help="every platform") group.add_argument("--platform", type=platform_arg, help="a single platform") - parser.add_argument("--output-dir", default="dist/upstream") - parser.add_argument("--truth-dir", default="dist/truth") - parser.add_argument("--platforms-dir", default="platforms") + parser.add_argument( + "--output-dir", default="dist/upstream", + help="directory the corrected platform files go to (default: %(default)s)", + ) + parser.add_argument( + "--truth-dir", default="dist/truth", + help="directory of the truth models generate_truth writes (default: " + "%(default)s)", + ) + parser.add_argument( + "--platforms-dir", default="platforms", + help="platform YAML directory (default: %(default)s)", + ) parser.add_argument( "--upstream-dir", default=DEFAULT_CACHE, diff --git a/scripts/fileless_audit.py b/scripts/fileless_audit.py index 2c08bd44..8c181e42 100644 --- a/scripts/fileless_audit.py +++ b/scripts/fileless_audit.py @@ -107,9 +107,18 @@ def main() -> None: "--all", action="store_true", help="every profile that declares no files and has no answer yet", ) - parser.add_argument("--emulators-dir", default="emulators") - parser.add_argument("--cache-dir", default=".cache") - parser.add_argument("--offline", action="store_true") + parser.add_argument( + "--emulators-dir", default="emulators", + help="emulator profile directory (default: %(default)s)", + ) + parser.add_argument( + "--cache-dir", default=".cache", + help="download cache directory (default: %(default)s)", + ) + parser.add_argument( + "--offline", action="store_true", + help="read only what the cache holds; no network access", + ) args = parser.parse_args() if args.all == bool(args.emulators): parser.error("name profiles or pass --all, not both") diff --git a/scripts/find_pinned_revision.py b/scripts/find_pinned_revision.py index a7821311..42f1aa40 100644 --- a/scripts/find_pinned_revision.py +++ b/scripts/find_pinned_revision.py @@ -74,7 +74,10 @@ def main() -> int: parser.add_argument("--path", required=True, help="path of the file in the project") parser.add_argument("--md5", required=True, help="md5 the platform pins") parser.add_argument("--write", type=Path, help="save the matching bytes here") - parser.add_argument("--cache-dir", default=upstream.CACHE_DIR) + parser.add_argument( + "--cache-dir", default=upstream.CACHE_DIR, + help="download cache directory (default: %(default)s)", + ) args = parser.parse_args() repo = upstream.parse_repo(args.repo) diff --git a/scripts/generate_pack.py b/scripts/generate_pack.py index 86a0c878..e85d9efe 100644 --- a/scripts/generate_pack.py +++ b/scripts/generate_pack.py @@ -2952,7 +2952,10 @@ def main() -> None: def _main(held: contextlib.ExitStack) -> None: parser = argparse.ArgumentParser(allow_abbrev=False, description="Generate platform BIOS ZIP packs") - parser.add_argument("--platform", "-p", type=platform_arg, help="Platform name (e.g., retroarch)") + parser.add_argument( + "--platform", "-p", type=platform_arg, + help="Platform name (e.g., retroarch)", + ) parser.add_argument( "--all", action="store_true", help="Generate packs for all active platforms" ) @@ -2970,11 +2973,23 @@ def _main(held: contextlib.ExitStack) -> None: parser.add_argument( "--include-archived", action="store_true", help="Include archived platforms" ) - parser.add_argument("--platforms-dir", default=DEFAULT_PLATFORMS_DIR) + parser.add_argument( + "--platforms-dir", default=DEFAULT_PLATFORMS_DIR, + help="platform YAML directory (default: %(default)s)", + ) parser.add_argument("--db", default=DEFAULT_DB_FILE, help="Path to database.json") - parser.add_argument("--bios-dir", default=DEFAULT_BIOS_DIR) - parser.add_argument("--output-dir", "-o", default=DEFAULT_OUTPUT_DIR) - parser.add_argument("--emulators-dir", default="emulators") + parser.add_argument( + "--bios-dir", default=DEFAULT_BIOS_DIR, + help="BIOS collection directory (default: %(default)s)", + ) + parser.add_argument( + "--output-dir", "-o", default=DEFAULT_OUTPUT_DIR, + help="directory the packs and manifests go to (default: %(default)s)", + ) + parser.add_argument( + "--emulators-dir", default="emulators", + help="emulator profile directory (default: %(default)s)", + ) parser.add_argument( "--offline", action="store_true", @@ -3002,7 +3017,8 @@ def _main(held: contextlib.ExitStack) -> None: "--source", choices=["platform", "truth", "full"], default="full", - help="File source: platform (YAML only), truth (emulator profiles), full (both)", + help="File source: platform (YAML only), truth (emulator profiles), full " + "(both)", ) parser.add_argument( "--all-variants", diff --git a/scripts/generate_readme.py b/scripts/generate_readme.py index 8f786d18..82aef685 100644 --- a/scripts/generate_readme.py +++ b/scripts/generate_readme.py @@ -756,8 +756,14 @@ def generate_contributing() -> str: def main() -> None: parser = argparse.ArgumentParser(allow_abbrev=False, description="Generate slim README.md") - parser.add_argument("--db", default="database.json") - parser.add_argument("--platforms-dir", default="platforms") + parser.add_argument( + "--db", default="database.json", + help="database file to read (default: %(default)s)", + ) + parser.add_argument( + "--platforms-dir", default="platforms", + help="platform YAML directory (default: %(default)s)", + ) args = parser.parse_args() db = load_database(args.db) diff --git a/scripts/generate_site.py b/scripts/generate_site.py index b151ec42..e19ee4b2 100644 --- a/scripts/generate_site.py +++ b/scripts/generate_site.py @@ -4244,10 +4244,22 @@ def main() -> None: allow_abbrev=False, description="Generate MkDocs site from project data" ) - parser.add_argument("--db", default="database.json") - parser.add_argument("--platforms-dir", default="platforms") - parser.add_argument("--emulators-dir", default="emulators") - parser.add_argument("--docs-dir", default=DOCS_DIR) + parser.add_argument( + "--db", default="database.json", + help="database file to read (default: %(default)s)", + ) + parser.add_argument( + "--platforms-dir", default="platforms", + help="platform YAML directory (default: %(default)s)", + ) + parser.add_argument( + "--emulators-dir", default="emulators", + help="emulator profile directory (default: %(default)s)", + ) + parser.add_argument( + "--docs-dir", default=DOCS_DIR, + help="directory the site sources are written to (default: %(default)s)", + ) args = parser.parse_args() try: # Two runs over one docs/ delete each other's pages and scratch diff --git a/scripts/generate_truth.py b/scripts/generate_truth.py index e83ad6b7..f7c4baa3 100644 --- a/scripts/generate_truth.py +++ b/scripts/generate_truth.py @@ -58,10 +58,12 @@ def parse_args(argv: list[str] | None = None) -> argparse.Namespace: parser.add_argument( "--platforms-dir", default=DEFAULT_PLATFORMS_DIR, + help="platform YAML directory (default: %(default)s)", ) parser.add_argument( "--emulators-dir", default=DEFAULT_EMULATORS_DIR, + help="emulator profile directory (default: %(default)s)", ) parser.add_argument("--db", default=DEFAULT_DB_FILE, help="database.json path") return parser.parse_args(argv) diff --git a/scripts/identity.py b/scripts/identity.py index fd6572a5..1400c6ca 100644 --- a/scripts/identity.py +++ b/scripts/identity.py @@ -145,7 +145,10 @@ def main() -> int: allow_abbrev=False, description="Report one content stored under identities that disagree.", ) - parser.add_argument("--bios-dir", default="bios") + parser.add_argument( + "--bios-dir", default="bios", + help="BIOS collection directory (default: %(default)s)", + ) parser.add_argument("--json", action="store_true", help="JSON output") parser.add_argument( "--strict", action="store_true", help="exit non-zero when any is found" diff --git a/scripts/mame_ref_audit.py b/scripts/mame_ref_audit.py index d612b22b..677148ee 100644 --- a/scripts/mame_ref_audit.py +++ b/scripts/mame_ref_audit.py @@ -115,11 +115,23 @@ def rewrite(name: str, emulators_dir: str, findings: list[Finding]) -> int: def main() -> None: parser = argparse.ArgumentParser(allow_abbrev=False, description=__doc__.splitlines()[0]) - parser.add_argument("emulators", nargs="+") - parser.add_argument("--emulators-dir", default="emulators") - parser.add_argument("--cache-dir", default=upstream.CACHE_DIR) - parser.add_argument("--offline", action="store_true") - parser.add_argument("--write", action="store_true") + parser.add_argument("emulators", nargs="+", help="MAME-family profiles to audit") + parser.add_argument( + "--emulators-dir", default="emulators", + help="emulator profile directory (default: %(default)s)", + ) + parser.add_argument( + "--cache-dir", default=upstream.CACHE_DIR, + help="download cache directory (default: %(default)s)", + ) + parser.add_argument( + "--offline", action="store_true", + help="read only what the cache holds; no network access", + ) + parser.add_argument( + "--write", action="store_true", + help="rewrite the refs the audit can settle", + ) args = parser.parse_args() total = 0 diff --git a/scripts/pipeline.py b/scripts/pipeline.py index 3b9b1e67..dc532949 100644 --- a/scripts/pipeline.py +++ b/scripts/pipeline.py @@ -371,8 +371,16 @@ def main() -> None: "--output-dir", default="dist", help="Pack output directory (default: dist/)" ) parser.add_argument("--target", "-t", help="Hardware target (e.g., switch, rpi4)") - parser.add_argument("--source", choices=["platform", "truth", "full"], default="full") - parser.add_argument("--all-variants", action="store_true") + parser.add_argument( + "--source", choices=["platform", "truth", "full"], default="full", + help="packs to build: the platform list, the profiles, or both (default: " + "%(default)s)", + ) + parser.add_argument( + "--all-variants", action="store_true", + help="Build the six source x required packs of each platform; " + "not with --source or --skip-packs", + ) parser.add_argument( "--check-buildbot", action="store_true", diff --git a/scripts/profile_sync.py b/scripts/profile_sync.py index 0c981221..813f4ece 100644 --- a/scripts/profile_sync.py +++ b/scripts/profile_sync.py @@ -3193,34 +3193,73 @@ def build_parser() -> argparse.ArgumentParser: group = parser.add_mutually_exclusive_group(required=True) group.add_argument("--emulator", help="a single profile") group.add_argument("--all", action="store_true", help="every profile") - parser.add_argument("--emulators-dir", default="emulators") + parser.add_argument( + "--emulators-dir", default="emulators", + help="emulator profile directory (default: %(default)s)", + ) parser.add_argument("--system", help="keep profiles covering this system") parser.add_argument("--type", dest="type_", help="keep profiles of this type") parser.add_argument("--stale-before", help="keep profiles profiled before a date") parser.add_argument("--limit", type=int, help="stop after N profiles") - parser.add_argument("--changed-only", action="store_true") + parser.add_argument( + "--changed-only", action="store_true", + help="list only the profiles with refs to review", + ) parser.add_argument( "--strict", action="store_true", help="exit 1 when a profile has refs to review, as for a new profile in CI", ) - parser.add_argument("--json", action="store_true", dest="as_json") - parser.add_argument("--markdown", action="store_true") + parser.add_argument( + "--json", action="store_true", dest="as_json", + help="JSON report", + ) + parser.add_argument( + "--markdown", action="store_true", + help="write a markdown report to --report-dir", + ) parser.add_argument( "--report-dir", default="reports", help="directory for the markdown report (default: reports)", ) - parser.add_argument("--fetch-plan", action="store_true") - parser.add_argument("--full-diff", action="store_true") + parser.add_argument( + "--fetch-plan", action="store_true", + help="print the upstream URLs a reader has to open", + ) + parser.add_argument( + "--full-diff", action="store_true", + help="print the upstream diff of every cited file since the pin", + ) parser.add_argument("--ref", help="restrict --full-diff to one cited path") - parser.add_argument("--context", type=int, default=3) - parser.add_argument("--check-version", action="store_true") - parser.add_argument("--detect-new-files", action="store_true") - parser.add_argument("--watch-hashes", action="store_true") - parser.add_argument("--tree-diff", action="store_true") - parser.add_argument("--triage", action="store_true") - parser.add_argument("--backfill-commits", action="store_true") + parser.add_argument( + "--context", type=int, default=3, + help="lines of context around each diff hunk (default: %(default)s)", + ) + parser.add_argument( + "--check-version", action="store_true", + help="compare core_version with the latest tag and release", + ) + parser.add_argument( + "--detect-new-files", action="store_true", + help="name files upstream loads that the profile does not list", + ) + parser.add_argument( + "--watch-hashes", action="store_true", + help="report hash literals that changed in the cited files", + ) + parser.add_argument( + "--tree-diff", action="store_true", + help="list files added, removed or renamed upstream since the pin", + ) + parser.add_argument( + "--triage", action="store_true", + help="rank the profiles by how much there is to reread", + ) + parser.add_argument( + "--backfill-commits", action="store_true", + help="write source_commit for profiles that only carry profiled_date", + ) parser.add_argument( "--rebase-refs", action="store_true", @@ -3242,10 +3281,22 @@ def build_parser() -> argparse.ArgumentParser: action="store_true", help="recale CHANGED refs too, after their diff has been read", ) - parser.add_argument("--dry-run", action="store_true") - parser.add_argument("--force", action="store_true") - parser.add_argument("--offline", action="store_true") - parser.add_argument("--cache-dir", default=DEFAULT_CACHE) + parser.add_argument( + "--dry-run", action="store_true", + help="print the writes and leave the profiles untouched", + ) + parser.add_argument( + "--force", action="store_true", + help="write even when emulators/ has uncommitted changes", + ) + parser.add_argument( + "--offline", action="store_true", + help="read only what the cache holds; no network access", + ) + parser.add_argument( + "--cache-dir", default=DEFAULT_CACHE, + help="download cache directory (default: %(default)s)", + ) return parser diff --git a/scripts/region_audit.py b/scripts/region_audit.py index a3ec6100..c3eef96f 100644 --- a/scripts/region_audit.py +++ b/scripts/region_audit.py @@ -195,7 +195,10 @@ def main() -> int: description="Cross-check profile region: values against No-Intro provenance" ) parser.add_argument("--db", default="database.json", help="Path to database.json") - parser.add_argument("--emulators-dir", default="emulators") + parser.add_argument( + "--emulators-dir", default="emulators", + help="emulator profile directory (default: %(default)s)", + ) parser.add_argument("--json", action="store_true", help="Machine-readable output") args = parser.parse_args() diff --git a/scripts/release_record.py b/scripts/release_record.py index 86e1844f..3c110e5f 100644 --- a/scripts/release_record.py +++ b/scripts/release_record.py @@ -127,8 +127,14 @@ def main() -> int: parser = argparse.ArgumentParser(allow_abbrev=False, description="Record what a release's packs hold") parser.add_argument("dist", type=Path, help="directory of the packs to publish") parser.add_argument("--tag", required=True, help="release tag, e.g. v2026.10.04") - parser.add_argument("--install-dir", default="install", type=Path) - parser.add_argument("--output", default=RECORD, type=Path) + parser.add_argument( + "--install-dir", default="install", type=Path, + help="manifests the archives are compared with (default: %(default)s)", + ) + parser.add_argument( + "--output", default=RECORD, type=Path, + help="record to write (default: %(default)s)", + ) args = parser.parse_args() try: diff --git a/scripts/restore_large_files.py b/scripts/restore_large_files.py index eb878c9d..1c842229 100644 --- a/scripts/restore_large_files.py +++ b/scripts/restore_large_files.py @@ -93,9 +93,18 @@ def restore( def main() -> None: parser = argparse.ArgumentParser(allow_abbrev=False, description=__doc__) - parser.add_argument("--cache", default=".cache/large") - parser.add_argument("--db", default="database.json") - parser.add_argument("--gitignore", default=".gitignore") + parser.add_argument( + "--cache", default=".cache/large", + help="where release assets are cached (default: %(default)s)", + ) + parser.add_argument( + "--db", default="database.json", + help="database file to read (default: %(default)s)", + ) + parser.add_argument( + "--gitignore", default=".gitignore", + help="the .gitignore listing release-asset files (default: %(default)s)", + ) args = parser.parse_args() _restored, unsatisfied = restore(args.cache, args.db, args.gitignore) if unsatisfied: diff --git a/scripts/romset_recipes.py b/scripts/romset_recipes.py index d4decde4..02d40d47 100644 --- a/scripts/romset_recipes.py +++ b/scripts/romset_recipes.py @@ -477,10 +477,22 @@ def main() -> int: help="write reconstructions to .variants/ (implies --missing)", ) parser.add_argument("--json", action="store_true", help="machine-readable output") - parser.add_argument("--bios-dir", default="bios") - parser.add_argument("--platforms-dir", default="platforms") - parser.add_argument("--emulators-dir", default="emulators") - parser.add_argument("--db", default="database.json") + parser.add_argument( + "--bios-dir", default="bios", + help="BIOS collection directory (default: %(default)s)", + ) + parser.add_argument( + "--platforms-dir", default="platforms", + help="platform YAML directory (default: %(default)s)", + ) + parser.add_argument( + "--emulators-dir", default="emulators", + help="emulator profile directory (default: %(default)s)", + ) + parser.add_argument( + "--db", default="database.json", + help="database file to read (default: %(default)s)", + ) parser.add_argument( "--dat-recipes", default="recipes", diff --git a/scripts/scraper/coreinfo_scraper.py b/scripts/scraper/coreinfo_scraper.py index dce58bd8..40c35db7 100644 --- a/scripts/scraper/coreinfo_scraper.py +++ b/scripts/scraper/coreinfo_scraper.py @@ -311,7 +311,10 @@ def main() -> None: allow_abbrev=False, description="Scrape libretro-core-info firmware requirements" ) - parser.add_argument("--dry-run", action="store_true") + parser.add_argument( + "--dry-run", action="store_true", + help="print what would change and write nothing", + ) parser.add_argument("--compare-db", help="Compare against database.json") args = parser.parse_args() diff --git a/scripts/scraper/dat_pack_importer.py b/scripts/scraper/dat_pack_importer.py index 647ca781..33dc62bb 100644 --- a/scripts/scraper/dat_pack_importer.py +++ b/scripts/scraper/dat_pack_importer.py @@ -92,7 +92,10 @@ def import_pack(source: str, pack: Path) -> tuple[dict, list[dict], int]: def main() -> int: parser = argparse.ArgumentParser(allow_abbrev=False, description="Import BIOS provenance from a DAT pack") - parser.add_argument("--source", required=True, choices=SOURCES) + parser.add_argument( + "--source", required=True, choices=SOURCES, + help="catalog the pack comes from", + ) parser.add_argument("--pack", required=True, help="DAT pack (ZIP or directory)") parser.add_argument("--output", "-o", help="Snapshot output path") parser.add_argument("--dry-run", action="store_true", help="Show imported entries") diff --git a/scripts/scraper/romset_dat_importer.py b/scripts/scraper/romset_dat_importer.py index 68b53ccb..584123aa 100644 --- a/scripts/scraper/romset_dat_importer.py +++ b/scripts/scraper/romset_dat_importer.py @@ -453,7 +453,10 @@ def _listxml_opener(pack: Path) -> Callable[[], io.BufferedIOBase]: def main() -> int: parser = argparse.ArgumentParser(allow_abbrev=False, description=__doc__) - parser.add_argument("--source", choices=SOURCES, required=True) + parser.add_argument( + "--source", choices=SOURCES, required=True, + help="emulator whose DATs are imported", + ) parser.add_argument("--pack", help="DAT file, ZIP or directory") parser.add_argument( "--fetch", @@ -462,14 +465,29 @@ def main() -> int: help="download upstream instead of using --pack " "(a MAME tag such as mame0289; bare, the newest release)", ) - parser.add_argument("--cache-dir", default=".cache/dats") - parser.add_argument("--output", default="") - parser.add_argument("--emulators-dir", default="emulators") - parser.add_argument("--platforms-dir", default="platforms") + parser.add_argument( + "--cache-dir", default=".cache/dats", + help="download cache directory (default: %(default)s)", + ) + parser.add_argument( + "--output", default="", + help="snapshot to write (default: recipes/.json)", + ) + parser.add_argument( + "--emulators-dir", default="emulators", + help="emulator profile directory (default: %(default)s)", + ) + parser.add_argument( + "--platforms-dir", default="platforms", + help="platform YAML directory (default: %(default)s)", + ) parser.add_argument( "--all", action="store_true", help="keep every set, not only referenced ones" ) - parser.add_argument("--dry-run", action="store_true") + parser.add_argument( + "--dry-run", action="store_true", + help="print what would change and write nothing", + ) args = parser.parse_args() blobs: dict[str, str] = {} diff --git a/scripts/slots.py b/scripts/slots.py index a3a9e3d8..eac475c6 100644 --- a/scripts/slots.py +++ b/scripts/slots.py @@ -862,10 +862,22 @@ def main() -> int: description="Report destinations where an emulator profile contradicts " "the file a platform baseline would ship.", ) - parser.add_argument("--platform", type=platform_arg, help="one platform instead of all") - parser.add_argument("--db", default="database.json") - parser.add_argument("--platforms-dir", default="platforms") - parser.add_argument("--emulators-dir", default="emulators") + parser.add_argument( + "--platform", type=platform_arg, + help="one platform instead of all", + ) + parser.add_argument( + "--db", default="database.json", + help="database file to read (default: %(default)s)", + ) + parser.add_argument( + "--platforms-dir", default="platforms", + help="platform YAML directory (default: %(default)s)", + ) + parser.add_argument( + "--emulators-dir", default="emulators", + help="emulator profile directory (default: %(default)s)", + ) parser.add_argument("--json", action="store_true", help="JSON output") parser.add_argument( "--include-archived", action="store_true", diff --git a/scripts/validate_pr.py b/scripts/validate_pr.py index 9e433e50..65976a17 100644 --- a/scripts/validate_pr.py +++ b/scripts/validate_pr.py @@ -423,8 +423,14 @@ def main() -> None: "--changed", action="store_true", help="Auto-detect changed BIOS files" ) parser.add_argument("--db", default=DEFAULT_DB, help="Path to database.json") - parser.add_argument("--platforms-dir", default=DEFAULT_PLATFORMS_DIR) - parser.add_argument("--emulators-dir", default=DEFAULT_EMULATORS_DIR) + parser.add_argument( + "--platforms-dir", default=DEFAULT_PLATFORMS_DIR, + help="platform YAML directory (default: %(default)s)", + ) + parser.add_argument( + "--emulators-dir", default=DEFAULT_EMULATORS_DIR, + help="emulator profile directory (default: %(default)s)", + ) # One output format: --json beside --markdown printed JSON and dropped # the markdown without a word. output = parser.add_mutually_exclusive_group() diff --git a/scripts/validate_site.py b/scripts/validate_site.py index d5bee228..72740561 100644 --- a/scripts/validate_site.py +++ b/scripts/validate_site.py @@ -265,9 +265,18 @@ def validate_site(site: Path, config_path: Path) -> list[str]: def main() -> None: parser = argparse.ArgumentParser(allow_abbrev=False, description=__doc__) - parser.add_argument("--site-dir", default="site") - parser.add_argument("--config", default="mkdocs.yml") - parser.add_argument("--max-errors", type=int, default=100) + parser.add_argument( + "--site-dir", default="site", + help="the built site (default: %(default)s)", + ) + parser.add_argument( + "--config", default="mkdocs.yml", + help="the MkDocs configuration (default: %(default)s)", + ) + parser.add_argument( + "--max-errors", type=int, default=100, + help="stop listing after this many errors (default: %(default)s)", + ) args = parser.parse_args() try: diff --git a/scripts/verify.py b/scripts/verify.py index 19580291..d5968e96 100644 --- a/scripts/verify.py +++ b/scripts/verify.py @@ -2202,7 +2202,10 @@ def _main(held: contextlib.ExitStack) -> None: parser.add_argument( "--list-systems", action="store_true", help="List available systems" ) - parser.add_argument("--include-archived", action="store_true") + parser.add_argument( + "--include-archived", action="store_true", + help="With --all, also verify the archived platforms (RetroPie)", + ) parser.add_argument("--target", "-t", help="Hardware target (e.g., switch, rpi4)") parser.add_argument( "--region", help="Region priority list, best first (e.g. us,eu,jp)" @@ -2212,9 +2215,18 @@ def _main(held: contextlib.ExitStack) -> None: action="store_true", help="List available targets for the platform", ) - parser.add_argument("--db", default=DEFAULT_DB) - parser.add_argument("--platforms-dir", default=DEFAULT_PLATFORMS_DIR) - parser.add_argument("--emulators-dir", default=DEFAULT_EMULATORS_DIR) + parser.add_argument( + "--db", default=DEFAULT_DB, + help="database file to read (default: %(default)s)", + ) + parser.add_argument( + "--platforms-dir", default=DEFAULT_PLATFORMS_DIR, + help="platform YAML directory (default: %(default)s)", + ) + parser.add_argument( + "--emulators-dir", default=DEFAULT_EMULATORS_DIR, + help="emulator profile directory (default: %(default)s)", + ) parser.add_argument( "--verbose", "-v", diff --git a/tests/test_workflow_paths.py b/tests/test_workflow_paths.py index f7106629..d0661884 100644 --- a/tests/test_workflow_paths.py +++ b/tests/test_workflow_paths.py @@ -122,6 +122,23 @@ class DocumentedSteps(unittest.TestCase): fields = [*schema["properties"], *item.get("properties", {})] self.assertEqual(sorted(f for f in fields if f"`{f}`" not in page), []) + def test_every_option_says_what_it_does(self): + """--include-archived and --all-variants, and 94 others, showed in + --help with no text: their constraints surfaced only as errors.""" + sources = [*SCRIPTS.rglob("*.py"), REPO_ROOT / "install.py"] + silent = [] + for path in sources: + tree = ast.parse(path.read_text(encoding="utf-8")) + for node in ast.walk(tree): + if ( + isinstance(node, ast.Call) + and getattr(node.func, "attr", None) == "add_argument" + and not any(k.arg == "help" for k in node.keywords) + ): + first = next((a.value for a in node.args if isinstance(a, ast.Constant)), "?") + silent.append(f"{path.relative_to(REPO_ROOT)}: {first}") + self.assertEqual(silent, []) + def test_the_scraper_recipe_names_every_abstract_method(self): """tools.md said implement fetch_requirements(); validate_format() is abstract too, and a scraper written from the page could not be built."""