The site, the README and the wiki take the screen's row names and the
--check pass line from install.py, and the wiki's line menu example is
written by generate_installer_doc from the function line mode runs.
which-pack describes the full screen the one-liner opens instead of a line
menu typed by hand. The systems question lays out in 80 columns under
Python 3.8, whose pty reports no width, and a test no longer reads the
host's drives.
Line mode says the screen's words for the files in place, missing or to
replace, counts the data files in its last line, names what the --from
folders hold before Enter, says Copying and the result's count once, and ends
every result with the same-choice command. Each data tree is hashed once per
run. A wrapped command reads one rule for PowerShell, a pack path keeps its
file name, folder lines keep one indent, and the systems question fits its
terminal. On the screen a tap on the focused Install row arms it, the Game
data row keeps the focus, a choice in place opens on Choose systems, a pack
holding none of the files offers no Install, and the 40x12 plan keeps its
version note.
Commands break between shell words with a continuation the shell reads,
an option kept with its value. The 40x12 setup and plan keep a note or a
folder whole. Line mode counts files in place and missing, and names the
BIOS folder, as the screen does. The systems question fits its terminal.
Answers code_audit_20 and tui_audit_13. A tap acts on the frame it was
made on, bar entries that install, quit or open Confirm take two taps,
and Preferred regions keep their rows while open. Every check of a list
keeps the systems ticked, the plan's counts read the list the check
read, line mode leaves game data out of the choice alone, Confirm counts
copies, a pack's missing files are said before a size, and paths break
after a separator only.
One table of roles from the 16 basic colours (accent, success,
warning, failure, muted, strong, selected) read by the full screen and
by the end of a line-mode run. Status words take their role from one
pattern table, the text never changes, and colour is off with NO_COLOR,
TERM dumb or unset, a terminfo entry naming fewer than 8 colours, or an
output that is not a terminal.
Colour goldens keep the escape codes, and a test strips them back to
the text goldens.
A KNULLI card renamed in its menu was read as a Batocera SHARE drive.
KNULLI is now named by about.info first, Batocera by its own hostname,
and a drive two systems fit is said instead of guessed. Runs without
questions see mounted cards as the screen does and stop on two setups.
The card marker table of the wiki is generated.
scripts/generate_installer_doc.py rewrites the marked tables of
wiki/installer.md: options from build_parser(), events from EVENT_KEYS,
exit codes from the sys.exit calls, RETROBIOS_PAD values and the keys of
each route from TUI_ROUTES, the one table the bar, the help and the stop
line now read. Prose cells are kept, a row the code gains stops the
script until its text is written, and --check runs in the tests. The
site drops the markers.
The full screen falls back to the line questions where the terminal's
terminfo moves no cursor the ANSI way (vt52, glass terminals), and --tui
names why. The line mode draws no escape code with TERM unset, dumb or
such a terminal. Ctrl-Z typed on the screen stops the run as SIGTSTP
does, the terminal handed back and redrawn on fg. A window too small
names 40x12 and its own size.
Pty tests check the modes, the cursor and the main screen after Ctrl-C,
Ctrl-D, SIGTERM, SIGHUP and Ctrl-Z then fg. Tests from a mutmut run over
the device filter, the card bounds and the WSL paths raise its score
from 62/71 to 71/71. The parser lists its options in the page's order,
with NAME, PATH, NAMES and N as arguments.
The README, the installer steps, the choice of what to install and platform detection still described the line prompts as what a terminal shows. They now name the full-screen interface first, with --plain for the questions, and say that no default folder is taken where detection was refused.
The Flatpak RetroArch's folder at 000 hid the retroarch.cfg naming ~/Games/bios, and the run offered 6.6 GB to ~/.config/retroarch/system. A closed folder under HOME or above the default now leaves no default: --dest is asked for. Python 3.14's quiet Path.exists() refusals are told from absence by os.stat, and an assumed folder reads as the one a frontend usually reads.
One closed folder under HOME (~/.config/EmuDeck at 000) made the whole
detection return nothing: a RetroArch whose retroarch.cfg was readable
was lost and the run fell back to a folder it does not read. Every
detection probe now goes through _exists, _is_dir or _is_file, which
count a refused place as absent, name the closed folder once, and let
the other probes go on. The decorator stays as the last net.
The refusal is an unsearched event before detect. The interface keeps
the line above the list of setups. At HOME or a drive root A goes into
a visible subfolder, never a card or drive row nor .cache, and with
none it stays on Use this folder and says where it is. A default folder
taken because the platform was not found is no longer called detected.
HOME kept across su without - made every detection probe raise PermissionError, and the run and the interface ended on a traceback. Detection now finds nothing there, says which folder this user cannot open and how to go on, on the first screen too.
A system_directory read from retroarch.cfg under a folder this user cannot open ended the run, and the interface before its first screen, on a traceback. It now gets the refusal --dest gets. On a handheld, an idle close on an error screen shows that error for a few seconds instead of waiting for a button that cannot come.
Path.exists() raised PermissionError from _missing_dest in line mode and from _choose in the interface. The run now names the folder and exits 1 (error event stage dest), and the interface asks for another folder.
install.py > log.txt at a terminal wrote the menu into the file and
waited for an answer nobody saw. A question now needs stdin and stdout on
a terminal, otherwise the run goes on as with --no-input and says so.
Path.exists() lets PermissionError through, so a BIOS subfolder without
search permission stopped --check and installs before any file. The file
is now reported unreadable and the run goes on with the others.
The test released the held downloads after a fixed pause. Under load the stop arrived after the release, all three files landed and nothing was stopped. It now waits for the run to say it is stopping.
An empty NO_COLOR turned colour off, which no-color.org reads as unset.
FORCE_COLOR and CLICOLOR_FORCE now paint a pipe. --check with several
platforms asks which to check rather than "Install for:", and
--list-platforms says when nothing is detected here.
A run stopped after 8 of 118 files said 118 were installed. The count
now comes from the downloads that finished, and a refused folder writes
one downloaded event per file, as the events table says.
_stable_hashes retried through the hash cache, so both retries returned
the first reading and the file was read once before the manifest run
stopped. The retries now read the file again.
On Windows the partial copy of a file of 16 MB or more is locked with msvcrt.locking, a LockFile region: the locking process cannot access that region through a second handle (Microsoft LockFile remarks). Hashing reopened the path, the read failed with a sharing violation, and every large file was reported as 'folder not writable' (issue 82). Both digests are now read in one pass through the handle that holds the lock. A read-only file already at the destination had the same misleading report: on Windows its attribute is now cleared before the verified copy replaces it, and a refusal that remains is named for what it is.
Opening and locking a partial download are two steps. Between them another run could finish, rename the same file into place and release its lock. The second run then locked the installed BIOS, read its full size as a finished partial and truncated it to download again. After the lock the partial's name must still point at the locked file, or the run downloads into a private copy.
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.
The cache of manifest hashes was keyed by the database's id without
holding the database, so a freed database replaced at the same
address got another scan's verified hashes back. The key now carries
the sha1 that database expects for the path.