mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-11-01 00:27:20 -05:00
scripts/generate_installer_doc.py rewrites the marked tables of wiki/installer.md: options from build_parser(), events from EVENT_KEYS, exit codes from the sys.exit calls, RETROBIOS_PAD values and the keys of each route from TUI_ROUTES, the one table the bar, the help and the stop line now read. Prose cells are kept, a row the code gains stops the script until its text is written, and --check runs in the tests. The site drops the markers. The full screen falls back to the line questions where the terminal's terminfo moves no cursor the ANSI way (vt52, glass terminals), and --tui names why. The line mode draws no escape code with TERM unset, dumb or such a terminal. Ctrl-Z typed on the screen stops the run as SIGTSTP does, the terminal handed back and redrawn on fg. A window too small names 40x12 and its own size. Pty tests check the modes, the cursor and the main screen after Ctrl-C, Ctrl-D, SIGTERM, SIGHUP and Ctrl-Z then fg. Tests from a mutmut run over the device filter, the card bounds and the WSL paths raise its score from 62/71 to 71/71. The parser lists its options in the page's order, with NAME, PATH, NAMES and N as arguments.
197 lines
7.1 KiB
Bash
Executable File
197 lines
7.1 KiB
Bash
Executable File
#!/bin/sh
|
|
set -eu
|
|
|
|
# One-line bootstrap and local wrapper. The downloaded installer is accepted
|
|
# only when it matches the SHA-256 embedded in this wrapper.
|
|
INSTALLER=""
|
|
# When sourced from stdin, $0 is the shell name and the working directory is
|
|
# not a trusted location for install.py. Reuse an adjacent installer only for
|
|
# an actual local install.sh invocation.
|
|
case "$0" in
|
|
install.sh|*/install.sh)
|
|
if [ -f "$0" ]; then
|
|
SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
|
|
INSTALLER="$SCRIPT_DIR/install.py"
|
|
fi
|
|
;;
|
|
esac
|
|
TEMP_INSTALLER=""
|
|
TEMP_DIRECTORY=""
|
|
DEFAULT_INSTALL_URL="https://raw.githubusercontent.com/Abdess/retrobios/main/install.py"
|
|
DEFAULT_INSTALL_SHA256="af5087172bc1909ad70f81c0e10c944db0d2326a3c9c1b4965c53faf1944d37c"
|
|
MAX_INSTALLER_BYTES=2097152
|
|
|
|
cleanup() {
|
|
if [ -n "$TEMP_INSTALLER" ] && [ -f "$TEMP_INSTALLER" ]; then
|
|
rm -f -- "$TEMP_INSTALLER"
|
|
fi
|
|
if [ -n "$TEMP_DIRECTORY" ] && [ -d "$TEMP_DIRECTORY" ]; then
|
|
rmdir -- "$TEMP_DIRECTORY" 2>/dev/null || true
|
|
fi
|
|
}
|
|
trap cleanup EXIT HUP INT TERM
|
|
|
|
if [ -z "$INSTALLER" ] || [ ! -f "$INSTALLER" ]; then
|
|
install_url=${RETROBIOS_INSTALL_URL:-$DEFAULT_INSTALL_URL}
|
|
expected=${RETROBIOS_INSTALL_SHA256:-$DEFAULT_INSTALL_SHA256}
|
|
case "$install_url" in
|
|
https://*) ;;
|
|
*) echo "Error: installer URL must use HTTPS." >&2; exit 1 ;;
|
|
esac
|
|
case "$expected" in
|
|
*[!0-9A-Fa-f]*)
|
|
echo "Error: installer SHA-256 must contain exactly 64 hexadecimal characters." >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
if [ "${#expected}" -ne 64 ]; then
|
|
echo "Error: installer SHA-256 must contain exactly 64 hexadecimal characters." >&2
|
|
exit 1
|
|
fi
|
|
TEMP_DIRECTORY=$(mktemp -d)
|
|
TEMP_INSTALLER="$TEMP_DIRECTORY/install.py"
|
|
# Quiet but for the error line: a progress table followed by
|
|
# "curl: (6) ..." and curl's own exit code told nobody what failed.
|
|
if command -v curl >/dev/null 2>&1; then
|
|
fetch() {
|
|
curl --fail --silent --show-error --location --proto '=https' --tlsv1.2 \
|
|
--connect-timeout 30 --retry 2 "$install_url" --output "$TEMP_INSTALLER"
|
|
}
|
|
elif command -v wget >/dev/null 2>&1; then
|
|
# BusyBox wget (Alpine, the RomM image) has no --https-only and refuses
|
|
# the whole command over it (networking/wget.c wget_longopts). The URL
|
|
# itself is checked to be https above, and the SHA-256 below decides.
|
|
https_only=""
|
|
if wget --help 2>&1 | grep -q -- '--https-only'; then
|
|
https_only="--https-only"
|
|
fi
|
|
fetch() {
|
|
wget --quiet ${https_only:+"$https_only"} --timeout=30 --tries=3 \
|
|
--output-document="$TEMP_INSTALLER" "$install_url"
|
|
}
|
|
else
|
|
echo "Error: curl or wget is required to download the installer." >&2
|
|
echo " On Debian or Ubuntu: sudo apt install curl" >&2
|
|
exit 1
|
|
fi
|
|
if ! fetch_error=$(fetch 2>&1); then
|
|
echo "Error: the installer could not be downloaded from $install_url" >&2
|
|
echo " $(printf '%s\n' "$fetch_error" | tail -n 1)" >&2
|
|
echo " Check the network connection, and HTTPS_PROXY if this network needs a proxy," >&2
|
|
echo " then run the same command again. Nothing was run and nothing was written." >&2
|
|
exit 1
|
|
fi
|
|
actual_size=$(wc -c < "$TEMP_INSTALLER" | tr -d ' ')
|
|
if [ "$actual_size" -gt "$MAX_INSTALLER_BYTES" ]; then
|
|
echo "Error: downloaded installer exceeds the size limit." >&2
|
|
exit 1
|
|
fi
|
|
if command -v sha256sum >/dev/null 2>&1; then
|
|
actual=$(sha256sum "$TEMP_INSTALLER" | awk '{print $1}')
|
|
elif command -v shasum >/dev/null 2>&1; then
|
|
actual=$(shasum -a 256 "$TEMP_INSTALLER" | awk '{print $1}')
|
|
else
|
|
echo "Error: sha256sum or shasum is required." >&2
|
|
exit 1
|
|
fi
|
|
expected=$(printf '%s' "$expected" | tr '[:upper:]' '[:lower:]')
|
|
if [ "$actual" != "$expected" ]; then
|
|
echo "Error: the downloaded installer does not match its expected fingerprint." >&2
|
|
echo " Nothing was run and nothing was written." >&2
|
|
overrides=""
|
|
[ -n "${RETROBIOS_INSTALL_URL:-}" ] && overrides="RETROBIOS_INSTALL_URL"
|
|
if [ -n "${RETROBIOS_INSTALL_SHA256:-}" ]; then
|
|
overrides="${overrides:+$overrides and }RETROBIOS_INSTALL_SHA256"
|
|
fi
|
|
if [ -n "$overrides" ]; then
|
|
# A pin or a URL of the user's own refuses the installer: retrying,
|
|
# as the advice below says, would never help.
|
|
echo " $overrides is set in this environment and decides which installer is" >&2
|
|
echo " accepted: unset it to use the installer this script names, or set it to match." >&2
|
|
exit 1
|
|
fi
|
|
echo " The download was most likely cut short: try again. Within minutes of an update" >&2
|
|
echo " of this project the two files can come from caches of different ages." >&2
|
|
echo " Waiting five minutes settles that." >&2
|
|
exit 1
|
|
fi
|
|
INSTALLER="$TEMP_INSTALLER"
|
|
fi
|
|
|
|
find_python() {
|
|
PYTHON=""
|
|
for command_name in python3 python; do
|
|
if command -v "$command_name" >/dev/null 2>&1 \
|
|
&& "$command_name" -c 'import sys; raise SystemExit(sys.version_info < (3, 8))' 2>/dev/null; then
|
|
PYTHON=$command_name
|
|
return 0
|
|
fi
|
|
done
|
|
return 1
|
|
}
|
|
|
|
# The command that installs Python here, named for this system: Termux has
|
|
# no sudo and installs with pkg, macOS has no apt.
|
|
python_install_command() {
|
|
case "${TERMUX_VERSION:-}:${PREFIX:-}" in
|
|
?*:*|*com.termux*) echo "pkg install python"; return ;;
|
|
esac
|
|
if [ "$(uname -s 2>/dev/null)" = "Darwin" ]; then
|
|
echo "xcode-select --install"
|
|
return
|
|
fi
|
|
os_ids=""
|
|
if [ -r /etc/os-release ]; then
|
|
os_ids=$(sed -n 's/^ID\(_LIKE\)\{0,1\}=//p' /etc/os-release | tr -d '"' | tr '\n' ' ')
|
|
fi
|
|
for os_id in $os_ids; do
|
|
case "$os_id" in
|
|
debian|ubuntu) echo "sudo apt install python3"; return ;;
|
|
fedora|rhel|centos) echo "sudo dnf install python3"; return ;;
|
|
arch) echo "sudo pacman -S python"; return ;;
|
|
opensuse*|suse) echo "sudo zypper install python3"; return ;;
|
|
alpine) echo "apk add python3"; return ;;
|
|
esac
|
|
done
|
|
echo ""
|
|
}
|
|
|
|
if ! find_python; then
|
|
install_command=$(python_install_command)
|
|
# Termux installs without root: at a terminal, the bootstrap offers to run it.
|
|
if [ "$install_command" = "pkg install python" ] && (: </dev/tty) 2>/dev/null; then
|
|
printf 'Python 3.8 or newer is required. Install it now with "%s"? [Y/n] ' \
|
|
"$install_command" >/dev/tty
|
|
read -r answer </dev/tty || answer="n"
|
|
case "$answer" in
|
|
[Nn]*) ;;
|
|
*) pkg install -y python </dev/tty && find_python || true ;;
|
|
esac
|
|
fi
|
|
fi
|
|
if [ -z "$PYTHON" ]; then
|
|
echo "Error: Python 3.8 or newer is required." >&2
|
|
if [ -n "$install_command" ]; then
|
|
echo " Install it with: $install_command" >&2
|
|
echo " Then run this command again." >&2
|
|
else
|
|
echo " Install it with this system's package manager, then run this command again." >&2
|
|
fi
|
|
exit 1
|
|
fi
|
|
|
|
# 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.
|
|
# A downloaded installer is a temporary copy the user cannot run again: its
|
|
# hints rebuild the one-line command instead.
|
|
if [ -n "$TEMP_INSTALLER" ]; then
|
|
RETROBIOS_BOOTSTRAP=sh
|
|
export RETROBIOS_BOOTSTRAP
|
|
fi
|
|
if [ ! -t 0 ] && (: </dev/tty) 2>/dev/null; then
|
|
"$PYTHON" "$INSTALLER" "$@" </dev/tty
|
|
else
|
|
"$PYTHON" "$INSTALLER" "$@"
|
|
fi
|