fix: name standalone folders instead of skipped

Every install ended on 'Standalone copies skipped', on machines with no standalone emulator as on one whose DuckStation lacked its BIOS. The line now lists the emulator folders that exist here, and nothing is said when there are none.
This commit is contained in:
Abdessamad Derraz committed 2026-10-21 10:02:15 +02:00
1 parent ff8a390ce6
commit 0b0480a121
5 files changed
+80 -21

No files matched your search

+1 -1
View File
@@ -11,7 +11,7 @@
$ErrorActionPreference = "Stop"
$defaultInstallUrl = "https://raw.githubusercontent.com/Abdess/retrobios/main/install.py"
$defaultInstallSha256 = "6e7005671e99ab965e815ba96bb6c6c0542667012d9b42bd139d2e3e0f06d40c"
$defaultInstallSha256 = "864b631d417299feb305fdab7db62e4395608cce809c71bbb15b9f942be2b867"
$maximumInstallerBytes = 2MB
$installerExit = 0
$installer = if ($PSScriptRoot) { Join-Path $PSScriptRoot "install.py" } else { $null }
+48 -19
View File
@@ -3755,6 +3755,42 @@ def select_data_directories(manifest: dict, files: list[dict], narrowed: bool) -
return [e for e in entries if kept & set(e.get("systems") or [])]
def _copy_targets(
entry: dict, os_type: str, extra_dirs: dict[str, Path] | None = None,
) -> list[Path]:
"""The emulator folders a standalone copy entry names on this OS.
WSL falls back to the Linux ones, and extra_dirs adds the folder a
frontend such as LaunchBox keeps the emulator in.
"""
targets = entry.get("targets", {}).get(os_type, [])
if not targets and os_type == "wsl":
targets = entry.get("targets", {}).get("linux", [])
target_dirs = [Path(os.path.expandvars(os.path.expanduser(t))) for t in targets]
extra_root = (extra_dirs or {}).get(entry.get("emulator", ""))
if extra_root is not None:
subdir = PurePosixPath(entry.get("file", "")).parent
extra = extra_root if str(subdir) == "." else extra_root / subdir
if extra not in target_dirs:
target_dirs.append(extra)
return target_dirs
def standalone_folders_here(
manifest: dict, os_type: str, extra_dirs: dict[str, Path] | None = None,
) -> list[Path]:
"""The emulator folders of the manifest's standalone copies that exist
on this machine: the ones --standalone-copies would write to."""
found: list[Path] = []
for entry in manifest.get("standalone_copies", []):
if "note" in entry:
continue
for folder in _copy_targets(entry, os_type, extra_dirs):
if folder not in found and folder.is_dir():
found.append(folder)
return found
def do_standalone_copies(
manifest: dict, bios_path: Path, os_type: str,
extra_dirs: dict[str, Path] | None = None,
@@ -3819,22 +3855,7 @@ def do_standalone_copies(
if not sources:
continue
# Resolve target directories with WSL fallback
targets = entry.get("targets", {}).get(os_type, [])
if not targets and os_type == "wsl":
targets = entry.get("targets", {}).get("linux", [])
target_dirs = [
Path(os.path.expandvars(os.path.expanduser(t))) for t in targets
]
extra_root = (extra_dirs or {}).get(entry.get("emulator", ""))
if extra_root is not None:
subdir = PurePosixPath(entry.get("file", "")).parent
extra = extra_root if str(subdir) == "." else extra_root / subdir
if extra not in target_dirs:
target_dirs.append(extra)
for target_dir in target_dirs:
for target_dir in _copy_targets(entry, os_type, extra_dirs):
if not target_dir.is_dir():
skipped += len(sources)
continue
@@ -5213,10 +5234,18 @@ def _install(args: argparse.Namespace, real_stdout: TextIO) -> None:
)
total_errors += copy_failed
elif manifest.get("standalone_copies") and not args.check:
print(
"\nStandalone copies skipped "
"(use --standalone-copies to opt in)."
# Said only where it concerns this machine: "skipped" printed on
# every run read as an incident, and named no emulator.
lb_root = launchbox_root(os_type)
folders = standalone_folders_here(
manifest, os_type, launchbox_bios_dirs(lb_root) if lb_root else None
)
if folders:
print("\nStandalone emulator folders found here:")
for folder in folders:
print(f" {folder}")
print(" --standalone-copies also copies the BIOS files and keys "
"they read into them.")
sys.stdout = real_stdout
# A check scripted as `--check && launch` reads the exit code only.
+1 -1
View File
@@ -18,7 +18,7 @@ esac
TEMP_INSTALLER=""
TEMP_DIRECTORY=""
DEFAULT_INSTALL_URL="https://raw.githubusercontent.com/Abdess/retrobios/main/install.py"
DEFAULT_INSTALL_SHA256="6e7005671e99ab965e815ba96bb6c6c0542667012d9b42bd139d2e3e0f06d40c"
DEFAULT_INSTALL_SHA256="864b631d417299feb305fdab7db62e4395608cce809c71bbb15b9f942be2b867"
MAX_INSTALLER_BYTES=2097152
cleanup() {
+28
View File
@@ -3863,6 +3863,34 @@ class ACompletePartialIsHandedOffOnWindows(unittest.TestCase):
self.assertTrue(install._write_refused(PermissionError(13, "denied")))
class StandaloneFoldersAreNamedWhenThereAreAny(unittest.TestCase, _LoopbackRun):
"""'Standalone copies skipped' closed every install, on a machine with
no standalone emulator as on one whose DuckStation lacked its BIOS."""
def setUp(self):
self.env = self.serve(self)
def _run(self) -> str:
proc = _install_run(self.env, "--platform", "retroarch", "--dest",
str(self.home / "system"), "--system", "atari-lynx",
"--no-input")
self.assertEqual(proc.returncode, 0, proc.stdout + proc.stderr)
return proc.stdout
def test_nothing_is_said_without_an_emulator_folder(self):
out = self._run()
self.assertNotIn("skipped", out)
self.assertNotIn("--standalone-copies", out)
def test_a_found_folder_is_named(self):
duckstation = self.home / ".local" / "share" / "duckstation" / "bios"
duckstation.mkdir(parents=True)
out = self._run()
self.assertIn("Standalone emulator folders found here:", out)
self.assertIn(str(duckstation), out)
self.assertIn("--standalone-copies", out)
class TheEmulatorNamesHaveTheirOwnListing(unittest.TestCase, _LoopbackRun):
"""--emulator nope said "--list-cores lists all 441" and --list-cores
printed 189: the buildbot names --emulator accepts were listed nowhere."""
+2
View File
@@ -421,6 +421,8 @@ that is not installed. A destination that is already a symbolic link is
replaced by the file rather than written through: a write through the link
would land outside the folder the user opted into. The summary counts each
copy as copied, skipped (folder absent) or failed, and names every failure.
A run without the flag lists the emulator folders of this list that exist on
the machine, and says nothing when there are none.
## RomM firmware layout