From cf596c92b60d12c7eccaa33d41dece6f451a6196 Mon Sep 17 00:00:00 2001 From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com> Date: Sun, 18 Oct 2026 15:39:49 +0200 Subject: [PATCH] fix: check --target for every platform first --- install.ps1 | 2 +- install.py | 27 ++++++++++++++++++++++++++- install.sh | 2 +- tests/test_install_cores.py | 25 +++++++++++++++++++++++++ 4 files changed, 53 insertions(+), 3 deletions(-) diff --git a/install.ps1 b/install.ps1 index 8440b3db..a796a821 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 = "8cf8886b8332714c2a2bc690a831fa2dd4b42f6b9c19df63bc002383b3650c2e" +$defaultInstallSha256 = "546d190d17449d7b25bcf981bd396645c194364f363a2d315380a043ca101e38" $maximumInstallerBytes = 2MB $installerExit = 0 $installer = if ($PSScriptRoot) { Join-Path $PSScriptRoot "install.py" } else { $null } diff --git a/install.py b/install.py index 329e7193..9ce4a113 100644 --- a/install.py +++ b/install.py @@ -3276,6 +3276,29 @@ def _install(args: argparse.Namespace, real_stdout: TextIO) -> None: failures: list[tuple[str, str]] = [] installed_paths: list[Path] = [] + # --target is checked for every platform before anything is written, as + # --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: + for plat_name, _bios_path in platforms: + targets = fetch_targets(plat_name) + if targets is None: + sys.exit(1) + target_lists[plat_name] = targets + if args.target not in targets: + print(f"Error: unknown target '{args.target}' for {plat_name}.", + file=sys.stderr) + print( + f" available: {', '.join(sorted(targets))}" if targets + else f" {plat_name} publishes no target list", + file=sys.stderr, + ) + if len(platforms) > 1: + print(" Nothing was installed. Name one platform with " + "--platform to install it alone.", file=sys.stderr) + sys.exit(1) + # Every check --installed-cores makes before anything is written: a # refusal for the second platform must not follow an install of the first. cores_found: dict[tuple[str, Path], list[str]] = {} @@ -3348,7 +3371,9 @@ def _install(args: argparse.Namespace, real_stdout: TextIO) -> None: target = board print(f" Board {board} detected (--every-board installs all boards)") if target: - targets = fetch_targets(plat_name) + targets = target_lists.get(plat_name) + if targets is None: + targets = fetch_targets(plat_name) if targets is None: sys.exit(1) target_info = targets.get(target) diff --git a/install.sh b/install.sh index 4ff86fab..a51c9988 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="8cf8886b8332714c2a2bc690a831fa2dd4b42f6b9c19df63bc002383b3650c2e" +DEFAULT_INSTALL_SHA256="546d190d17449d7b25bcf981bd396645c194364f363a2d315380a043ca101e38" MAX_INSTALLER_BYTES=2097152 cleanup() { diff --git a/tests/test_install_cores.py b/tests/test_install_cores.py index 3da1a3af..7fe61090 100644 --- a/tests/test_install_cores.py +++ b/tests/test_install_cores.py @@ -334,6 +334,31 @@ class RefusedBeforeAnyInstall(unittest.TestCase): fetch.assert_not_called() +class AnUnknownTargetStopsTheRunFirst(unittest.TestCase): + """EmuDeck installed 3.2 GB, then steamos was refused for RetroArch and + the run ended without a summary.""" + + def test_nothing_is_fetched_when_one_platform_lacks_the_target(self): + tmp = Path(tempfile.mkdtemp(dir=REPO_ROOT / "tmp")) + self.addCleanup(shutil.rmtree, tmp, True) + detected = [("emudeck", tmp / "bios"), ("retroarch", tmp / "system")] + lists = {"emudeck": {"steamos": {"cores": []}}, "retroarch": {"x86_64": {"cores": []}}} + with mock.patch.object(install, "detect_os", return_value="linux"), \ + mock.patch.object(install, "detect_frontends", return_value=[]), \ + mock.patch.object(install, "detect_platforms", return_value=detected), \ + mock.patch.object(install, "fetch_targets", side_effect=lists.get), \ + mock.patch.object(install, "fetch_manifest") as fetch, \ + mock.patch.object(sys, "argv", ["install.py", "--target", "steamos", "--no-input"]), \ + contextlib.redirect_stdout(io.StringIO()), \ + contextlib.redirect_stderr(io.StringIO()) as err: + with self.assertRaises(SystemExit) as stop: + install.main() + self.assertEqual(stop.exception.code, 1) + self.assertIn("unknown target 'steamos' for retroarch", err.getvalue()) + self.assertIn("Nothing was installed", err.getvalue()) + fetch.assert_not_called() + + class _CoreRepository(FakeRepository): """The fake repository with the two maps and a portable RetroArch."""