diff --git a/README.md b/README.md index 93902f7..9a3f227 100644 --- a/README.md +++ b/README.md @@ -284,33 +284,25 @@ The following guides are available: If you already have a Windows VM or server you wish to use with WinApps, you will need to merge `install/RDPApps.reg` into the Windows Registry manually. -### Step 2: Clone WinApps Repository and Dependencies -1. Clone the WinApps GitHub repository. - ```bash - git clone --recurse-submodules --remote-submodules https://github.com/winapps-org/winapps.git && cd winapps - ``` - -2. Install the required dependencies. - - Debian/Ubuntu: - ```bash - sudo apt install -y dialog freerdp3-x11 iproute2 libnotify-bin netcat - ``` - - Fedora/RHEL: - ```bash - sudo dnf install -y dialog freerdp iproute libnotify nmap-ncat - ``` - - Arch Linux: - ```bash - sudo pacman -Syu --needed -y dialog freerdp iproute2 libnotify gnu-netcat - ``` - - Gentoo Linux: - ```bash - sudo emerge --ask=n sys-libs/dialog net-misc/freerdp:3 net-misc/iproute2 x11-libs/libnotify net-analyzer/netcat - ``` - -- `Docker Engine`: https://docs.docker.com/engine/install/ -- `Podman`: https://podman.io/docs/installation -- `podman-compose`: https://github.com/containers/podman-compose +### Step 2: Install Dependencies +Install the required dependencies. + - Debian/Ubuntu: + ```bash + sudo apt install -y dialog freerdp3-x11 iproute2 libnotify-bin netcat + ``` + - Fedora/RHEL: + ```bash + sudo dnf install -y dialog freerdp iproute libnotify nmap-ncat + ``` + - Arch Linux: + ```bash + sudo pacman -Syu --needed -y dialog freerdp iproute2 libnotify + gnu-netcat + ``` + - Gentoo Linux: + ```bash + sudo emerge --ask=n sys-libs/dialog net-misc/freerdp:3 net-misc/iproute2 x11-libs/libnotify net-analyzer/netcat + ``` > [!NOTE] > WinApps requires `FreeRDP` version 3 or later. If not available for your distribution through your package manager, you can install the [Flatpak](https://flathub.org/apps/com.freerdp.FreeRDP). @@ -443,7 +435,7 @@ FREERDP_COMMAND="" ### Step 4: Run the WinApps Installer Run the WinApps installer. ```bash -./setup.sh +bash <(curl https://raw.githubusercontent.com/winapps-org/winapps/main/setup.sh) ``` A list of supported additional arguments can be accessed by running `./setup.sh --help`. @@ -461,15 +453,15 @@ Adding your own applications with custom icons and MIME types to the installer i WinApps offers a manual mode for running applications that were not configured by the WinApps installer. This is completed with the `manual` flag. Executables that are in the Windows PATH do not require full path definition. ```bash -./bin/winapps manual "C:\my\directory\executableNotInPath.exe" -./bin/winapps manual executableInPath.exe +winapps manual "C:\my\directory\executableNotInPath.exe" +winapps manual executableInPath.exe ``` ## Updating WinApps The installer can be run multiple times. To update your installation of WinApps: 1. Run the WinApps installer to remove WinApps from your system. 2. Pull the latest changes from the WinApps GitHub repository. -3. Re-install WinApps using the WinApps installer. +3. Re-install WinApps using the WinApps installer by running `winapps-setup`. ## Star History diff --git a/setup.sh b/setup.sh index e878442..bb51273 100755 --- a/setup.sh +++ b/setup.sh @@ -37,6 +37,9 @@ readonly EC_INVALID_FLAVOR="16" # Backend specified is not 'libvirt', 'docker' readonly SYS_BIN_PATH="/usr/local/bin" # UNIX path to 'bin' directory for a '--system' WinApps installation. readonly USER_BIN_PATH="${HOME}/.local/bin" # UNIX path to 'bin' directory for a '--user' WinApps installation. readonly USER_BIN_PATH_WIN='\\tsclient\home\.local\bin' # WINDOWS path to 'bin' directory for a '--user' WinApps installation. +# 'SOURCE' +readonly SYS_SOURCE_PATH="${SYS_BIN_PATH}/winapps" # UNIX path to WinApps source directory for a '--system' WinApps installation. +readonly USER_SOURCE_PATH="${USER_BIN_PATH}/winapps" # UNIX path to WinApps source directory for a '--system' WinApps installation. # 'APP' readonly SYS_APP_PATH="/usr/share/applications" # UNIX path to 'applications' directory for a '--system' WinApps installation. readonly USER_APP_PATH="${HOME}/.local/share/applications" # UNIX path to 'applications' directory for a '--user' WinApps installation. @@ -98,6 +101,7 @@ SUDO="" # Set to "sudo" if the user specifies '--system', or "" if the u BIN_PATH="" # Set to $SYS_BIN_PATH if the user specifies '--system', or $USER_BIN_PATH if the user specifies '--user'. APP_PATH="" # Set to $SYS_APP_PATH if the user specifies '--system', or $USER_APP_PATH if the user specifies '--user'. APPDATA_PATH="" # Set to $SYS_APPDATA_PATH if the user specifies '--system', or $USER_APPDATA_PATH if the user specifies '--user'. +SOURCE_PATH="" # Set to $SYS_SOURCE_PATH if the user specifies '--system', or $USER_SOURCE_PATH if the user specifies '--user'. # INSTALLATION PROCESS INSTALLED_EXES=() # List of executable file names of officially supported applications that have already been configured during the current installation process. @@ -134,29 +138,40 @@ function waUsage() { ${COMMAND_TEXT}./setup.sh --help${CLEAR_TEXT} # Display this usage message." } -# Name: 'waSetWorkingDirectory' -# Role: Changes the working directory to the directory containing the script. -function waSetWorkingDirectory() { +# Name: 'waGetSourceCode' +# Role: Grab the WinApps source code using Git. +function waGetSourceCode() { # Declare variables. local SCRIPT_DIR_PATH="" # Stores the absolute path of the directory containing the script. # Determine the absolute path to the directory containing the script. SCRIPT_DIR_PATH=$(readlink -f "$(dirname "${BASH_SOURCE[0]}")") + # Check if winapps is currently installed on $SOURCE_PATH + if [[ -f "$SCRIPT_DIR_PATH/winapps" && "$SCRIPT_DIR_PATH" -ne "$SOURCE_PATH" ]]; then + # Display a warning. + echo -e "${WARNING_TEXT}[WARNING]${CLEAR_TEXT} You are running a WinApps installation located outside of default location '${SOURCE_PATH}'. A new installation will be created." + echo -e "${WARNING_TEXT}[WARNING]${CLEAR_TEXT} You might want to remove your old installation on '${SCRIPT_DIR_PATH}'." + fi + + if [[ ! -d "$SOURCE_PATH" ]]; then + $SUDO git clone --recurse-submodules --remote-submodules https://github.com/winapps-org/winapps.git "$SOURCE_PATH" + fi + # Silently change the working directory. - if ! cd "$SCRIPT_DIR_PATH" &>/dev/null; then + if ! cd "$SOURCE_PATH" &>/dev/null; then # Display the error type. echo -e "${ERROR_TEXT}ERROR:${CLEAR_TEXT} ${BOLD_TEXT}DIRECTORY CHANGE FAILURE.${CLEAR_TEXT}" # Display error details. - echo -e "${INFO_TEXT}Failed to change the working directory to ${CLEAR_TEXT}${COMMAND_TEXT}${SCRIPT_DIR_PATH}${CLEAR_TEXT}${INFO_TEXT}.${CLEAR_TEXT}" + echo -e "${INFO_TEXT}Failed to change the working directory to ${CLEAR_TEXT}${COMMAND_TEXT}${SOURCE_PATH}${CLEAR_TEXT}${INFO_TEXT}.${CLEAR_TEXT}" # Display the suggested action(s). echo "--------------------------------------------------------------------------------" echo "Ensure:" - echo -e " - ${COMMAND_TEXT}${SCRIPT_DIR_PATH}${CLEAR_TEXT} exists." - echo -e " - ${COMMAND_TEXT}${SCRIPT_DIR_PATH}${CLEAR_TEXT} is valid and does not contain syntax errors." - echo -e " - The current user has sufficient permissions to access ${COMMAND_TEXT}${SCRIPT_DIR_PATH}${CLEAR_TEXT}." + echo -e " - ${COMMAND_TEXT}${SOURCE_PATH}${CLEAR_TEXT} exists." + echo -e " - ${COMMAND_TEXT}${SOURCE_PATH}${CLEAR_TEXT} has been cloned and checked out properly." + echo -e " - The current user has sufficient permissions to access and write to ${COMMAND_TEXT}${SOURCE_PATH}${CLEAR_TEXT}." echo "--------------------------------------------------------------------------------" # Terminate the script. @@ -301,11 +316,13 @@ function waCheckInput() { function waConfigurePathsAndPermissions() { if [ "$OPT_USER" -eq 1 ]; then SUDO="" + SOURCE_PATH="$USER_SOURCE_PATH" BIN_PATH="$USER_BIN_PATH" APP_PATH="$USER_APP_PATH" APPDATA_PATH="$USER_APPDATA_PATH" elif [ "$OPT_SYSTEM" -eq 1 ]; then SUDO="sudo" + SOURCE_PATH="$SYS_SOURCE_PATH" BIN_PATH="$SYS_BIN_PATH" APP_PATH="$SYS_APP_PATH" APPDATA_PATH="$SYS_APPDATA_PATH" @@ -337,7 +354,7 @@ function waCheckExistingInstall() { echo -n "Checking for existing conflicting WinApps installations... " # Check for an existing 'user' installation. - if [ -f "${USER_BIN_PATH}/winapps" ]; then + if [[ -f "${USER_BIN_PATH}/winapps" || -d "${USER_SOURCE_PATH}/winapps" ]]; then # Complete the previous line. echo -e "${FAIL_TEXT}Failed!${CLEAR_TEXT}\n" @@ -357,7 +374,7 @@ function waCheckExistingInstall() { fi # Check for an existing 'system' installation. - if [ -f "${SYS_BIN_PATH}/winapps" ]; then + if [[ -f "${SYS_BIN_PATH}/winapps" || -d "${USER_SOURCE_PATH}/winapps" ]]; then # Complete the previous line. echo -e "${FAIL_TEXT}Failed!${CLEAR_TEXT}\n" @@ -450,6 +467,54 @@ function waLoadConfig() { # Name: 'waCheckScriptDependencies' # Role: Terminate script if dependencies are missing. function waCheckScriptDependencies() { + # 'Git' + if ! command -v git &>/dev/null; then + # Display the error type. + echo -e "${ERROR_TEXT}ERROR:${CLEAR_TEXT} ${BOLD_TEXT}MISSING DEPENDENCIES.${CLEAR_TEXT}" + + # Display the error details. + echo -e "${INFO_TEXT}Please install 'git' to proceed.${CLEAR_TEXT}" + + # Display the suggested action(s). + echo "--------------------------------------------------------------------------------" + echo "Debian/Ubuntu-based systems:" + echo -e " ${COMMAND_TEXT}sudo apt install git${CLEAR_TEXT}" + echo "Red Hat/Fedora-based systems:" + echo -e " ${COMMAND_TEXT}sudo dnf install git${CLEAR_TEXT}" + echo "Arch Linux systems:" + echo -e " ${COMMAND_TEXT}sudo pacman -S git${CLEAR_TEXT}" + echo "Gentoo Linux systems:" + echo -e " ${COMMAND_TEXT}sudo emerge --ask dev-vcs/git${CLEAR_TEXT}" + echo "--------------------------------------------------------------------------------" + + # Terminate the script. + return "$EC_MISSING_DEPS" + fi + + # 'curl' + if ! command -v curl &>/dev/null; then + # Display the error type. + echo -e "${ERROR_TEXT}ERROR:${CLEAR_TEXT} ${BOLD_TEXT}MISSING DEPENDENCIES.${CLEAR_TEXT}" + + # Display the error details. + echo -e "${INFO_TEXT}Please install 'curl' to proceed.${CLEAR_TEXT}" + + # Display the suggested action(s). + echo "--------------------------------------------------------------------------------" + echo "Debian/Ubuntu-based systems:" + echo -e " ${COMMAND_TEXT}sudo apt install curl${CLEAR_TEXT}" + echo "Red Hat/Fedora-based systems:" + echo -e " ${COMMAND_TEXT}sudo dnf install curl${CLEAR_TEXT}" + echo "Arch Linux systems:" + echo -e " ${COMMAND_TEXT}sudo pacman -S curl${CLEAR_TEXT}" + echo "Gentoo Linux systems:" + echo -e " ${COMMAND_TEXT}sudo emerge --ask net-misc/curl${CLEAR_TEXT}" + echo "--------------------------------------------------------------------------------" + + # Terminate the script. + return "$EC_MISSING_DEPS" + fi + # 'Dialog'. if ! command -v dialog &>/dev/null; then # Display the error type. @@ -852,7 +917,7 @@ function waCheckContainerRunning() { # Display the suggested action(s). echo "--------------------------------------------------------------------------------" echo "Please ensure Windows is powered on:" - echo -e "${COMMAND_TEXT}${COMPOSE_COMMAND} --file ~/.config/winapps/winapps.conf start${CLEAR_TEXT}" + echo -e "${COMMAND_TEXT}${COMPOSE_COMMAND} --file ~/.config/winapps/compose.yaml start${CLEAR_TEXT}" echo "--------------------------------------------------------------------------------" # Terminate the script. @@ -1469,6 +1534,9 @@ function waInstall() { # Check for missing dependencies. waCheckInstallDependencies + # Get the source code + waGetSourceCode + # Update $MULTI_FLAG. if [[ $MULTIMON == "true" ]]; then MULTI_FLAG="/multimon" @@ -1536,8 +1604,9 @@ function waInstall() { # Check for installed applications. waFindInstalled - # Install the WinApps bash script. - $SUDO cp "./bin/winapps" "${BIN_PATH}/winapps" + # Install the WinApps bash scripts. + $SUDO ln -s "./bin/winapps" "${BIN_PATH}/winapps" + $SUDO ln -s "./setup.sh" "${BIN_PATH}/winapps-setup" # Configure the Windows RDP session application launcher. waConfigureWindows @@ -1553,10 +1622,27 @@ function waInstall() { waConfigureDetectedApps fi + # Ensure BIN_PATH is on PATH + waEnsureOnPath + # Print feedback. echo -e "${SUCCESS_TEXT}INSTALLATION COMPLETE.${CLEAR_TEXT}" } +# Name: 'waEnsureOnPath' +# Role: Ensures that $BIN_PATH is on $PATH. +function waEnsureOnPath() { + if [[ ":$PATH:" == *":$BIN_PATH:"* ]]; then + echo -e "${WARNING_TEXT}[WARNING]${CLEAR_TEXT} It seems like '${BIN_PATH}' is not on PATH." + echo -e "${WARNING_TEXT}[WARNING]${CLEAR_TEXT} You can add it by running:" + # shellcheck disable=SC2086 + echo -e "${WARNING_TEXT}[WARNING]${CLEAR_TEXT} - For Bash: ${COMMAND_TEXT}echo 'export PATH="${BIN_PATH}:\$PATH"' >> ~/.bashrc${CLEAR_TEXT}" + # shellcheck disable=SC2086 + echo -e "${WARNING_TEXT}[WARNING]${CLEAR_TEXT} - For ZSH: ${COMMAND_TEXT}echo 'export PATH="${BIN_PATH}:\$PATH"' >> ~/.zshrc${CLEAR_TEXT}" + echo -e "${WARNING_TEXT}[WARNING]${CLEAR_TEXT} Make sure to restart your Terminal afterwards.\n" + fi +} + # Name: 'waUninstall' # Role: Uninstalls WinApps. function waUninstall() { @@ -1570,8 +1656,9 @@ function waUninstall() { local DESKTOP_FILE_NAME="" # Stores the name of the '.desktop' file for the application. local BASH_SCRIPT_NAME="" # Stores the name of the application. - # Remove the 'WinApps' bash script. + # Remove the 'WinApps' bash scripts. $SUDO rm -f "${BIN_PATH}/winapps" + $SUDO rm -f "${BIN_PATH}/winapps-setup" # Remove WinApps configuration data, temporary files and logs. rm -rf "$USER_APPDATA_PATH" @@ -1622,9 +1709,10 @@ function waUninstall() { done # Print caveats. - echo -e "\n${INFO_TEXT}Please note your WinApps configuration folder was not removed.${CLEAR_TEXT}" - echo -e "${INFO_TEXT}You can remove this manually by running:${CLEAR_TEXT}" - echo -e "${COMMAND_TEXT}rm -r $(dirname "$CONFIG_PATH")${CLEAR_TEXT}\n" + echo -e "\n${INFO_TEXT}Please note that your WinApps configuration and the WinApps source code were not removed.${CLEAR_TEXT}" + echo -e "${INFO_TEXT}You can remove these manually by running:${CLEAR_TEXT}" + echo -e "${COMMAND_TEXT}rm -r $(dirname "$CONFIG_PATH")${CLEAR_TEXT}" + echo -e "${COMMAND_TEXT}rm -r ${SOURCE_PATH}${CLEAR_TEXT}\n" # Print feedback. echo -e "${SUCCESS_TEXT}UNINSTALLATION COMPLETE.${CLEAR_TEXT}" @@ -1647,9 +1735,6 @@ waCheckScriptDependencies # shellcheck source=/dev/null # Exclude this file from being checked by ShellCheck. source "$INQUIRER_PATH" -# Set the working directory. -waSetWorkingDirectory - # Sanitise and parse the user input. waCheckInput "$@"