RetroPie-Setup/scriptmodules/admin/setup.sh

462 lines
17 KiB
Bash

#!/usr/bin/env bash
# This file is part of The RetroPie Project
#
# The RetroPie Project is the legal property of its developers, whose names are
# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.
#
# See the LICENSE.md file at the top-level directory of this distribution and
# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md
#
rp_module_id="setup"
rp_module_desc="GUI based setup for RetroPie"
rp_module_section=""
function rps_logInit() {
if [[ ! -d "$__logdir" ]]; then
if mkdir -p "$__logdir"; then
chown $user:$user "$__logdir"
else
fatalError "Couldn't make directory $__logdir"
fi
fi
local now=$(date +'%Y-%m-%d_%H%M%S')
logfilename="$__logdir/rps_$now.log.gz"
touch "$logfilename"
chown $user:$user "$logfilename"
time_start=$(date +"%s")
}
function rps_logStart() {
echo "Log started at: $(date -d @$time_start)"
}
function rps_logEnd() {
time_end=$(date +"%s")
echo
echo "Log ended at: $(date -d @$time_end)"
date_total=$((time_end-time_start))
local hours=$((date_total / 60 / 60 % 24))
local mins=$((date_total / 60 % 60))
local secs=$((date_total % 60))
echo "Total running time: $hours hours, $mins mins, $secs secs"
}
function rps_printInfo() {
if [[ ${#__ERRMSGS[@]} -gt 0 ]]; then
printMsgs "dialog" "${__ERRMSGS[@]}"
printMsgs "dialog" "Please see $1 for more in depth information regarding the errors."
fi
printMsgs "dialog" "${__INFMSGS[@]}"
}
function rps_availFreeDiskSpace() {
local rootdirExists=0
if [[ ! -d "$rootdir" ]]; then
rootdirExists=1
mkdir -p $rootdir
fi
local __required=$1
local __avail=$(df -P $rootdir | tail -n1 | awk '{print $4}')
if [[ $rootdirExists -eq 1 ]]; then
rmdir $rootdir
fi
required_MB=$((__required/1024))
available_MB=$((__avail/1024))
if [[ "$__avail" -lt "$__required" ]]; then
dialog --yesno "Minimum recommended disk space ($required_MB MB) not available.\n\nTry 'raspi-config' to resize partition to full size. Only $available_MB MB available at $rootdir.\n\nContinue anyway?" 22 76 2>&1 >/dev/tty || exit 0
fi
}
function depends_setup() {
rps_availFreeDiskSpace 500000
if [[ "$__raspbian_ver" -eq 7 ]]; then
printMsgs "dialog" "Raspbian Wheezy is no longer supported. Binaries are no longer updated and new emulators may fail to build, install or run.\n\nPlease backup your system and start from the latest image."
fi
}
function updatescript_setup()
{
chown -R $user:$user "$scriptdir"
printHeading "Fetching latest version of the RetroPie Setup Script."
pushd "$scriptdir" >/dev/null
if [[ ! -d ".git" ]]; then
printMsgs "dialog" "Cannot find directory '.git'. Please clone the RetroPie Setup script via 'git clone https://github.com/RetroPie/RetroPie-Setup.git'"
popd >/dev/null
return 1
fi
local error
if ! error=$(su $user -c "git pull 2>&1 >/dev/null"); then
printMsgs "dialog" "Update failed:\n\n$error"
popd >/dev/null
return 1
fi
popd >/dev/null
printMsgs "dialog" "Fetched the latest version of the RetroPie Setup script."
return 0
}
function post_update_setup() {
# run _update_hook_id functions - eg to fix up modules for retropie-setup 4.x install detection
rp_updateHooks
printMsgs "dialog" "NOTICE: The RetroPie-Setup script and pre-made RetroPie SD card images are available to download for free from https://retropie.org.uk.\n\nIt has come to our attention that some people are profiting from selling RetroPie SD cards, some including copyrighted games. This is illegal.\n\nIf you have been sold this software on its own or including games, you can let us know about it by emailing retropieproject@gmail.com"
gui_setup
}
function package_setup() {
local idx="$1"
local md_id="${__mod_id[$idx]}"
while true; do
local options=()
rp_hasBinary "$idx" && options+=(B "Install/Update from binary")
if fnExists "sources_${md_id}"; then
options+=(S "Install/Update from source")
fi
if rp_isInstalled "$idx"; then
if fnExists "gui_${md_id}"; then
options+=(C "Configuration / Options")
fi
options+=(X "Remove")
fi
local help="${__mod_desc[$idx]}\n\n${__mod_help[$idx]}"
if [[ -n "$help" ]]; then
options+=(H "Package Help")
fi
cmd=(dialog --backtitle "$__backtitle" --cancel-label "Back" --menu "Choose an option for ${__mod_id[$idx]}" 22 76 16)
choice=$("${cmd[@]}" "${options[@]}" 2>&1 >/dev/tty)
local logfilename
__ERRMSGS=()
__INFMSGS=()
case "$choice" in
B|I)
rps_logInit
{
rp_installModule "$idx"
} &> >(tee >(gzip --stdout >"$logfilename"))
rps_printInfo "$logfilename"
;;
S)
rps_logInit
{
rp_callModule "$idx"
} &> >(tee >(gzip --stdout >"$logfilename"))
rps_printInfo "$logfilename"
;;
C)
rps_logInit
{
rp_callModule "$idx" gui
} &> >(tee >(gzip --stdout >"$logfilename"))
rps_printInfo "$logfilename"
;;
X)
local text="Are you sure you want to remove $md_id?"
[[ "${__mod_section[$idx]}" == "core" ]] && text+="\n\nWARNING - core packages are needed for RetroPie to function!"
dialog --defaultno --yesno "$text" 22 76 2>&1 >/dev/tty || continue
rps_logInit
{
rp_callModule "$idx" remove
} &> >(tee >(gzip --stdout >"$logfilename"))
rps_printInfo "$logfilename"
;;
H)
printMsgs "dialog" "$help"
;;
*)
break
;;
esac
done
}
function section_gui_setup() {
local section="$1"
while true; do
local options=()
rp_hasBinaries && options+=(B "Install/Update all ${__sections[$section]} packages from binary" "This will install all $section packages from binary archives (if available). If a binary archive is missing a source install will be performed.")
options+=(
S "Install/Update all ${__sections[$section]} packages from source" "This will build and install all the packages from $section from source. Building from source will pull in the very latest releases of many of the emulators. Building could fail or resulting binaries could not work. Only choose this option if you are comfortable in working with the linux console and debugging any issues."
X "Remove all ${__sections[$section]} packages" "This will remove all $section packages."
)
local idx
for idx in $(rp_getSectionIds $section); do
if rp_isInstalled "$idx"; then
installed="(Installed)"
else
installed=""
fi
options+=("$idx" "${__mod_id[$idx]} $installed" "${__mod_desc[$idx]}"$'\n\n'"${__mod_help[$idx]}")
done
local cmd=(dialog --backtitle "$__backtitle" --cancel-label "Back" --item-help --help-button --menu "Choose an option" 22 76 16)
local choice=$("${cmd[@]}" "${options[@]}" 2>&1 >/dev/tty)
[[ -z "$choice" ]] && break
if [[ "${choice[@]:0:4}" == "HELP" ]]; then
printMsgs "dialog" "${choice[@]:5}"
continue
fi
local logfilename
__ERRMSGS=()
__INFMSGS=()
case "$choice" in
B)
dialog --defaultno --yesno "Are you sure you want to install/update all $section packages from binary?" 22 76 2>&1 >/dev/tty || continue
rps_logInit
{
for idx in $(rp_getSectionIds $section); do
rp_installModule "$idx"
done
} &> >(tee >(gzip --stdout >"$logfilename"))
rps_printInfo "$logfilename"
;;
S)
dialog --defaultno --yesno "Are you sure you want to install/update all $section packages from source?" 22 76 2>&1 >/dev/tty || continue
rps_logInit
{
for idx in $(rp_getSectionIds $section); do
rp_callModule "$idx"
done
} &> >(tee >(gzip --stdout >"$logfilename"))
rps_printInfo "$logfilename"
;;
X)
local text="Are you sure you want to remove all $section packages?"
[[ "$section" == "core" ]] && text+="\n\nWARNING - core packages are needed for RetroPie to function!"
dialog --defaultno --yesno "$text" 22 76 2>&1 >/dev/tty || continue
rps_logInit
{
for idx in $(rp_getSectionIds $section); do
rp_isInstalled "$idx" && rp_callModule "$idx" remove
done
} &> >(tee >(gzip --stdout >"$logfilename"))
rps_printInfo "$logfilename"
;;
*)
package_setup "$choice"
;;
esac
done
}
function settings_gui_setup() {
while true; do
local options=()
local idx
for idx in "${__mod_idx[@]}"; do
# show all configuration modules and any installed packages with a gui function
if [[ "${__mod_section[idx]}" == "config" ]] || rp_isInstalled "$idx" && fnExists "gui_${__mod_id[idx]}"; then
options+=("$idx" "${__mod_id[$idx]} - ${__mod_desc[$idx]}" "${__mod_desc[$idx]}")
fi
done
local cmd=(dialog --backtitle "$__backtitle" --cancel-label "Back" --item-help --help-button --menu "Choose an option" 22 76 16)
local choice=$("${cmd[@]}" "${options[@]}" 2>&1 >/dev/tty)
[[ -z "$choice" ]] && break
if [[ "${choice[@]:0:4}" == "HELP" ]]; then
printMsgs "dialog" "${choice[@]:5}"
continue
fi
[[ -z "$choice" ]] && break
local logfilename
__ERRMSGS=()
__INFMSGS=()
rps_logInit
{
if fnExists "gui_${__mod_id[choice]}"; then
rp_callModule "$choice" depends
rp_callModule "$choice" gui
else
rp_callModule "$choice"
fi
} &> >(tee >(gzip --stdout >"$logfilename"))
rps_printInfo "$logfilename"
done
}
function update_packages_setup() {
local idx
for idx in ${__mod_idx[@]}; do
if rp_isInstalled "$idx"; then
rp_installModule "$idx"
fi
done
}
function update_packages_gui_setup() {
local update="$1"
if [[ "$update" != "update" ]]; then
dialog --defaultno --yesno "Are you sure you want to update installed packages?" 22 76 2>&1 >/dev/tty || return 1
if dialog --yesno "It is advisable to update the RetroPie-Setup script before updating packages - may I do this now ?" 22 76 2>&1 >/dev/tty; then
updatescript_setup
exec "$scriptdir/retropie_packages.sh" setup update_packages_gui update
fi
fi
local logfilename
__ERRMSGS=()
__INFMSGS=()
rps_logInit
{
dialog --yesno "Would you like to update the underlying OS packages (eg kernel etc) ?" 22 76 2>&1 >/dev/tty && apt_upgrade_raspbiantools
update_packages_setup
} &> >(tee >(gzip --stdout >"$logfilename"))
rps_printInfo "$logfilename"
}
function quick_install_setup() {
for idx in $(rp_getSectionIds core) $(rp_getSectionIds main); do
if rp_hasBinaries; then
rp_installModule "$idx"
else
rp_callModule "$idx"
fi
done
}
function packages_gui_setup() {
local section
local options=()
options+=(
I "Quick install" "This will install all packages from Core and Main which gives a basic RetroPie install. Further packages can then be installed later from the Optional and Experimental sections. If binaries are available they will be used, alternatively packages will be built from source - which will take longer."
U "Update all installed packages" "Update all currently installed packages"
)
for section in core main opt driver exp; do
options+=($section "Manage ${__sections[$section]} packages" "Choose top install/update/configure packages from the ${__sections[$section]}")
done
local cmd
while true; do
cmd=(dialog --backtitle "$__backtitle" --cancel-label "Back" --item-help --help-button --menu "Choose an option" 22 76 16)
local choice
choice=$("${cmd[@]}" "${options[@]}" 2>&1 >/dev/tty)
[[ -z "$choice" ]] && break
if [[ "${choice[@]:0:4}" == "HELP" ]]; then
printMsgs "dialog" "${choice[@]:5}"
continue
fi
case "$choice" in
I)
dialog --defaultno --yesno "Are you sure you want to do a quick install?" 22 76 2>&1 >/dev/tty || continue
quick_install_setup
;;
U)
update_packages_gui_setup
;;
*)
section_gui_setup "$choice"
;;
esac
done
}
function uninstall_setup()
{
dialog --defaultno --yesno "Are you sure you want to uninstall RetroPie?" 22 76 2>&1 >/dev/tty || return 0
printMsgs "dialog" "This feature is new, and you still may need to remove some files manually, such as symlinks for some emulators created in $home"
dialog --defaultno --yesno "Are you REALLY sure you want to uninstall RetroPie?\n\n$rootdir and $datadir will be removed - this includes your RetroPie configurations and ROMs." 22 76 2>&1 >/dev/tty || return 0
clear
printHeading "Uninstalling RetroPie"
for idx in "${__mod_idx[@]}"; do
rp_callModule $idx remove
done
rm -rfv "$rootdir"
rm -rfv "$datadir"
if dialog --defaultno --yesno "Do you want to remove all the system packages that RetroPie depends on? \n\nWARNING: this will remove packages like SDL even if they were installed before you installed RetroPie - it will also remove any package configurations - such as those in /etc/samba for Samba.\n\nIf unsure choose No (selected by default)." 22 76 2>&1 >/dev/tty; then
clear
# remove all dependencies
for idx in "${__mod_idx[@]}"; do
rp_callModule "$idx" depends remove
done
fi
}
function reboot_setup()
{
clear
reboot
}
# retropie-setup main menu
function gui_setup() {
while true; do
pushd "$scriptdir" >/dev/null
local commit=$(git log -1 --pretty=format:"%cr (%h)")
popd >/dev/null
cmd=(dialog --backtitle "$__backtitle" --title "Choose an option" --cancel-label "Exit" --item-help --help-button --menu "Script Version: $__version\nLast Commit: $commit" 22 76 16)
options=(
P "Manage Packages"
"Install/Remove and Configure the various components of RetroPie, including emulators, ports, and controller drivers."
S "Setup / Tools"
"Configuration Tools and additional setup. Any components of RetroPie that have configuration will also appear here after install."
X "Uninstall RetroPie"
"Uninstall RetroPie completely."
U "Update RetroPie-Setup script"
"Update this RetroPie-Setup script. Note that RetroPie-Setup is constantly updated - the version numbers were introduced primarily for the pre-made images we provided, but we now display a version in this menu as a guide. If you update the RetroPie-Setup script after downloading a pre-made image, you may get a higher version number or a -dev release. This does not mean the software is unstable, it just means we are working on changes for the next version, when we will create a new image."
R "Perform Reboot"
"Reboot your machine."
)
choice=$("${cmd[@]}" "${options[@]}" 2>&1 >/dev/tty)
if [[ -n "$choice" ]]; then
if [[ "${choice[@]:0:4}" == "HELP" ]]; then
printMsgs "dialog" "${choice[@]:5}"
continue
fi
clear
case "$choice" in
P)
packages_gui_setup
;;
S)
settings_gui_setup
;;
X)
uninstall_setup
;;
U)
updatescript_setup && exec "$scriptdir/retropie_packages.sh" setup post_update
;;
R)
dialog --defaultno --yesno "Are you sure you want to reboot?" 22 76 2>&1 >/dev/tty || continue
reboot_setup
;;
esac
else
break
fi
done
clear
}