feat: set up Termux storage from the one-liner

This commit is contained in:
Abdessamad Derraz committed 2026-11-05 12:18:39 +01:00
1 parent bc6bd590f1
commit 4dd43aa627
8 files changed
+77 -11

No files matched your search

+1 -1
View File
@@ -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
View File
@@ -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.
+2 -2
View File
@@ -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
+1 -1
View File
@@ -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",
+1 -1
View File
@@ -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
+45
View File
@@ -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
+2 -3
View File
@@ -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
View File
@@ -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
```