diff --git a/install.ps1 b/install.ps1 index 57aca4f16..dab7b3426 100644 --- a/install.ps1 +++ b/install.ps1 @@ -16,7 +16,7 @@ # and Invoke-WebRequest throws on a cut transfer before the hash is read: # the site's build rewrites this line there (scripts/sitebootstrap.py). $mismatchAdvice = "The download was most likely cut short: try again. Within minutes of an update of this project the two files can come from caches of different ages. Waiting five minutes settles that." - $defaultInstallSha256 = "482a7710467d988f3878a5d8ebe5f885dfee35c3a1aac0df05077b6b062a7610" + $defaultInstallSha256 = "7622c5e1a9ec7a76bf3c325b1fd356a22b53aefe0b625d6c12447afee9414300" $maximumInstallerBytes = 2MB $installerExit = 0 $installer = if ($PSScriptRoot) { Join-Path $PSScriptRoot "install.py" } else { $null } diff --git a/install.py b/install.py index baa21de99..429dffa35 100644 --- a/install.py +++ b/install.py @@ -13429,6 +13429,29 @@ def main() -> None: if (args.list_platforms or args.list_targets or args.list_systems or args.list_cores or args.list_emulators): parser.error("--for-games narrows an install, not a listing") + # Applied or refused, never ignored: a run prints one list, and the + # narrowing options apply to --list-systems and --list-cores only, past + # --target and --installed-cores, which --list-emulators also reads. + listings = [flag for flag, given in ( + ("--list-platforms", args.list_platforms), ("--list-targets", args.list_targets), + ("--list-systems", args.list_systems), ("--list-cores", args.list_cores), + ("--list-emulators", args.list_emulators)) if given] + if len(listings) > 1: + parser.error(f"{listings[0]} and {listings[1]} each print a list: run them " + "one at a time") + if listings and listings[0] in ("--list-platforms", "--list-targets", + "--list-emulators"): + unread = (("--system", args.system), ("--core", args.core), + ("--region", args.region), ("--emulator", args.emulator)) + if listings[0] != "--list-emulators": + unread += (("--target", args.target), ("--every-board", args.every_board), + ("--installed-cores", args.installed_cores)) + if listings[0] == "--list-platforms": + unread += (("--platform", args.platform),) + given = next((flag for flag, value in unread if value), "") + if given: + parser.error(f"{listings[0]} prints the whole list, which {given} " + "does not narrow") if args.declared_only: # Applied or refused, never ignored. for given, reason in ( @@ -15176,7 +15199,7 @@ def _install(args: argparse.Namespace, real_stdout: TextIO) -> None: # --installed-cores is below: EmuDeck installed 3.2 GB and only then was # steamos refused for RetroArch, with no summary of what had landed. target_lists: dict[str, dict] = {} - if args.target and not args.list_targets: + if args.target: for plat_name, _bios_path in platforms: targets = fetch_targets(plat_name) if targets is None: diff --git a/install.sh b/install.sh index 4f1d02bbf..cbdaed395 100755 --- a/install.sh +++ b/install.sh @@ -23,7 +23,7 @@ DEFAULT_INSTALL_URL="https://raw.githubusercontent.com/Abdess/retrobios/main/ins # curl or wget stop on a cut transfer before the hash is read: the site's # build rewrites this line there (scripts/sitebootstrap.py). MISMATCH_ADVICE="The download was most likely cut short: try again. Within minutes of an update of this project the two files can come from caches of different ages. Waiting five minutes settles that." -DEFAULT_INSTALL_SHA256="482a7710467d988f3878a5d8ebe5f885dfee35c3a1aac0df05077b6b062a7610" +DEFAULT_INSTALL_SHA256="7622c5e1a9ec7a76bf3c325b1fd356a22b53aefe0b625d6c12447afee9414300" MAX_INSTALLER_BYTES=2097152 cleanup() { diff --git a/install/launchers/index.json b/install/launchers/index.json index 6f8f8ff49..2be9a4f89 100644 --- a/install/launchers/index.json +++ b/install/launchers/index.json @@ -27,8 +27,8 @@ { "dest": "roms/ports/retrobios/install.py", "repo_path": "install.py", - "size": 1104874, - "sha256": "482a7710467d988f3878a5d8ebe5f885dfee35c3a1aac0df05077b6b062a7610", + "size": 1106280, + "sha256": "7622c5e1a9ec7a76bf3c325b1fd356a22b53aefe0b625d6c12447afee9414300", "executable": false }, { @@ -71,8 +71,8 @@ "muos": { "archive": { "dest": "ARCHIVE/RetroBIOS.muxapp", - "size": 1158501, - "sha256": "0ecf443039c136286322a57b33f1374dd52de0b5f2a772fbae93c1f98c19b62d" + "size": 1159907, + "sha256": "6460af3bc1a9d27c7373b42cf45f19bf8619b8e55daac9892af9f57df21b258e" }, "members": [ { @@ -92,8 +92,8 @@ { "name": "RetroBIOS/install.py", "repo_path": "install.py", - "size": 1104874, - "sha256": "482a7710467d988f3878a5d8ebe5f885dfee35c3a1aac0df05077b6b062a7610", + "size": 1106280, + "sha256": "7622c5e1a9ec7a76bf3c325b1fd356a22b53aefe0b625d6c12447afee9414300", "executable": false }, { @@ -166,8 +166,8 @@ { "dest": ".config/modules/retrobios/install.py", "repo_path": "install.py", - "size": 1104874, - "sha256": "482a7710467d988f3878a5d8ebe5f885dfee35c3a1aac0df05077b6b062a7610", + "size": 1106280, + "sha256": "7622c5e1a9ec7a76bf3c325b1fd356a22b53aefe0b625d6c12447afee9414300", "executable": false }, { diff --git a/tests/test_install.py b/tests/test_install.py index 7efea9660..658385670 100644 --- a/tests/test_install.py +++ b/tests/test_install.py @@ -4475,6 +4475,50 @@ def _install_run(env: dict, *argv: str, **kwargs) -> subprocess.CompletedProcess ) +class AListingAppliesItsOptionsOrRefusesThem(unittest.TestCase): + """--list-systems --list-cores printed the systems alone, and + --list-platforms, --list-targets and --list-emulators printed the same + list with --system, --region or --core as without, code 0.""" + + def test_two_listings_or_an_option_a_listing_ignores_are_refused(self): + env = dict(os.environ, RETROBIOS_OS="linux") + given = ["--platform", "retroarch", "--offline", "--no-input", + "--manifest", "install/retroarch.json"] + for argv, words in ( + ([*given, "--list-systems", "--list-cores"], + "--list-systems and --list-cores each print a list"), + ([*given, "--list-cores", "--list-emulators"], + "--list-cores and --list-emulators each print a list"), + (["--list-platforms", "--list-systems", "--platform", "retroarch"], + "--list-platforms and --list-systems each print a list"), + (["--list-platforms", "--region", "us"], + "--list-platforms prints the whole list, which --region does not narrow"), + (["--list-platforms", "--platform", "retroarch"], + "--list-platforms prints the whole list, which --platform does not narrow"), + ([*given, "--list-targets", "--system", "sony-playstation"], + "--list-targets prints the whole list, which --system does not narrow"), + ([*given, "--list-targets", "--target", "switch"], + "--list-targets prints the whole list, which --target does not narrow"), + ([*given, "--list-emulators", "--system", "sony-playstation"], + "--list-emulators prints the whole list, which --system does not narrow"), + ([*given, "--list-emulators", "--core", "beetle_psx"], + "--list-emulators prints the whole list, which --core does not narrow"), + ): + with self.subTest(argv=argv): + proc = _install_run(env, *argv) + self.assertEqual(proc.returncode, 2, proc.stdout + proc.stderr) + self.assertIn(words, proc.stderr) + + def test_the_options_a_listing_reads_still_apply(self): + env = dict(os.environ, RETROBIOS_OS="linux") + given = ["--platform", "retroarch", "--offline", "--no-input", + "--manifest", "install/retroarch.json"] + whole = _install_run(env, *given, "--list-cores") + narrowed = _install_run(env, *given, "--list-cores", "--system", "nintendo-gba") + self.assertEqual((whole.returncode, narrowed.returncode), (0, 0), narrowed.stderr) + self.assertLess(len(narrowed.stdout), len(whole.stdout)) + + class AMissingPackNamesTheOptionAndThePacksBeside(unittest.TestCase): """A typo in --from-pack said "Error: X does not exist": not the option, not the pack sitting next to the name typed.""" diff --git a/tests/test_install_offline.py b/tests/test_install_offline.py index b46ea29be..08d9194d2 100644 --- a/tests/test_install_offline.py +++ b/tests/test_install_offline.py @@ -778,7 +778,12 @@ class OfflineMakesNoRequest(Scratch): self.assertIn("--offline", proc.stderr) def test_a_listing_and_a_pack_need_no_network_anyway(self): - proc = self.run_installer("--offline", "--list-platforms") + # --platform alone with it is refused: the listing names every one. + proc = subprocess.run( + [sys.executable, str(REPO_ROOT / "install.py"), "--offline", "--list-platforms"], + env=_offline_env(), capture_output=True, text=True, timeout=120, + check=False, stdin=subprocess.DEVNULL, + ) self.assertEqual(proc.returncode, 0, proc.stderr) diff --git a/wiki/installer.md b/wiki/installer.md index 88da4c7b0..f66a8eb54 100644 --- a/wiki/installer.md +++ b/wiki/installer.md @@ -976,9 +976,9 @@ what the options name, everything by default. | `--required-only` | With `--for-games`, only the files the games cannot start without | | `--no-game-data` | Leave out game data (a game's own files, not firmware) and install the firmware only. What it leaves out is named. See [Firmware without game data](#firmware-without-game-data) | | `--declared-only` | Keep only the files the platform's own list names (`cores: null` in the manifest), not the extra files cores load. With `--check`, the answer is about the list the platform itself checks. Refused with `--core`, the listings it does not change, `--standalone-copies` and `--tui` | -| `--list-systems` | Print a platform's systems with the files and size each holds, the files other systems share too counted apart | -| `--list-cores` | Print the cores whose extra files a platform installs | -| `--list-emulators` | Print every name `--emulator` accepts, each buildbot name beside the emulator it stands for | +| `--list-systems` | Print a platform's systems with the files and size each holds, the files other systems share too counted apart. `--system`, `--core`, `--region`, `--target` and `--installed-cores` narrow it, as they narrow an install. A run prints one list: two listing options are refused | +| `--list-cores` | Print the cores whose extra files a platform installs. The options that narrow `--list-systems` narrow it too | +| `--list-emulators` | Print every name `--emulator` accepts, each buildbot name beside the emulator it stands for. `--target` and `--installed-cores` narrow it, and `--system`, `--core`, `--region` and `--emulator` are refused | | `--romm-firmware TEMPLATE` | RomM: where each platform's firmware goes in the library, as `filesystem.structure.firmware` in RomM's `config.yml` says (`{platform}/bios` for a library laid out as `{platform}/roms`). Read from `config.yml` beside the library when it is there. See [RomM firmware layout](#romm-firmware-layout) | | `--no-input` | Never ask a question, even at a terminal. A run whose output goes to a file or a pipe asks nothing either, and says so on stderr. It finds the setups and the mounted cards the screen finds: one is taken, as Enter takes it, two stop the run with an `error` event (`stage` `detect`, `reason` `conflict`) naming each with its `--platform` and `--dest`, and none stops it too, with `reason` `not_found` when a file list or a pack names the platform | | `--check` | Report and exit without writing | @@ -994,8 +994,8 @@ what the options name, everything by default. | `--tui` | Open the full-screen interface, or stop with the reason it cannot open here (code 2) instead of falling back to the questions. Wins over `RETROBIOS_PLAIN` and `ACCESSIBLE`. See [The full-screen interface](#the-full-screen-interface) | | `--plain` | Ask the questions line by line instead of the full-screen interface, the mode for a screen reader. See [The full-screen interface](#the-full-screen-interface) | | `--version` | Print the installer's identity, the first 12 hex digits of the SHA-256 the bootstraps pin | -| `--list-platforms` | Print the supported platforms and what was detected here | -| `--list-targets` | Print the hardware targets a platform publishes, with the core count each carries | +| `--list-platforms` | Print the supported platforms and what was detected here. An option that narrows a list (`--platform`, `--system`, `--core`, `--region`, `--emulator`, `--target`, `--every-board`, `--installed-cores`) is refused | +| `--list-targets` | Print the hardware targets a platform publishes, with the core count each carries. `--system`, `--core`, `--region`, `--emulator`, `--target`, `--every-board` and `--installed-cores` are refused | | `--jobs N`, `-j N` | Parallel downloads, 1 to 32, default 8 | | `--verbose`, `-v` | Print per-attempt failures and hash mismatches | | `--standalone-copies` | Also copy into detected standalone emulator directories |