mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-11-13 05:23:51 -06:00
feat: find the RetroArch AppImage portable home
This commit is contained in:
1 parent
2571acc820
commit
92e374328f
6 files changed
+103
-10
No files matched your search
+1
-1
@@ -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 = "450cee7625f098d5796452b02ab9c8bffdeaaef89180d2254bbe07ce354bc359"
|
||||
$defaultInstallSha256 = "5bce9f0f81e4f1c7302ca78fa5242f26acc06523f8718378ee97042f2421ff78"
|
||||
$maximumInstallerBytes = 2MB
|
||||
$installerExit = 0
|
||||
$installer = if ($PSScriptRoot) { Join-Path $PSScriptRoot "install.py" } else { $null }
|
||||
|
||||
+45
@@ -1401,6 +1401,49 @@ def _macos_retroarch_base() -> Path:
|
||||
return Path.home() / "Documents" / "RetroArch"
|
||||
|
||||
|
||||
def _retroarch_appimage_dirs(home: Path) -> list[Path]:
|
||||
"""The system folder of each RetroArch AppImage kept with a portable
|
||||
folder, up to two folders below home.
|
||||
|
||||
The buildbot's Linux build unpacks RetroArch-Linux-x86_64.AppImage beside
|
||||
RetroArch-Linux-x86_64.AppImage.home/.config/retroarch. The AppImage
|
||||
runtime sets HOME to <AppImage>.home and XDG_CONFIG_HOME to
|
||||
<AppImage>.config when those folders exist (type2-runtime fedfad51,
|
||||
src/runtime/runtime.c:1449-1462), so this RetroArch never reads
|
||||
~/.config/retroarch. The archive holds no retroarch.cfg: until the first
|
||||
run writes one, the system folder is the base folder's (frontend_unix_get_env
|
||||
in platform_unix.c).
|
||||
"""
|
||||
images: list[Path] = []
|
||||
for depth in ("", "*/", "*/*/"):
|
||||
for suffix in (".home", ".config"):
|
||||
try:
|
||||
hits = sorted(home.glob(f"{depth}*.AppImage{suffix}"))
|
||||
except OSError:
|
||||
continue
|
||||
for hit in hits:
|
||||
image = hit.with_name(hit.name[:-len(suffix)])
|
||||
if image not in images and _is_file(image):
|
||||
images.append(image)
|
||||
dirs: list[Path] = []
|
||||
for image in images:
|
||||
portable_home = image.with_name(image.name + ".home")
|
||||
portable_config = image.with_name(image.name + ".config")
|
||||
if _is_dir(portable_config):
|
||||
base = portable_config / "retroarch"
|
||||
elif _is_dir(portable_home) and "XDG_CONFIG_HOME" not in os.environ:
|
||||
base = portable_home / ".config" / "retroarch"
|
||||
else:
|
||||
continue
|
||||
tilde = portable_home if _is_dir(portable_home) else home
|
||||
system = _parse_retroarch_system_dir(base / "retroarch.cfg", base, tilde)
|
||||
if system is None and _is_dir(base):
|
||||
system = base / "system"
|
||||
if system is not None and system not in dirs:
|
||||
dirs.append(system)
|
||||
return dirs
|
||||
|
||||
|
||||
def _unix_retroarch_base() -> Path:
|
||||
"""RetroArch's base folder on Linux: $XDG_CONFIG_HOME/retroarch when the
|
||||
variable is set, else ~/.config/retroarch (fill_pathname_application_data
|
||||
@@ -2839,6 +2882,8 @@ def detect_platforms(os_type: str) -> list[tuple[str, Path]]:
|
||||
found.append(("retroarch", ra_dir))
|
||||
break
|
||||
|
||||
found.extend(("retroarch", ra_dir) for ra_dir in _retroarch_appimage_dirs(home))
|
||||
|
||||
if os_type == "darwin":
|
||||
# open_default_config_file reads <Application Support>/RetroArch/config
|
||||
# (configuration.c). A value left at default is the documents folder,
|
||||
|
||||
+1
-1
@@ -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="450cee7625f098d5796452b02ab9c8bffdeaaef89180d2254bbe07ce354bc359"
|
||||
DEFAULT_INSTALL_SHA256="5bce9f0f81e4f1c7302ca78fa5242f26acc06523f8718378ee97042f2421ff78"
|
||||
MAX_INSTALLER_BYTES=2097152
|
||||
|
||||
cleanup() {
|
||||
|
||||
@@ -27,8 +27,8 @@
|
||||
{
|
||||
"dest": "roms/ports/retrobios/install.py",
|
||||
"repo_path": "install.py",
|
||||
"size": 1115328,
|
||||
"sha256": "450cee7625f098d5796452b02ab9c8bffdeaaef89180d2254bbe07ce354bc359",
|
||||
"size": 1117350,
|
||||
"sha256": "5bce9f0f81e4f1c7302ca78fa5242f26acc06523f8718378ee97042f2421ff78",
|
||||
"executable": false
|
||||
},
|
||||
{
|
||||
@@ -71,8 +71,8 @@
|
||||
"muos": {
|
||||
"archive": {
|
||||
"dest": "ARCHIVE/RetroBIOS.muxapp",
|
||||
"size": 1168955,
|
||||
"sha256": "1f52731fda2beb3ff9e7aaf7f3d9333853e66b99240b24e4f6b0026368755cb4"
|
||||
"size": 1170977,
|
||||
"sha256": "cfb61e90dafef4fceadd8750412fe91a98b5d8cbf9574c819c09bddb76486e78"
|
||||
},
|
||||
"members": [
|
||||
{
|
||||
@@ -92,8 +92,8 @@
|
||||
{
|
||||
"name": "RetroBIOS/install.py",
|
||||
"repo_path": "install.py",
|
||||
"size": 1115328,
|
||||
"sha256": "450cee7625f098d5796452b02ab9c8bffdeaaef89180d2254bbe07ce354bc359",
|
||||
"size": 1117350,
|
||||
"sha256": "5bce9f0f81e4f1c7302ca78fa5242f26acc06523f8718378ee97042f2421ff78",
|
||||
"executable": false
|
||||
},
|
||||
{
|
||||
@@ -166,8 +166,8 @@
|
||||
{
|
||||
"dest": ".config/modules/retrobios/install.py",
|
||||
"repo_path": "install.py",
|
||||
"size": 1115328,
|
||||
"sha256": "450cee7625f098d5796452b02ab9c8bffdeaaef89180d2254bbe07ce354bc359",
|
||||
"size": 1117350,
|
||||
"sha256": "5bce9f0f81e4f1c7302ca78fa5242f26acc06523f8718378ee97042f2421ff78",
|
||||
"executable": false
|
||||
},
|
||||
{
|
||||
|
||||
@@ -4542,6 +4542,53 @@ class WindowsSeenFromWsl(unittest.TestCase):
|
||||
str(self.root))
|
||||
|
||||
|
||||
class RetroArchAppImageIsPortable(unittest.TestCase):
|
||||
"""The buildbot's Linux RetroArch is an AppImage beside a .home folder
|
||||
the AppImage runtime makes its HOME: the run found nothing and offered
|
||||
~/.config/retroarch/system, a folder this RetroArch never reads."""
|
||||
|
||||
def _detect(self, home: Path, env: dict | None = None) -> list:
|
||||
cleared = {"HOME": str(home), "XDG_CONFIG_HOME": ""}
|
||||
with unittest.mock.patch.dict(os.environ, {**cleared, **(env or {})}), \
|
||||
unittest.mock.patch.object(Path, "home", return_value=home):
|
||||
os.environ.pop("XDG_CONFIG_HOME")
|
||||
return install.detect_platforms("linux")
|
||||
|
||||
def _unpack(self, home: Path) -> Path:
|
||||
folder = home / "Downloads" / "RetroArch-Linux-x86_64"
|
||||
base = folder / "RetroArch-Linux-x86_64.AppImage.home" / ".config" / "retroarch"
|
||||
(base / "system").mkdir(parents=True)
|
||||
(folder / "RetroArch-Linux-x86_64.AppImage").write_bytes(b"\x7fELF")
|
||||
return base
|
||||
|
||||
def test_the_unpacked_archive_is_found(self):
|
||||
home = Path(_tempdir(self))
|
||||
base = self._unpack(home)
|
||||
self.assertIn(("retroarch", base / "system"), self._detect(home))
|
||||
|
||||
def test_its_config_is_read_with_its_own_home(self):
|
||||
home = Path(_tempdir(self))
|
||||
base = self._unpack(home)
|
||||
(base / "retroarch.cfg").write_text('system_directory = "~/bios"\n')
|
||||
portable = base.parent.parent
|
||||
self.assertIn(("retroarch", portable / "bios"), self._detect(home))
|
||||
|
||||
def test_a_config_folder_beside_it_wins(self):
|
||||
home = Path(_tempdir(self))
|
||||
base = self._unpack(home)
|
||||
config = base.parent.parent.with_name("RetroArch-Linux-x86_64.AppImage.config")
|
||||
(config / "retroarch").mkdir(parents=True)
|
||||
found = self._detect(home)
|
||||
self.assertIn(("retroarch", config / "retroarch" / "system"), found)
|
||||
self.assertNotIn(("retroarch", base / "system"), found)
|
||||
|
||||
def test_a_folder_without_its_appimage_is_left(self):
|
||||
home = Path(_tempdir(self))
|
||||
base = self._unpack(home)
|
||||
(base.parent.parent.with_name("RetroArch-Linux-x86_64.AppImage")).unlink()
|
||||
self.assertNotIn(("retroarch", base / "system"), self._detect(home))
|
||||
|
||||
|
||||
class SteamRetroArchOnMacIsPortable(unittest.TestCase):
|
||||
"""platform_darwin.m makes the Steam build portable (HAVE_STEAM) with no
|
||||
portable.txt: a default system_directory is Application Support's, and
|
||||
|
||||
@@ -1177,6 +1177,7 @@ usual folders of a setup that has one on each side: RetroArch's in this Linux
|
||||
| `~/.var/app/org.libretro.RetroArch/config/retroarch/retroarch.cfg` | RetroArch (Flatpak) | `system_directory` |
|
||||
| `~/snap/retroarch/current/.config/retroarch/retroarch.cfg` | RetroArch (Snap) | `system_directory` |
|
||||
| `~/.config/retroarch/retroarch.cfg` | RetroArch (native) | `system_directory` |
|
||||
| `<name>.AppImage.home/.config/retroarch/retroarch.cfg` (or `<name>.AppImage.config/retroarch/`) beside an AppImage in `~`, or one or two folders below it | RetroArch (AppImage from the buildbot, whose portable folder becomes its home) | `system_directory`. Without a config, `system` in that `retroarch` folder |
|
||||
| `~/Library/Application Support/RetroArch/config/retroarch.cfg` | RetroArch (macOS) | `system_directory`. At default, `~/Documents/RetroArch/system` (portable, Steam build included: `Application Support/RetroArch/system`) |
|
||||
| `retroarch.cfg` beside `retroarch.exe` (`C:\RetroArch-Win64`, `C:\RetroArch`, `Program Files\RetroArch`) | RetroArch (Windows) | `system_directory`. At default or without a config, `system` beside the exe |
|
||||
| `%APPDATA%\RetroArch\retroarch.cfg` | RetroArch (Windows) | `system_directory`, read when the exe folder has no config |
|
||||
|
||||
Reference in new issue
Block a user