The site serves install.sh at /retrobios/i and install.ps1 at
/retrobios/i.ps1. generate_site.py writes both copies with the
installer address set to install.py at the commit the site is built
from (GITHUB_SHA in CI, HEAD locally), so the pinned SHA-256 and the
downloaded installer always come from one commit, including while a
deploy is still running.
Every command a user copies names the short address. The raw form
stays on the installer page as the fallback. Deploy Site now runs on
changes to install.sh and install.ps1. The install box weight keeps
the address length its ratio was fitted on, so no console page moves.
get/<platform>/ lists the files of the current release pack, read from
release.json, or gives the command for a setup without one. The README,
setup pages, Get your files and the release notes link it instead of
asset URLs, which die with each deleted tag. Setups without a ZIP say so
with the command beside it, and validate_site checks every get/ page.
A 2 GB part drew a 98-column line, and on an 80-column console every redraw wrapped and left a copy behind. The bar now shrinks to the width and goes below ten columns of room.
Profiles, the wiki, comments, docstrings, command output and schema descriptions carried em-dashes, clause-joining semicolons, unicode arrows, box-drawing banners and check-mark glyphs. Each sentence was rewritten rather than having its character swapped. Hashes, paths, source_ref values and every cited file:line are unchanged, which a comparison of each parsed profile against the previous revision confirms.
validate_pr comments now say PASS and FAIL in words, and source_ref values in a profile's structured blocks render as code. test_prose_style fails if any of these comes back, in tracked files or in the generated site.
Fifty options appeared in no page. fileless_audit also gains --all, so
its example sweeps instead of naming three settled profiles, and it and
download.py --info now fail on an unknown name or an unreachable source.
argparse completed a prefix into the only flag starting with it:
slots.py --emulator read profiles from a directory named after the
emulator and reported nothing, and pipeline.py --all built every pack
variant. Every parser now refuses an abbreviation.
Run ruff check --fix: remove unused imports (F401), fix f-strings
without placeholders (F541), remove unused variables (F841), fix
duplicate dict key (F601).
Run isort --profile black: normalize import ordering across all files.
Run ruff format: apply consistent formatting (black-compatible) to
all 58 Python files.
3 intentional E402 remain (imports after require_yaml() must execute
after yaml is available).
- fix KeyError in compute_coverage (generate_readme, generate_site)
- fix comma-separated MD5 handling in generate_pack check_inside_zip
- fix _verify_file_hash to handle multi-MD5 for large files
- fix external downloads not tracked in seen_destinations/file_status
- fix tar path traversal in _is_safe_tar_member (refresh_data_dirs)
- fix predictable tmp path in download.py
- fix _sanitize_path to filter "." components
- remove blanket data_dir suppression in find_undeclared_files
- remove blanket data_dir suppression in cross_reference
- add status_counts to verify_platform return value
- add md5_composite cache for repeated ZIP hashing
Critical: stream large file downloads (OOM fix), fix basename match
in auto_fetch, include hashes in pack grouping fingerprint, handle
not_in_zip status in verify, fix escaped quotes in batocera parser.
Important: deduplicate shared group includes, catch coreinfo network
errors, fix NODEDUP path component match, fix CI word splitting on
spaces, replace bare except Exception in 3 files.
Minor: argparse in list_platforms, specific exceptions in download.py.