mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-11-06 01:53:56 -06:00
feat: set up Termux storage from the one-liner
This commit is contained in:
1 parent
bc6bd590f1
commit
4dd43aa627
8 files changed
+77
-11
No files matched your search
@@ -24,7 +24,7 @@ curl -fsSL https://abdess.github.io/retrobios/i | sh
|
||||
# Windows (PowerShell)
|
||||
irm https://abdess.github.io/retrobios/i.ps1 | iex
|
||||
|
||||
# Android (Termux, after pkg install python and termux-setup-storage)
|
||||
# Android (Termux: it installs Python and asks for storage access)
|
||||
curl -fsSL https://abdess.github.io/retrobios/i | sh
|
||||
|
||||
# SD card mounted on a PC: a muOS, KNULLI, ROCKNIX, Onion, spruceOS or MinUI card
|
||||
|
||||
+21
@@ -212,6 +212,27 @@ if [ -z "$PYTHON" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Termux reaches shared storage, where RetroArch keeps its system folder,
|
||||
# once termux-setup-storage has run: the installer told the user to run it
|
||||
# and start again. At a terminal the bootstrap runs it here. It only asks
|
||||
# the Termux app, which shows Android's permission dialog and creates
|
||||
# ~/storage once allowed: the wait gives the user time to answer.
|
||||
case "${TERMUX_VERSION:-}:${PREFIX:-}" in
|
||||
?*:*|*com.termux*)
|
||||
if [ ! -d "$HOME/storage" ] && command -v termux-setup-storage >/dev/null 2>&1 \
|
||||
&& (: </dev/tty) 2>/dev/null; then
|
||||
echo "Android asks for the storage permission: allow it, so that the files reach" >/dev/tty
|
||||
echo "the RetroArch folder." >/dev/tty
|
||||
termux-setup-storage </dev/tty >/dev/tty 2>&1 || true
|
||||
waited=0
|
||||
while [ ! -d "$HOME/storage" ] && [ "$waited" -lt 60 ]; do
|
||||
sleep 1
|
||||
waited=$((waited + 1))
|
||||
done
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
# Piped from curl, standard input is this script, not the terminal: the
|
||||
# installer would skip every question it can ask. Hand it the terminal when
|
||||
# there is one.
|
||||
|
||||
@@ -116,8 +116,8 @@ terminals:
|
||||
android:
|
||||
label: Android (Termux)
|
||||
how: >-
|
||||
Install **Termux**, a terminal app. Run `pkg install python` and `termux-setup-storage`
|
||||
once. Then paste the line. Press Enter.
|
||||
Install **Termux**, a terminal app. Paste the line. Press Enter. Accept the Python
|
||||
install and allow the storage access Android asks for.
|
||||
shell: sh
|
||||
device:
|
||||
label: On the device
|
||||
|
||||
@@ -575,7 +575,7 @@ def generate_readme(db: dict, platforms_dir: str, db_path: str = "database.json"
|
||||
"# Windows (PowerShell)",
|
||||
install_command("powershell"),
|
||||
"",
|
||||
"# Android (Termux, after pkg install python and termux-setup-storage)",
|
||||
"# Android (Termux: it installs Python and asks for storage access)",
|
||||
install_command("sh"),
|
||||
"",
|
||||
"# SD card mounted on a PC: a muOS, KNULLI, ROCKNIX, Onion, spruceOS or MinUI card",
|
||||
|
||||
@@ -8471,7 +8471,7 @@ def install_commands(args: str = "", indent: str = "",
|
||||
for label, shell in (
|
||||
("Linux, macOS, Steam Deck:", "sh"),
|
||||
("Windows (PowerShell):", "powershell"),
|
||||
("Android (Termux, after `pkg install python` and `termux-setup-storage`):", "sh"),
|
||||
("Android (Termux, the command installs Python and asks for storage access):", "sh"),
|
||||
):
|
||||
lines += [f"{indent}{label}", "", *fence(shell, install_command(shell, args), indent), ""]
|
||||
return lines
|
||||
|
||||
@@ -2694,6 +2694,51 @@ class WindowsWithoutPythonIsOfferedWinget(unittest.TestCase):
|
||||
self.assertFalse((fake_bin / "python3").exists())
|
||||
|
||||
|
||||
@unittest.skipUnless(shutil.which("script"), "needs a terminal")
|
||||
class TermuxStorageIsSetUpByTheBootstrap(unittest.TestCase):
|
||||
"""The installer told an Android user to run termux-setup-storage and
|
||||
start the whole run over: the bootstrap runs it and waits for ~/storage."""
|
||||
|
||||
def _run(self, storage_exists: bool) -> tuple[subprocess.CompletedProcess, Path]:
|
||||
root = Path(_tempdir(self))
|
||||
shutil.copy(REPO_ROOT / "install.sh", root / "install.sh")
|
||||
(root / "install.py").write_text("print('installer ran')\n")
|
||||
home = root / "home"
|
||||
home.mkdir()
|
||||
if storage_exists:
|
||||
(home / "storage").mkdir()
|
||||
fake_bin = root / "bin"
|
||||
fake_bin.mkdir()
|
||||
for tool in ("sed", "tr", "dirname", "cat", "awk", "uname", "sleep", "mkdir"):
|
||||
found = shutil.which(tool)
|
||||
if found:
|
||||
(fake_bin / tool).symlink_to(found)
|
||||
(fake_bin / "python3").symlink_to(sys.executable)
|
||||
# The app creates ~/storage once Android's dialog is answered.
|
||||
(fake_bin / "termux-setup-storage").write_text(
|
||||
f'#!/bin/sh\necho ran >> "{root}/setup.log"\nmkdir "$HOME/storage"\n')
|
||||
(fake_bin / "termux-setup-storage").chmod(0o755)
|
||||
command = (f"PATH={shlex.quote(str(fake_bin))} HOME={shlex.quote(str(home))} "
|
||||
f"TERMUX_VERSION=0.118 /bin/sh {shlex.quote(str(root / 'install.sh'))}")
|
||||
proc = subprocess.run(
|
||||
[shutil.which("script"), "-qec", command, "/dev/null"],
|
||||
capture_output=True, text=True, timeout=120, stdin=subprocess.DEVNULL)
|
||||
return proc, root
|
||||
|
||||
def test_it_runs_once_then_the_installer(self):
|
||||
proc, root = self._run(storage_exists=False)
|
||||
self.assertEqual(proc.returncode, 0, proc.stdout)
|
||||
self.assertEqual((root / "setup.log").read_text(), "ran\n")
|
||||
self.assertIn("allow it", proc.stdout)
|
||||
self.assertIn("installer ran", proc.stdout)
|
||||
|
||||
def test_a_set_up_storage_is_left_alone(self):
|
||||
proc, root = self._run(storage_exists=True)
|
||||
self.assertEqual(proc.returncode, 0, proc.stdout)
|
||||
self.assertFalse((root / "setup.log").exists())
|
||||
self.assertIn("installer ran", proc.stdout)
|
||||
|
||||
|
||||
@unittest.skipUnless(shutil.which("pwsh"), "needs PowerShell")
|
||||
class APyLauncherWithoutARuntimeIsPassed(unittest.TestCase):
|
||||
"""findPython returned the py launcher as soon as it existed: one left
|
||||
|
||||
@@ -53,11 +53,10 @@ curl -fsSL https://abdess.github.io/retrobios/i | sh
|
||||
</TabItem>
|
||||
<TabItem label="Android (Termux)">
|
||||
|
||||
Install **Termux**, a terminal app, and run these lines.
|
||||
Install **Termux**, a terminal app, and run this line. It installs Python
|
||||
and asks Android for storage access: allow both.
|
||||
|
||||
```sh title="Terminal"
|
||||
pkg install python
|
||||
termux-setup-storage
|
||||
curl -fsSL https://abdess.github.io/retrobios/i | sh
|
||||
```
|
||||
|
||||
|
||||
+4
-3
@@ -1397,11 +1397,12 @@ writable (Android 10 and earlier), it is a standalone copy target.
|
||||
|
||||
Under scoped storage the two RetroArch config paths are unreadable from Termux on
|
||||
Android 11 and later, so on current devices the folders are what answers.
|
||||
Running `termux-setup-storage` once is what makes the shared one reachable:
|
||||
Running `termux-setup-storage` once is what makes the shared one reachable.
|
||||
The one-line command runs it when `~/storage` is missing, then waits up to a
|
||||
minute for the permission Android asks for, as it offers `pkg install python`
|
||||
when Python is missing:
|
||||
|
||||
```bash
|
||||
pkg install python
|
||||
termux-setup-storage
|
||||
curl -fsSL https://abdess.github.io/retrobios/i | sh
|
||||
```
|
||||
|
||||
|
||||
Reference in new issue
Block a user