fix: refuse targets when their list cannot be read

This commit is contained in:
Abdessamad Derraz committed 2026-10-06 01:39:31 +02:00
1 parent 403c7ff910
commit 2a56fccc85
4 files changed
+42 -8

No files matched your search

+1 -1
View File
@@ -8,7 +8,7 @@ param(
$ErrorActionPreference = "Stop" $ErrorActionPreference = "Stop"
$defaultInstallUrl = "https://raw.githubusercontent.com/Abdess/retrobios/main/install.py" $defaultInstallUrl = "https://raw.githubusercontent.com/Abdess/retrobios/main/install.py"
$defaultInstallSha256 = "3ea3a3e21012cc2dbf24c08a0ad314233ade04e62c0d2164b76146f1b361d714" $defaultInstallSha256 = "42b1747ae867d41da39b11daf783c0106daa6ed18861a2214c196f3a5c9a3c60"
$maximumInstallerBytes = 2MB $maximumInstallerBytes = 2MB
$installer = if ($PSScriptRoot) { Join-Path $PSScriptRoot "install.py" } else { $null } $installer = if ($PSScriptRoot) { Join-Path $PSScriptRoot "install.py" } else { $null }
$temporary = $null $temporary = $null
+16 -6
View File
@@ -954,8 +954,13 @@ def fetch_manifest(plat: str) -> dict:
sys.exit(1) sys.exit(1)
def fetch_targets(plat: str) -> dict: def fetch_targets(plat: str) -> "dict | None":
"""Download target core list. Returns empty dict on 404.""" """Download the target core list.
Empty on 404, where the platform publishes no targets. None when the list
could not be read: a timeout says nothing about the platform, and
answering "no targets" for it sent users to the full pack.
"""
url = TARGETS_URL.format(platform=plat) url = TARGETS_URL.format(platform=plat)
try: try:
with urllib.request.urlopen(url, timeout=30) as resp: with urllib.request.urlopen(url, timeout=30) as resp:
@@ -965,10 +970,11 @@ def fetch_targets(plat: str) -> dict:
except urllib.error.HTTPError as exc: except urllib.error.HTTPError as exc:
if exc.code == 404: if exc.code == 404:
return {} return {}
print(f" Warning: failed to fetch targets for {plat}: {exc}", file=sys.stderr) print(f" Error: failed to fetch targets for {plat}: {exc}", file=sys.stderr)
return {} return None
except (urllib.error.URLError, OSError, ValueError): except (urllib.error.URLError, OSError, ValueError) as exc:
return {} print(f" Error: failed to fetch targets for {plat}: {exc}", file=sys.stderr)
return None
def _filter_by_target( def _filter_by_target(
@@ -1580,6 +1586,8 @@ def main() -> None:
if args.list_targets: if args.list_targets:
targets = fetch_targets(plat_name) targets = fetch_targets(plat_name)
if targets is None:
sys.exit(1)
if not targets: if not targets:
print(f" No targets available for {plat_name}") print(f" No targets available for {plat_name}")
else: else:
@@ -1592,6 +1600,8 @@ def main() -> None:
# Target filtering # Target filtering
if args.target: if args.target:
targets = fetch_targets(plat_name) targets = fetch_targets(plat_name)
if targets is None:
sys.exit(1)
target_info = targets.get(args.target) target_info = targets.get(args.target)
if target_info is None: if target_info is None:
# Carrying on would install every file, which is the opposite # Carrying on would install every file, which is the opposite
+1 -1
View File
@@ -18,7 +18,7 @@ esac
TEMP_INSTALLER="" TEMP_INSTALLER=""
TEMP_DIRECTORY="" TEMP_DIRECTORY=""
DEFAULT_INSTALL_URL="https://raw.githubusercontent.com/Abdess/retrobios/main/install.py" DEFAULT_INSTALL_URL="https://raw.githubusercontent.com/Abdess/retrobios/main/install.py"
DEFAULT_INSTALL_SHA256="3ea3a3e21012cc2dbf24c08a0ad314233ade04e62c0d2164b76146f1b361d714" DEFAULT_INSTALL_SHA256="42b1747ae867d41da39b11daf783c0106daa6ed18861a2214c196f3a5c9a3c60"
MAX_INSTALLER_BYTES=2097152 MAX_INSTALLER_BYTES=2097152
cleanup() { cleanup() {
+24
View File
@@ -1357,5 +1357,29 @@ class TestAvailablePlatforms(unittest.TestCase):
self.assertIn("retroarch", proc.stdout) self.assertIn("retroarch", proc.stdout)
class TargetListFailureIsNotAnAnswer(unittest.TestCase):
"""A timeout is not 'no targets': it sent users to the full pack."""
def test_unreachable_list_is_none(self):
import urllib.error
from unittest import mock
def boom(*args, **kwargs):
raise urllib.error.URLError("timed out")
with mock.patch.object(install.urllib.request, "urlopen", boom), \
contextlib.redirect_stderr(io.StringIO()):
self.assertIsNone(install.fetch_targets("retroarch"))
def test_absent_list_is_empty(self):
import urllib.error
from unittest import mock
def missing(url, *args, **kwargs):
raise urllib.error.HTTPError(url, 404, "Not Found", {}, None)
with mock.patch.object(install.urllib.request, "urlopen", missing):
self.assertEqual(install.fetch_targets("retroarch"), {})
if __name__ == "__main__": if __name__ == "__main__":
unittest.main() unittest.main()