diff --git a/APP-MANAGER b/APP-MANAGER index 0992a5e83..a29cf0ee5 100755 --- a/APP-MANAGER +++ b/APP-MANAGER @@ -1,11 +1,15 @@ #!/usr/bin/env bash -AMVERSION="7.8.1-1" +AMVERSION="8" # Determine main repository and branch AMREPO="https://raw.githubusercontent.com/ivan-hc/AM/main" AMBRANCH=$(basename "$AMREPO") +# Determine catalogue in use +export AMCATALOGUEMARKDOWNS="https://portable-linux-apps.github.io/apps" +export AMCATALOGUEICONS="https://portable-linux-apps.github.io/icons" + # Determine the name of this script and its working directory export REALDIR="$PWD" DIR="$( cd "$( dirname "$0" )" && pwd )" @@ -13,16 +17,16 @@ CLI=$(basename "$0") # Determine system architecture and current user arch="$HOSTTYPE" -export currentuser="$USER" +export ARCH="$arch" # XDG Variables -BINDIR="${XDG_BIN_HOME:-$HOME/.local/bin}" -DATADIR="${XDG_DATA_HOME:-$HOME/.local/share}" -CONFIGDIR="${XDG_CONFIG_HOME:-$HOME/.config}" +export BINDIR="${XDG_BIN_HOME:-$HOME/.local/bin}" +export DATADIR="${XDG_DATA_HOME:-$HOME/.local/share}" +export CONFIGDIR="${XDG_CONFIG_HOME:-$HOME/.config}" export CACHEDIR="${XDG_CACHE_HOME:-$HOME/.cache}" function _create_cache_dir() { - AMCACHEDIR="$AMPATH/.cache" + AMCACHEDIR="$CACHEDIR/$AMCLI" mkdir -p "$AMCACHEDIR" } @@ -36,7 +40,9 @@ SCRIPTDIR="$(xdg-user-dir DESKTOP 2>/dev/null || echo "$HOME")" export SCRIPTDIR # Colors -RED='\033[0;31m'; LightBlue='\033[1;34m'; Green='\033[0;32m' +RED='\033[0;31m'; Gold='\033[0;33m'; Green='\033[0;32m'; LightBlue='\033[1;34m'; +DIVIDING_LINE="--------------------\ +---------------------------------------------------------" # Prevent the use of "sudo" ("AM") function _no_sudo() { @@ -48,60 +54,32 @@ function _no_sudo() { _no_sudo -##################### # "AM" CORE VARIABLES -##################### - function _am() { AMCLI="am" AMCLIPATH="$AMCLI" if command -v sudo >/dev/null 2>&1; then - SUDOCOMMAND="sudo" + SUDOCMD="sudo" elif command -v doas >/dev/null 2>&1; then - SUDOCOMMAND="doas" + SUDOCMD="doas" else echo 'ERROR: No sudo or doas found' exit 1 fi - COMPLETIONPATH="/etc/bash_completion.d" - COMPLETIONFILE="am-completion.sh" APPSPATH="/opt" AMPATH="$APPSPATH/$AMCLI" _create_cache_dir mkdir -p "$AMPATH"/modules } -####################################### # "APPMAN" CORE VARIABLES AND FUNCTIONS -####################################### - -function _check_if_home_local_bin_is_not_in_path() { - if ! echo "$PATH" | grep -q "$BINDIR"; then - echo "--------------------------------------------------------------------------" - echo " ⚠️ WARNING: \"${XDG_BIN_HOME:-$HOME/.local/bin}\" is not in PATH, apps may not run." - read -rp " ◆ Want to add it to ~/.profile and ~/.bash_profile? (Y/n): " yn - if ! echo "$yn" | grep -i '^n' >/dev/null 2>&1; then - if test -f "$HOME/.profile"; then - printf '\n%s\n' 'export PATH="$PATH:${XDG_BIN_HOME:-$HOME/.local/bin}"' >> "$HOME/.profile" - elif test -f "$HOME/.bash_profile"; then - printf '\n%s\n' 'export PATH="$PATH:${XDG_BIN_HOME:-$HOME/.local/bin}"' >> "$HOME/.bash_profile" - fi - echo "--------------------------------------------------------------------------" - echo " You might need to resource above files or reboot to apply these changes." - echo "--------------------------------------------------------------------------" - fi - fi -} - function _appman_initialize() { APPSDIR=$1 mkdir -p ~/"$APPSDIR"/appman/modules mkdir -p "$BINDIR" "$DATADIR"/applications "$DATADIR"/icons AMCLI="appman" AMCLIPATH="$DIR/$AMCLI" - SUDOCOMMAND="" - COMPLETIONPATH="$HOME" - COMPLETIONFILE=".bash_completion" + SUDOCMD="" APPSPATH="$HOME/$APPSDIR" AMPATH="$HOME/$APPSDIR/$AMCLI" _create_cache_dir @@ -109,22 +87,18 @@ function _appman_initialize() { function _appman_prompt_for_directory() { local location - read -r -ep "Please, write the name or the path of your custom application's folder: $(echo -e '\n\n '"$HOME"'/')" location + read -r -ep " Please, write the name or the path of your custom application's folder: $(echo -e '\n\n '"$HOME"'/')" location echo "$location" } function _appman_validate_directory() { location=$1 if [ "$location" = "" ]; then - echo "--------------------------------------------------------------------------" - echo "OPERATION ABORTED!" + echo -e "$DIVIDING_LINE\nOPERATION ABORTED!" exit 1 elif [ "$location" = ".local/bin" ]; then - echo "--------------------------------------------------------------------------" - echo " 💀 ERROR, you can't install applications into a \"\$PATH\"" - echo " The ~/.local/bin directory is normally used for executables." - echo " Please, choose a different path and retry!" - echo "--------------------------------------------------------------------------" + echo -e "$DIVIDING_LINE\n 💀 ERROR, you can't install applications into a \"\$PATH\"" + echo -e " The ~/.local/bin directory is normally used for executables.\n Please, choose a different path and retry! \n$DIVIDING_LINE" exit 1 else location_appman="${location/#$HOME}" @@ -137,81 +111,67 @@ function _appman_validate_directory() { function _appman() { if [ ! -f "$APPMANCONFIG"/appman-config ]; then - echo "--------------------------------------------------------------------------" - echo " >>> Thank you for choosing AppMan!" - echo "--------------------------------------------------------------------------" - echo "Before proceeding with any task, write the name of the directory in which" - echo 'you will install the apps, for example "Programs" or "My-apps", you can ' - echo 'also choose a subfolder, for example ".local/My-apps" or a deeper path.' - echo "" - echo "The destination folder will be created in $HOME" - echo "" - echo "SYNTAX: PATH/TO/DIRNAME" - echo "" - echo 'NOTE, any spaces or "/" at the beginning and end will be removed. If you ' - echo 'decide to change your choice in the future, first remove all the programs' - echo 'and then edit the ~/.config/appman/appman-config text file.' - echo "--------------------------------------------------------------------------" - echo "" + echo -e "$DIVIDING_LINE\n >>> Thank you for choosing AppMan! \n$DIVIDING_LINE" + echo " Before proceeding with any task, write the name of the directory in which" + echo " you will install the apps, for example \"Programs\" or \"My-apps\", you can" + echo " also choose a subfolder, for example \".local/My-apps\" or a deeper path." + echo -e "\n The destination folder will be created in $HOME\n" + echo -e " SYNTAX: PATH/TO/DIRNAME\n" + echo " NOTE, any spaces or "/" at the beginning and end will be removed. If you" + echo " decide to change your choice in the future, first remove all the programs" + echo -e " and then edit the ~/.config/appman/appman-config text file.\n$DIVIDING_LINE\n" location=$(_appman_prompt_for_directory) validated_location=$(_appman_validate_directory "$location") mkdir -p "$APPMANCONFIG" echo "$validated_location" >> "$APPMANCONFIG"/appman-config - echo '--------------------------------------------------------------------------' - echo 'You are ready! Start installing your favorite apps locally!!' - echo "All apps will be installed in $HOME/$validated_location" - echo "" - echo 'In case of problems, use the option "-h".' - echo '--------------------------------------------------------------------------' + echo -e "$DIVIDING_LINE\n You are ready! Start installing your favorite apps locally!" + echo " All apps will be installed in $HOME/$validated_location" + echo -e "\n In case of problems, use the option \"-h\".\n$DIVIDING_LINE" fi _appman_initialize "$(<"$APPMANCONFIG"/appman-config)" - - _check_if_home_local_bin_is_not_in_path + if ! echo "$PATH" | grep -q "$BINDIR"; then + echo -e "$DIVIDING_LINE\n ⚠️ WARNING: \"$BINDIR\" is not in PATH, apps may not run.\n$DIVIDING_LINE" + fi } -######################################## # DETERMINE WHEN TO USE "AM" OR "APPMAN" -######################################## - -if [ "$DIR/$CLI" = "/usr/local/bin/am" ] 2>/dev/null; then +if [ "$(realpath $0)" = "/opt/am/APP-MANAGER" ]; then + _am +elif [ "$(realpath $0)" = "/usr/bin/am" ]; then _am else _appman fi - AMCLIUPPER=$(echo "$AMCLI" | tr '[:lower:]' '[:upper:]') -# Set header authorization if GitHub API key file exists -[ -f "$AMPATH/ghapikey.txt" ] && HeaderAuthWithGITPAT=" --header \"Authorization: token $(<"$AMPATH/ghapikey.txt")\" " +# Create new data directory and move important files there +AMDATADIR="$DATADIR/AM" +mkdir -p "$AMDATADIR" +[ -f "$AMPATH/betatester" ] && mv "$AMPATH/betatester" "$AMDATADIR/betatester" +[ -f "$AMPATH/list" ] && mv "$AMPATH/list" "$AMDATADIR/list" +[ -f "$AMPATH/$arch-apps" ] && mv "$AMPATH/$arch-apps" "$AMDATADIR/$arch-apps" -################ # DEVELOPER MODE -################ - -if test -f "$AMPATH"/betatester; then +if test -f "$AMDATADIR"/betatester; then AMREPO="https://raw.githubusercontent.com/ivan-hc/AM/dev" AMBRANCH=$(basename "$AMREPO") fi + function _betatester_message_on() { - if test -f "$AMPATH"/betatester; then - echo '--------------------------------------------------------------------------' - echo "\"$AMCLI\" $AMVERSION: developer mode" | tr '[:lower:]' '[:upper:]' - echo '--------------------------------------------------------------------------' + if test -f "$AMDATADIR"/betatester; then + echo -e "$DIVIDING_LINE\n\"$AMCLIUPPER\" $AMVERSION: DEVELOPER MODE\n$DIVIDING_LINE" fi } -function _use_betatester_on() { - touch "$AMPATH"/betatester -} - -function _use_betatester_off() { - rm -f "$AMPATH"/betatester -} +# Apps database in use +APPSDB="$AMREPO/programs/$arch" +APPSLISTDB="$AMREPO/programs/$arch-apps" -########################################### -# FUNCTIONS RELATED TO THE SAFE USE OF "AM" -########################################### +################################################################################ +# SECURITY +################################################################################ +# SAFETY CHECKS function _am_dependences_check() { # Check for essential commands required by the application missing_deps=() @@ -224,17 +184,14 @@ function _am_dependences_check() { # Exit if any essential command is missing if [ -n "$missing_deps" ]; then - echo '--------------------------------------------------------------------------' + echo "$DIVIDING_LINE" printf " ${RED}💀 ERROR! MISSING ESSENTIAL COMMANDS\033[0m: %s\n\n Install the above and try again! \n" "${missing_deps[*]}" - echo '--------------------------------------------------------------------------' - echo -e "\n ${Green}List of the $AMCLIUPPER $AMVERSION core dependences\033[0m:\n" + echo -e "$DIVIDING_LINE\n ${Green}List of the $AMCLIUPPER $AMVERSION core dependences\033[0m:\n" echo "$AMDEPENDENCES" | tr ' ' ',' | sed 's/,/, /g' | sed 's/^/ /g' - echo "" - echo '--------------------------------------------------------------------------' + echo -e "\n$DIVIDING_LINE" echo " If this message appears it is because you are missing some dependency" echo " and if its the first time its because something new has been introduced." - echo -e "\n See ${LightBlue}https://github.com/ivan-hc/AM#core-dependences\033[0m for more information" - echo '--------------------------------------------------------------------------' + echo -e "\n See ${LightBlue}https://github.com/ivan-hc/AM#core-dependences\033[0m for more information\n$DIVIDING_LINE" exit 1 fi } @@ -243,10 +200,12 @@ function _am_security_check() { _am_dependences_check # Check and create the $AMPATH directory if it does not exist if [ ! -d "$AMPATH" ]; then - $SUDOCOMMAND mkdir -p "$AMPATH" + $SUDOCMD mkdir -p "$AMPATH" fi } +_am_security_check + # Function to check online connections (uses github.com by default, as the database and CLI itself are stored/hosted there) function _online_check() { if ! wget -q --tries=10 --timeout=20 --spider https://github.com; then @@ -255,65 +214,122 @@ function _online_check() { fi } -########################################### -# FUNCTIONS RELATED TO THE DATABASE OF APPS -########################################### +################################################################################ +# 3RD PARTY +################################################################################ + +function _newrepo_list_available() { + [ ! -f "$AMDATADIR/newrepo-lists" ] && echo " ERROR, \"$AMDATADIR/newrepo-lists\" file not found" && exit 1 +} +function _use_newrepo() { + [ -z "$2" ] && echo " USAGE: $AMCLI $1 [ARGUMENT]" && exit 1 + case $2 in + 'add') + [ -z "$3" ] && echo -e " USAGE: $AMCLI $1 $2 /path/to/dir\n $AMCLI $1 $2 {URL}" && exit 1 + echo "$3" >> "$AMDATADIR/newrepo-lists" + ;; + 'enable'|'on') + _newrepo_list_available + [ -f "$AMDATADIR/newrepo-off" ] && mv "$AMDATADIR/newrepo-off" "$AMDATADIR/newrepo-on" && echo " New repo ON!" + ;; + 'disable'|'off') + _newrepo_list_available + [ -f "$AMDATADIR/newrepo-on" ] && mv "$AMDATADIR/newrepo-on" "$AMDATADIR/newrepo-off" && echo " New repo OFF!" + ;; + 'info') + echo -e " Source: $AMREPO\n Apps: $APPSDB\n List: $APPSLISTDB" + ;; + 'purge') + [ -f "$AMDATADIR/newrepo-lists" ] && rm -f "$AMDATADIR"/newrepo* && echo " Removed all 3rd party repositories" + ;; + 'select') + _newrepo_list_available + printf "Select a repo from the list or press CTRL+C to abort:\n$DIVIDING_LINE\n"; sleep 1 + select repo in $(sort -u "$AMDATADIR/newrepo-lists" | uniq); do + test -n "$repo" && break + echo ">>> Invalid Selection" + done + echo "$repo" > "$AMDATADIR/newrepo-on" + ;; + esac +} + +# 3RD PARTY DATABASES function _am_newrepo_check() { # Determine if the CLI uses the "main" branch of https://github.com/ivan-hc/AM or an alternative one - if [ -f "$AMPATH"/new-repo.txt ]; then - AMREPO=$(<"$AMPATH/new-repo.txt") # Utilizing command substitution with < for more efficient file reading - AMBRANCH=$(basename "$AMREPO") - export APPSDB="$AMREPO/programs/$arch" - export APPSLISTDB="$AMREPO/programs/$arch-apps" - export LIBSLISTDB="$AMREPO/programs/libs-list" - if [ "$*" != "newrepo off" ]; then - echo '--------------------------------------------------------------------------' - echo " Source: $AMREPO" - echo '--------------------------------------------------------------------------' + if [ -f "$AMDATADIR/newrepo-on" ]; then + if grep -q "^http" "$AMDATADIR/newrepo-on"; then + AMREPO=$(<"$AMDATADIR/newrepo-on") + elif grep -q "^/" "$AMDATADIR/newrepo-on"; then + AMREPO="file://$(<"$AMDATADIR/newrepo-on")" fi - else + AMBRANCH=$(basename "$AMREPO") export APPSDB="$AMREPO/programs/$arch" export APPSLISTDB="$AMREPO/programs/$arch-apps" - export LIBSLISTDB="$AMREPO/programs/libs-list" + export AMCATALOGUEMARKDOWNS="" + export AMCATALOGUEICONS="" + [ "$1" != "newrepo" ] && [ "$1" != "neodb" ] && echo -e "$DIVIDING_LINE\n Source: $AMREPO\n$DIVIDING_LINE" fi } -function _am_databases_check() { - # Determine catalogue in use - export AMCATALOGUEMARKDOWNS="https://portable-linux-apps.github.io/apps" - export AMCATALOGUEICONS="https://portable-linux-apps.github.io/icons" - _am_newrepo_check "$@" - # To implement future application database changes - if [ -f "$AMPATH/neodb" ]; then - if grep -q "://" "$AMPATH/neodb"; then - if grep -q "#STATUS=quiet" "$AMPATH/neodb"; then - case "$1" in - '-a'|'about'|'-d'|'download'|'-i'|'install'|'-l'|'list'|'-q'|'query') - echo '--------------------------------------------------------------------------' - echo " Source: Third party repositories are enabled" - echo '--------------------------------------------------------------------------' - ;; - esac - fi - fi - fi +_am_newrepo_check "$@" + +################################################################################ +# UTILITIES +################################################################################ + +# COMPLETION LIST +available_options="about add apikey backup clean config disable downgrade download enable extra files \ + home info install launcher list lock neodb newrepo nolibfuse off on overwrite purge query \ + remove sandbox select sync template test unlock update --appimages --apps --byname --config \ + --convert --debug --devmode-disable --devmode-enable --force-latest --home --launcher --less \ + --pkg --rollback --disable-sandbox --sandbox --system --user" + +function _completion_lists() { + # Remove existing lists and download new ones + curl -Ls "$APPSLISTDB" > "$AMDATADIR/$arch-apps" + awk -v FS="(◆ | : )" '{print $2}' <"$AMDATADIR"/"$arch"-apps > "$AMDATADIR"/list + # Append options to the list + for o in $available_options; do + echo "$o" >> "$AMDATADIR"/list + done } -##################################### -# CHECK VERSION OF THE INSTALLED APPS -##################################### +# BASH AND ZSH COMPLETION +completion_file="${ZDOTDIR:-$HOME}"/.bash_completion +if ! grep -qo " $AMCLI$" "$completion_file" >/dev/null 2>&1; then + echo "complete -W \"\$(cat $AMDATADIR/list 2>/dev/null)\" $AMCLI" >> "$completion_file" + if [ -f "${ZDOTDIR:-$HOME}"/.zshrc ] && echo "$SHELL" | grep -q "zsh"; then + cat <<-HEREDOC >> "${ZDOTDIR:-$HOME}"/.zshrc + autoload bashcompinit + bashcompinit + source "$completion_file" + HEREDOC + fi + echo "Shell completion has been enabled!" +fi +sed -i "s#$AMPATH/list#$AMDATADIR/list#g" "$completion_file" 2>/dev/null +# VERSION OF THE INSTALLED APPS +# Filters function _check_version_filters() { - sed "s/$arch//g; s/amd64//g; s/x86-64//g; s/x64//g; s/basic//g; s/standard//g; s/full//g; s/help//g;" | tr '-' '\n' | tr '_' '\n' | grep -vi "appimage\|$arg\|?\|tar." | grep "[0-9]" | head -1 | sed 's/^v//g; s/^\.//g; s/\.$//g;' + sed -E "s/$arch|amd64|x86-64|x64|basic|standard|full|help//g; s/-/\n/g; s/_/\n/g;" |\ + grep -vi "appimage\|$arg\|?\|tar." | grep "[0-9]" | head -1 | sed 's/^v//g; s/^\.//g; s/\.$//g;' } +function _check_version_grep_numbers() { + grep -Eo "([0-9]{1,}\.)+[0-9]{1,}" | head -1 +} + +# Versions function _check_version_if_any_version_reference_is_somewhere() { - APPVERSION=$(grep -i "version=" "$APPSPATH"/"$arg"/* 2>/dev/null | grep -Eo "([0-9]{1,}\.)+[0-9]{1,}" | head -1) + APPVERSION=$(grep -i "version=" "$APPSPATH"/"$arg"/* 2>/dev/null | _check_version_grep_numbers) } function _check_version_if_zsync_file_exists() { - APPVERSION=$(strings -d ./"$arg"/*.zsync | grep -i "$(echo "$arg" | sed 's/-appimage//g')" | grep -Eo "([0-9]{1,}\.)+[0-9]{1,}" | head -1) + APPVERSION=$(strings -d ./"$arg"/*.zsync | grep -i "$(echo "$arg" | sed 's/-appimage//g')" | + _check_version_grep_numbers) if [ -z "$APPVERSION" ]; then APPVERSION=$(date -r ./"$arg"/*.zsync "+%Y.%m.%d") fi @@ -325,7 +341,7 @@ function _check_version_if_version_file_exists() { if grep -q "download$" ./"$arg"/version; then APPVERSION=$(sort "$APPSPATH"/"$arg"/version | tr '/' '\n' | _check_version_filters) elif grep -q "://" ./"$arg"/version; then - APPVERSION=$(sort ./"$arg"/version | tr '/' '\n' | grep -Eo "([0-9]{1,}\.)+[0-9]{1,}" | head -1) + APPVERSION=$(sort ./"$arg"/version | tr '/' '\n' | _check_version_grep_numbers) elif grep -q "/v[0-9]*" ./"$arg"/version; then APPVERSION=$(sort "$APPSPATH"/"$arg"/version | tr '/' '\n' | grep "^v[0-9]" | head -1 | sed 's/^v//g') elif [ "$(sort ./"$arg"/version | wc -w)" = 1 ]; then @@ -340,20 +356,13 @@ function _check_version_if_version_file_exists() { } function _check_version_if_an_updater_exists() { - APPVERSION=$("$APPSPATH"/"$arg"/updater -d "$APPSPATH"/"$arg"/"$arg" 2>/dev/null | grep -i "$arg" | grep -Eo "([0-9]{1,}\.)+[0-9]{1,}" | head -1) + APPVERSION=$("$APPSPATH"/"$arg"/updater -d "$APPSPATH"/"$arg"/"$arg" 2>/dev/null | grep -i "$arg" |\ + _check_version_grep_numbers) if [ -z "$APPVERSION" ]; then _check_version_if_any_version_reference_is_somewhere fi } -function _check_version_if_amcli() { - APPVERSION="$AMVERSION" -} - -function _check_version_if_firefox_webapp() { - APPVERSION="WebApp" -} - function _check_version_if_library() { LIBNAME=$(sort "$APPSPATH"/"$arg"/remove | tr ' ' '\n' | grep "usr/local/lib" | head -1 | sed 's:.*/::') APPVERSION=$(find /usr/local/lib -type f -name "$LIBNAME" -type f | sed 's:.*.so.::' | tail -1) @@ -363,14 +372,11 @@ function _check_version_if_binary_in_place() { APPVERSION=$(date -r ./"$arg"/"$arg" "+%Y.%m.%d") } -function _check_version_if_no_version_found() { - APPVERSION="unknown" -} - function _check_version() { rm -f "$AMCACHEDIR"/version-args cd "$APPSPATH" && - INSTALLED_APPS=$(find . -name 'remove' -printf "%h\n" 2>/dev/null | du -sh -- * 2> /dev/null | sort -rh | sed 's@.* @@') + INSTALLED_APPS=$(find . -name 'remove' -printf "%h\n" 2>/dev/null | du -sh -- * 2> /dev/null |\ + sort -rh | sed 's@.* @@') for arg in $INSTALLED_APPS; do if test -f ./"$arg"/remove 2>/dev/null; then if test -f ./"$arg"/*.zsync 2>/dev/null; then @@ -380,21 +386,21 @@ function _check_version() { elif test -f ./"$arg"/updater 2>/dev/null; then _check_version_if_an_updater_exists elif [ "$arg" = "$AMCLI" ]; then - _check_version_if_amcli + APPVERSION="$AMVERSION" elif grep -qi "version=" ./"$arg"/* 2>/dev/null; then _check_version_if_any_version_reference_is_somewhere elif echo "$arg" | grep -q "ffwa-"; then - _check_version_if_firefox_webapp + APPVERSION="WebApp" elif grep -q "usr/local/lib" "$APPSPATH"/"$arg"/remove 2> /dev/null; then _check_version_if_library else - _check_version_if_no_version_found + APPVERSION="unknown" fi if [ -z "$APPVERSION" ]; then if test -f ./"$arg"/"$arg" 2>/dev/null; then _check_version_if_binary_in_place else - _check_version_if_no_version_found + APPVERSION="unknown" fi fi echo " ◆ $arg | $APPVERSION" >> "$AMCACHEDIR"/version-args @@ -418,189 +424,88 @@ if test -f "$AMCACHEDIR"/version-args; then _check_version_for_auto_updatable_apps 2>/dev/null fi +# This function removes all info and versions from the register function _remove_info_files() { rm -f "$AMCACHEDIR"/files* rm -f "$AMCACHEDIR"/version-args } -################################################################################### -# FUNCTIONS RELATED TO INTERNAL OPTIONS TO ENABLE/DISABLE BASH (AND ZSH) COMPLETION -################################################################################### +################################################################################ +# INTERNAL OPTIONS +################################################################################ -function _use_disable-completion() { - if [ "$(grep -o "$AMCLI" 0<"$COMPLETIONPATH/$COMPLETIONFILE" | head -1)" = "$AMCLI" ]; then - grep -v 'complete -W "$(cat '"$AMPATH"'/list 2>/dev/null)" '"$AMCLI"'' "$COMPLETIONPATH/$COMPLETIONFILE" > "$AMPATH"/$COMPLETIONFILE.backup && - $SUDOCOMMAND mv "$AMPATH"/$COMPLETIONFILE.backup "$COMPLETIONPATH/$COMPLETIONFILE" - echo " Completion disabled! " +# APIKEY +ghapikey_file="$AMDATADIR/ghapikey.txt" +[ -f "$AMPATH/ghapikey.txt" ] && mv "$ghapikey_file" "$ghapikey_file" +# Set header authorization if GitHub API key file exists +[ -f "$ghapikey_file" ] && HeaderAuthWithGITPAT=" --header \"Authorization: token $(<"$ghapikey_file")\" " + +function _use_apikey() { + case $2 in + 'del'|'delete'|'remove') + [ -f "$ghapikey_file" ] || { echo " ✖ No file named $ghapikey_file has been found"; exit 1; } + rm -f "$ghapikey_file" && echo " ✔ $ghapikey_file has been removed" + exit 0 + esac + if [[ "$2" =~ ^(gh[ps]_[a-zA-Z0-9]{36}|github_pat_[a-zA-Z0-9]{22}_[a-zA-Z0-9]{59})$ ]]; then + test_apikey_output_with_wget=$(curl -Ls --header "Authorization: token $2" 'https://api.github.com/repos/ivan-hc/AM/releases' | head -1) + [ -n "$test_apikey_output_with_wget" ] && echo "$2" > "$ghapikey_file" \ + && echo "Validation successful!" || echo "ERROR: This is not a valid key!" else - echo " Completion script is NOT enabled! " + echo "ERROR: Wrong expression, validation failed!" fi } -function _use_enable_completion() { - if [ "$(grep -o "$AMCLI" 0<"$COMPLETIONPATH/$COMPLETIONFILE" | head -1)" = "$AMCLI" ]; then - echo " Completion script is already enabled!" - else - $SUDOCOMMAND mkdir -p "$COMPLETIONPATH" - if [ "$AMCLI" = appman ]; then - if ! test -f "$COMPLETIONPATH/$COMPLETIONFILE"; then - echo '#!/usr/bin/env bash' >> "$COMPLETIONFILE" - fi - else - echo '#!/usr/bin/env bash' >> "$COMPLETIONFILE" - fi - echo 'complete -W "$(cat '"$AMPATH"'/list 2>/dev/null)" '"$AMCLI"'' >> "$COMPLETIONFILE" - chmod a+x "$COMPLETIONFILE" - $SUDOCOMMAND mv "$COMPLETIONFILE" "$COMPLETIONPATH/" 2> /dev/null - echo " Completion has been enabled!" - fi - if [ -f "$HOME/.zshrc" ] || [ -f "$ZDOTDIR/.zshrc" ]; then - if [ -n "$ZDOTDIR" ]; then - ZSHDIR="$ZDOTDIR" - else - ZSHDIR="$HOME" - fi - if grep -q "source $ZSHDIR/$COMPLETIONFILE" "$ZSHDIR/.zshrc"; then - echo "Zsh completion already enabled!" - else - echo '#!/usr/bin/env bash' >> "$ZSHDIR/$COMPLETIONFILE" - echo 'complete -W "$(cat '"$AMPATH"'/list 2>/dev/null)" '"$AMCLI"'' >> "$ZSHDIR/$COMPLETIONFILE" - chmod a+x "$ZSHDIR/$COMPLETIONFILE" - echo -e "\nautoload bashcompinit\nbashcompinit\nsource $ZSHDIR/$COMPLETIONFILE" >> "$ZSHDIR/.zshrc" - fi - fi -} - -# Generate a list of words to use in bash completion -function _generate_options_list() { - rm -f "$AMPATH/options" - cat <<-HEREDOC >> "$AMPATH/options" - about - apikey - backup - clean - downgrade - download - extra - files - install - list - lock - neodb - newrepo - nolibfuse - overwrite - query - remove - sync - template - test - unlock - update - web - --appimages - --apps - --byname - --config - --convert - --debug - --devmode-disable - --devmode-enable - --disable-completion - --enable-completion - --force-latest - --home - --launcher - --less - --pkg - --rollback - --disable-sandbox - --sandbox - --silent - --system - --user - HEREDOC -} - -function _completion_lists() { - _generate_options_list - # Remove existing lists and download new ones - rm -Rf "$AMPATH"/{"$arch"-apps,list,libs-list} && - wget -q "$APPSLISTDB" -P "$AMPATH" && - wget -q "$LIBSLISTDB" -P "$AMPATH" - - # THIRD PARTY APPS - if test -f "$AMPATH/neodb"; then - rm -R -f "$AMCACHEDIR/multirepo-args" - MULTIREPO=$(grep "List=" "$AMPATH/neodb" | grep -E "$arch-apps" | sed 's/List=//g') - for anyrepo in $MULTIREPO; do - if curl --output /dev/null --silent --head --fail "$anyrepo" 1>/dev/null; then - wget -q "$anyrepo" -O - | grep "◆" >> "$AMPATH"/"$arch"-apps +function _update_github_api_key_in_the_updater_files() { + if [ -f "$ghapikey_file" ]; then + ghapikey=$(<"$ghapikey_file") + updater_files=("$APPSPATH"/*/AM-updater) # Assuming AM-updater is one level deeper + for f in "${updater_files[@]}"; do + if [ -f "$f" ] && grep -q "https://api.github.com" "$f"; then + # Check if the file already contains a valid API key + if ! grep -qE "(gh[ps]_[a-zA-Z0-9]{36}|github_pat_[a-zA-Z0-9]{22}_[a-zA-Z0-9]{59})" "$f"; then + # Insert HeaderAuthWithGITPAT before the GitHub API URL + sed -i "s#https://api.github.com#$HeaderAuthWithGITPAT https://api.github.com#g" "$f" + else + # Replace existing API key with the one from ghapikey.txt + sed -i "s#\(gh[ps]_[a-zA-Z0-9]\{36\}\|github_pat_[a-zA-Z0-9]\{22\}_[a-zA-Z0-9]\{59\}\)#$ghapikey#g" "$f" + fi fi done - sort "$AMPATH"/"$arch"-apps | uniq > "$AMPATH"/"$arch"-apps-backup - rm -R -f "$AMPATH"/"$arch"-apps - mv "$AMPATH"/"$arch"-apps-backup "$AMPATH"/"$arch"-apps - fi - - # Extract and append program and library names to the list - for file in "$arch"-apps libs-list; do - awk -v FS="(◆ | : )" '{print $2}' <"$AMPATH"/"$file" >> "$AMPATH"/list - done - - # Append options to the list - cat "$AMPATH"/options >> "$AMPATH"/list + fi } -##################################################################### -# FUNCTIONS RELATED TO INTERNAL OPTIONS TO MADE "AM" WORK AS "APPMAN" -##################################################################### - -# Function for the option "appman" or "--user" that helps "AM" function like "AppMan" +# "APPMAN MODE" FOR "AM" USERS function _appman_mode_enabled_message() { - if [ "$CLI" = am ] 2>/dev/null; then - echo '--------------------------------------------------------------------------' - #echo " \"AppMan Mode\" enabled!" | tr '[:lower:]' '[:upper:]' - echo -e " \"AM\" is running as \"AppMan\", use ${Green}am --system\033[0m to switch it back to \"AM\"" - echo '--------------------------------------------------------------------------' + if [ "$CLI" = am ]; then + echo -e "$DIVIDING_LINE\n \"AM\" is running as \"AppMan\", use ${Green}am --system\033[0m to switch it back to \"AM\"\n$DIVIDING_LINE" fi } function _if_appman_mode_enabled() { - if [ "$CLI" = am ]; then - if test -f "$APPMANCONFIG"/appman-mode; then - _appman_mode_enabled_message - fi - fi + [ "$CLI" = am ] && [ -f "$APPMANCONFIG"/appman-mode ] && _appman_mode_enabled_message } function _use_appman() { _online_check - if [ "$CLI" = appman ] 2>/dev/null; then - echo " This function only works for AM" - exit + if [ "$CLI" = appman ]; then + echo " This function only works for AM" && exit fi if test -f "$APPMANCONFIG"/appman-mode; then - _appman - _appman_mode_enabled_message + _appman; _appman_mode_enabled_message else - mkdir -p "$APPMANCONFIG" - touch "$APPMANCONFIG"/appman-mode - _appman - _appman_mode_enabled_message + mkdir -p "$APPMANCONFIG" && touch "$APPMANCONFIG"/appman-mode + _appman; _appman_mode_enabled_message fi } function _back_to_am() { if test -f "$APPMANCONFIG"/appman-mode; then - rm -f "$APPMANCONFIG"/appman-mode - echo '--------------------------------------------------------------------------' - echo " \"AppMan Mode\" disabled!" | tr '[:lower:]' '[:upper:]' - echo '--------------------------------------------------------------------------' + rm -f "$APPMANCONFIG"/appman-mode && echo -e "$DIVIDING_LINE\n \"AppMan Mode\" disabled! \n$DIVIDING_LINE" fi } -if [ "$AMCLI" = am ] 2>/dev/null; then +if [ "$AMCLI" = am ]; then if test -f "$APPMANCONFIG"/appman-mode; then case "$1" in '--system') @@ -616,38 +521,60 @@ if [ "$AMCLI" = am ] 2>/dev/null; then esac elif [ ! -w /opt/am ]; then read -r -p " \"AM\" is read-only, want to use it in \"AppMan Mode\" (Y,n)? " yn - case $yn in - 'N'|'n') - exit 0;; - 'Y'|'y'|*) - echo '--------------------------------------------------------------------------' - echo " \"AppMan Mode\" enabled!" | tr '[:lower:]' '[:upper:]' - echo '--------------------------------------------------------------------------' - _use_appman 1>/dev/null;; - esac + if echo "$yn" | grep -i '^y' >/dev/null 2>&1; then + exit 0 + else + echo -e "$DIVIDING_LINE\n \"AppMan Mode\" enabled! \n$DIVIDING_LINE" + _use_appman 1>/dev/null + fi fi fi -############################################################## -# FUNCTIONS RELATED TO INTERNAL OPTION TO CLEAN UNNEEDED FILES -############################################################## +# BETA TESTER +function _use_beta_tester() { + if [ "$1" = "--devmode-disable" ]; then + rm -f "$AMDATADIR"/betatester + else + touch "$AMDATADIR"/betatester + _betatester_message_on + fi +} +# CLEAN UNNEEDED FILES function _clean_amcachedir_message() { _clean_amcachedir - echo " ◆ Clear the contents of $AMCACHEDIR" + echo " ✔ Clear the contents of $AMCACHEDIR" } function _clean_all_home_cache_directories_of_appimages() { if test -d "$APPSPATH"/*/*.home/.cache 2> /dev/null; then rm -Rf "$APPSPATH"/*/*.home/.cache/* && - echo " ◆ Clear the contents of all *.home/.cache AppImages directories" + echo " ✔ Clear the contents of all *.home/.cache AppImages directories" fi } function _clean_all_tmp_directories_from_appspath() { if test -d "$APPSPATH"/*/tmp 2> /dev/null; then rm -Rf "$APPSPATH"/*/tmp && - echo ' ◆ Removed all '"$APPSPATH"'/*/tmp directories' + echo ' ✔ Removed all '"$APPSPATH"'/*/tmp directories' + fi +} + +function _clean_determine_removable_launchers() { + if ! test -f "$APPIMAGENAME" 2> /dev/null; then + if ! test -d "$MOUNTPOINTS" 2> /dev/null; then + if echo "$MOUNTPOINTS" | grep -q "/media/"; then + unmounted_poin="/media" + elif echo "$MOUNTPOINTS" | grep -q "/mnt/"; then + unmounted_poin="/mnt" + fi + echo " ✖ ERROR: cannot remove \"$(basename "$var")\"" + echo " related AppImage is located in an unmounted path of $unmounted_poin" + else + rm -f "$var" + rm -f "$HOME"/.local/bin/"$launcher2del"* + cd "$HOME"/.local/bin && find . -xtype l -delete + fi fi } @@ -655,48 +582,39 @@ function _clean_launchers() { if test -d "$DATADIR"/applications/AppImages 2> /dev/null; then for var in "$DATADIR"/applications/AppImages/*.desktop; do APPIMAGENAME=$(grep "Exec=" 0<"$var" 2>/dev/null | head -1 | cut -c 6- | sed 's/\s.*$//') + launcher2del=$(basename -- "$(echo "$APPIMAGENAME" | tr '[:upper:]' '[:lower:]')") MOUNTPOINTS=$(echo "$APPIMAGENAME" | cut -d'/' -f1-4) - if ! test -f "$APPIMAGENAME" 2> /dev/null; then - if ! test -d "$MOUNTPOINTS" 2> /dev/null; then - if echo "$MOUNTPOINTS" | grep -q "/media/"; then - echo "" - echo " 💀ERROR: cannot remove $(basename "$var")" - echo " related AppImage is located in an unmounted path of /media" - echo "" - elif echo "$MOUNTPOINTS" | grep -q "/mnt/"; then - echo "" - echo " 💀ERROR: cannot remove $(basename "$var")" - echo " related AppImage is located in an unmounted path of /mnt" - echo "" - fi - else - rm -f "$var" - rm -f "$HOME"/.local/bin/"$(basename -- "$(echo "$APPIMAGENAME" | tr '[:upper:]' '[:lower:]')")"* - cd "$HOME"/.local/bin && find . -xtype l -delete - fi - fi + _clean_determine_removable_launchers done - echo ' ◆ Removed orphaned launchers produced with the "--launcher" option' + echo ' ✔ Removed orphaned launchers produced with the "--launcher" option' rmdir "$DATADIR"/applications/AppImages fi } function _clean_old_modules() { - if [ "$AMCLI" = am ] 2>/dev/null; then - MODULES=$(grep -Eo '\S*.am\S*' /opt/am/APP-MANAGER | sed 's@.*/@@' | grep -v ";" | grep ".am" | uniq | sort) + if [ "$AMCLI" = am ]; then + MODULES=$(sort /opt/am/APP-MANAGER | tr '"' '\n' | grep "[a-z]\.am$" | uniq) else - MODULES=$(grep -Eo '\S*.am\S*' "$AMCLIPATH" 2>/dev/null | sed 's@.*/@@' | grep -v ";" | grep ".am" | uniq | sort) + MODULES=$(sort "$AMCLIPATH" 2>/dev/null | tr '"' '\n' | grep "[a-z]\.am$" | uniq) fi for m in "$APPSPATH"/"$AMCLI"/modules/*; do if [[ "${MODULES}" != *"$(basename -- "$m")"* ]];then rm -f "$m" 2>/dev/null - echo " ◆ Removed obsolete module named \"$(basename -- "$m")\"" + echo " ✔ Removed obsolete module named \"$(basename -- "$m")\"" fi done } +function _clean_and_remove_old_am_cache_directory() { + rm -f "$AMPATH"/{betatester,*list*,options,.cache/*} + if test -d "$AMPATH/.cache"; then + rmdir "$AMPATH"/.cache + echo " ✔ Removed no more needed $AMPATH/.cache directory" + fi +} + function _use_clean() { - echo -e "\n Cleaning temporary files and folders...\n" && sleep 0.1 && + echo " Cleaning temporary files and folders..." && sleep 0.1 && for i in {100..000}; do echo -ne " $i\r" && sleep 0.0001 done @@ -705,57 +623,302 @@ function _use_clean() { _clean_all_tmp_directories_from_appspath _clean_launchers 2> /dev/null _clean_old_modules - echo -e "\n DONE!\n" + _clean_and_remove_old_am_cache_directory } -######################################################################################### -# FUNCTIONS RELATED TO INTERNAL OPTIONS TO UPDATE "AM"/"APPMAN", THE APPS AND THE MODULES -######################################################################################### - -# Function to update GitHub API key in AM-updater files -function _update_github_api() { - local ghapikey_file="$AMPATH/ghapikey.txt" - if [ -f "$ghapikey_file" ]; then - ghapikey=$(<"$ghapikey_file") - local updater_files=("$APPSPATH"/*/AM-updater) # Assuming AM-updater is one level deeper - for f in "${updater_files[@]}"; do - if [ -f "$f" ] && grep -q "https://api.github.com" "$f"; then - # Check if the file already contains a valid API key - if ! grep -qE "(gh[ps]_[a-zA-Z0-9]{36}|github_pat_[a-zA-Z0-9]{22}_[a-zA-Z0-9]{59})" "$f"; then - # Insert HeaderAuthWithGITPAT before the GitHub API URL - sed -i "s#https://api.github.com#$HeaderAuthWithGITPAT https://api.github.com#g" "$f" - else - # Replace existing API key with the one from ghapikey.txt - sed -i "s#\(gh[ps]_[a-zA-Z0-9]\{36\}\|github_pat_[a-zA-Z0-9]\{22\}_[a-zA-Z0-9]\{59\}\)#$ghapikey#g" "$f" - fi +# FORCE "LATEST" RELEASE FOR APPS INSTALLED FROM GITHUB +function _use_force_latest() { + _online_check + ARGS="$(echo "$@" | cut -f2- -d ' ')" + for arg in $ARGS; do + if ! test -d "$APPSPATH"/"$arg"; then + echo " ERROR: \"$arg\" is not installed, see \"-f\"" + elif ! test -f "$APPSPATH"/"$arg"/AM-updater; then + echo " ERROR: \"$AMCLI\" cannot manage updates for \"$arg\"" + elif ! grep -q "api.github.com" "$APPSPATH"/"$arg"/AM-updater; then + echo " ERROR: \"$arg\" source is not on Github" + elif ! grep -q "/releases | " "$APPSPATH"/"$arg"/AM-updater; then + echo " ERROR: \"$arg\" does not redirect to a generic \"releases\"" + else + sed -i 's#/releases | #/releases/latest | #g' "$APPSPATH"/"$arg"/AM-updater + "$AMCLIPATH" -u "$arg" fi - done - fi + done } -function _list_updatable_apps() { - _check_version - cd "$APPSPATH" && find . -name 'AM-updater' -printf " %h\n" 2>/dev/null | sort -u | xargs -n 1 basename 2>/dev/null > "$AMCACHEDIR"/updatable-args - ARGS=$(cat "$AMCACHEDIR"/updatable-args) - for arg in $ARGS; do - app_version=$(grep -w " ◆ $arg |" "$AMCACHEDIR/version-args" | sed 's:.*| ::') - echo " ◆ $arg $app_version" >> "$AMCACHEDIR"/updatable-args-list - done +#HELP +function _help_body() { + printf " +NAME: ${Green}$AMCLIUPPER\033[0m \ +VERSION: ${Green}$AMVERSION\033[0m + +SYNOPSIS: ${LightBlue}$AMCLI {OPTION}\033[0m + ${LightBlue}$AMCLI {OPTION} {PROGRAM}\033[0m + +DESCRIPTION: A command line utility to install and manage AppImages and other \ +portable programs for GNU/Linux thanks to its AUR-inspired database. + +OPTIONS: + +${Gold}about, -a\033[0m + + ${LightBlue}$AMCLI -a {PROGRAM}\033[0m + +Description: Shows more info about one or more apps. + +${Gold}apikey\033[0m + + ${LightBlue}$AMCLI apikey {Github Token} + ${LightBlue}$AMCLI apikey delete\033[0m + +Description: Accede to github APIs using your personal access tokens. The \ +file named \"ghapikey.txt\" will be saved in $AMDATADIR. Use \"del\" to remove it. + +${Gold}backup, -b\033[0m + + ${LightBlue}$AMCLI -b {PROGRAM}\033[0m + +Description: Create a snapshot of the current version of an installed program. + +${Gold}clean, -c\033[0m + + ${LightBlue}$AMCLI -c\033[0m + +Removes all the unnecessary files and folders. + +${Gold}config, -C, --config\033[0m + + ${LightBlue}$AMCLI -C {PROGRAM}\033[0m + +Description: Set a dedicated \$XDD_CONFIG_HOME for one or more AppImages. + +${Gold}downgrade, --rollback\033[0m + + ${LightBlue}$AMCLI --rollback {PROGRAM}\033[0m + +Description: Download an older or specific app version. + +${Gold}download, -d\033[0m + + ${LightBlue}$AMCLI -d {PROGRAM} + ${LightBlue}$AMCLI -d --convert {PROGRAM}\033[0m + +Description: Download one or more installation scripts to your desktop or \ +convert them to local installers for \"AppMan\" (the latter must be present). + +${Gold}extra, -e\033[0m + + ${LightBlue}$AMCLI -e user/project {APPNAME} + ${LightBlue}$AMCLI -e user/project {APPNAME} {KEYWORD}\033[0m + +Description: Install AppImages from github.com, outside the database. This \ +allows you to install, update and manage them all like the others. Where \ +\"user/project\" can be the whole URL to the github repository, give a name \ +to the program so that it can be used from the command line. Optionally, add \ +an \"univoque\" keyword if multiple AppImages are listed. + +${Gold}files, -f\033[0m + + ${LightBlue}$AMCLI -f + ${LightBlue}$AMCLI -f --byname + ${LightBlue}$AMCLI -f --less\033[0m + +Description: Shows the list of all installed programs, with sizes. By default \ +apps are sorted by size, use \"--byname\" to sort by name. With the option \ +\"--less\" it shows only the number of installed apps. + +${Gold}help -h\033[0m + + ${LightBlue}$AMCLI -h\033[0m + +Description: Prints this message. + +${Gold}home, -H, --home\033[0m + + ${LightBlue}$AMCLI -H {PROGRAM}\033[0m + +Description: Set a dedicated \$HOME directory for one or more AppImages. + +${Gold}install, -i\033[0m + + ${LightBlue}$AMCLI -i {PROGRAM} + ${LightBlue}$AMCLI -i --debug {PROGRAM} + ${LightBlue}$AMCLI -i --force-latest {PROGRAM}\033[0m + +Description: Install one or more programs or libraries from the list. With the \ +\"--debug\" option you can see log messages to debug the script. For more \ +details on \"--force-latest\", see the dedicated option, below. + +${Gold}lock\033[0m + + ${LightBlue}$AMCLI lock {PROGRAM}\033[0m + +Description: Prevent an application being updated, if it has an\"AM-updater\" script. + +${Gold}list, -l\033[0m + + ${LightBlue}$AMCLI -l + ${LightBlue}$AMCLI -l --appimages\033[0m + +Description: Shows the list of all the apps available, or just the AppImages. + +${Gold}newrepo, neodb\033[0m + + ${LightBlue}$AMCLI newrepo add {URL}\\{PATH} + ${LightBlue}$AMCLI newrepo select + ${LightBlue}$AMCLI newrepo on\\off + ${LightBlue}$AMCLI newrepo purge + ${LightBlue}$AMCLI newrepo info\033[0m + +Description: Set a new default repo, use \"add\" to append the path to a local \ +directory or an online URL, then use \"select\" to use it by default, a message \ +will warn you about the usage of this repo instead of the default one. Use \"on\"\ +/\"off\" to enable/disable it. Use \"purge\" to remove all 3rd party repos. Use \ +\"info\" to see the source from where installation scripts and lists are taken. + +${Gold}nolibfuse\033[0m + + ${LightBlue}$AMCLI nolibfuse {PROGRAM}\033[0m + +Description: Convert old AppImages and get rid of \"libfuse2\" dependence. + +${Gold}overwrite, -o\033[0m + + ${LightBlue}$AMCLI -o {PROGRAM}\033[0m + +Description: Overwrite apps with snapshots saved previously (see \"-b\"). + +${Gold}query, -q\033[0m + + ${LightBlue}$AMCLI -q {KEYWORD} + ${LightBlue}$AMCLI -q --appimages {KEYWORD} + ${LightBlue}$AMCLI -q --pkg {PROGRAM1} {PROGRAM2}\033[0m + +Description: Search for keywords in the list of available applications, add \ +the \"--appimages\" option to list only the AppImages or add \"--pkg\" to \ +list multiple programs at once. + +${Gold}remove, -r\033[0m + + ${LightBlue}$AMCLI -r {PROGRAM}\033[0m + +Description: Removes one or more apps, requires confirmation. + +${Gold}-R\033[0m + + ${LightBlue}$AMCLI -R {PROGRAM}\033[0m + +Description: Removes one or more apps without asking. + +${Gold}sandbox, --sandbox\033[0m + + ${LightBlue}$AMCLI sandbox {PROGRAM}\033[0m + +Description: Run an AppImage in a sandbox using Aisap. + +${Gold}sync, -s\033[0m + + ${LightBlue}$AMCLI -s\033[0m + +Description: Updates this script to the latest version hosted. + +${Gold}template, -t\033[0m + + ${LightBlue}$AMCLI -t {PROGRAM}\033[0m + +Description: Generate a custom installation script. + +${Gold}unlock\033[0m + + ${LightBlue}$AMCLI unlock {PROGRAM}\033[0m + +Description: Unlock updates for the selected program (nulls \"lock\"). + +${Gold}update, -u, -U\033[0m + + ${LightBlue}$AMCLI -u + ${LightBlue}$AMCLI -u --apps + ${LightBlue}$AMCLI -u {PROGRAM}\033[0m + +Description: Update everything. Add \"--apps\" to update oly the apps or write \ +only the apps you want to update by adding their names. + +${Gold}version, -v\033[0m + + ${LightBlue}$AMCLI -v\033[0m + +Description: Shows the version. + +${Gold}--devmode-disable\033[0m + + ${LightBlue}$AMCLI --devmode-disable\033[0m + +Description: Undo \"--devmode-enable\" (see below). + +${Gold}--devmode-enable\033[0m + + ${LightBlue}$AMCLI --devmode-enable\033[0m + +Description: Use the development branch (at your own risk). + +${Gold}--disable-sandbox\033[0m + + ${LightBlue}$AMCLI --disable-sandbox {PROGRAM}\033[0m + +Description: Disable the sandbox for the selected app. + +${Gold}--force-latest\033[0m + + ${LightBlue}$AMCLI --force-latest {PROGRAM}\033[0m + +Description: Downgrades an installed app from pre-release to \"latest\". + +${Gold}--launcher\033[0m + + ${LightBlue}$AMCLI --launcher /path/to/\${APPIMAGE}\033[0m + +Description: Drag/drop one or more AppImages in the terminal and embed them in \ +the apps menu and customize a command to use from the CLI. + +${Gold}--system\033[0m + + ${LightBlue}am --system\033[0m + +Description: Switch \"AM\" back to \"AM\" from \"AppMan Mode\" (see \"--user\"). + +${Gold}--user, appman\033[0m + + ${LightBlue}am --user\033[0m + +Description: Made \"AM\" run in \"AppMan Mode\", locally, useful for unprivileged users. This option only works with \"AM\". + +$DIVIDING_LINE + + SITES: + + https://github.com/ivan-hc/AM + + https://portable-linux-apps.github.io + +\n" +} + +function _use_help() { + _if_appman_mode_enabled + _help_body | fold -sw 77 | sed 's/^/ /g' | less -Ir } +# SYNCHRONIZE function _sync_installation_scripts() { - echo "-----------------------------------------------------------------------------" - echo -e " Checking for changes of the installation scripts in the online database..." - rm -R -f "$AMCACHEDIR"/sync-args && echo "" >> "$AMCACHEDIR"/sync-args + echo -e "$DIVIDING_LINE\n Checking for changes of the installation scripts in the online database..." cd "$APPSPATH" && - find . -name 'AM-updater' -printf "%h\n" 2>/dev/null | sort -u | cut -c 3- > "$AMCACHEDIR"/sync-args - ARGS=$(cat "$AMCACHEDIR"/sync-args) + ARGS=$(find . -name 'AM-updater' -printf "%h\n" 2>/dev/null | sort -u | cut -c 3-) for arg in $ARGS; do mkdir -p "$APPSPATH/$arg/.am-installer" if test -f "$APPSPATH/$arg/.am-installer"/*; then scriptname=$(ls "$APPSPATH/$arg/.am-installer/" | head -1) CURRENT=$(cat "$APPSPATH"/"$arg"/.am-installer/"$scriptname") - SOURCE=$(wget -q "$APPSDB"/"$scriptname" -O -) + SOURCE=$(curl -Ls "$APPSDB"/"$scriptname") if [ "$CURRENT" = "$SOURCE" ]; then echo -ne "\r" 2> /dev/null else @@ -772,97 +935,101 @@ function _sync_installation_scripts() { } function _sync_modules() { - echo "-----------------------------------------------------------------------------" - echo -e " Check for updates in modules..." - MODULES=$(curl -Ls $HeaderAuthWithGITPAT https://api.github.com/repos/ivan-hc/AM/contents/modules?ref="$AMBRANCH" | sed 's/[()",{}]/ /g; s/ /\n/g' | grep -o 'https.*raw.*modules.*am$' | grep -v "sync\|update") - for v in $MODULES; do + echo -e "$DIVIDING_LINE\n Check for updates in modules..." + MODULES=$(curl -Ls "$AMREPO/APP-MANAGER" | tr '"' '\n' | grep "[a-z]\.am$") + for module_name in $MODULES; do cd "$AMPATH"/modules || return - MODULENAME=$(echo "$v" | sed 's:.*/::') - if ! test -f ./"$MODULENAME"; then - echo " ◆ Downloading $MODULENAME (not previously installed)..." - wget -q "$v" + if ! test -f ./"$module_name"; then + echo " ◆ Downloading $module_name (not previously installed)..." + curl -Os "$AMREPO/modules/$module_name" 2> /dev/null chmod a+x ./"$MODULENAME" fi - CURRENT=$(cat ./"$MODULENAME" 2>/dev/null) - SOURCE=$(wget -q "$v" -O -) + CURRENT=$(cat ./"$module_name" 2>/dev/null) + SOURCE=$(curl -Ls "$AMREPO/modules/$module_name") if [ "$CURRENT" = "$SOURCE" ]; then echo -ne "\r" 2> /dev/null else - echo " ◆ Updating $MODULENAME..." - mkdir "$AMCACHEDIR"/tmp - cd "$AMCACHEDIR"/tmp || return - wget -q "$v" - cd .. - echo y | mv tmp/*.am "$AMPATH"/modules/ - rmdir tmp + echo " ◆ Updating $module_name..." + curl -Ls "$AMREPO/modules/$module_name" > ./"$module_name" 2> /dev/null fi done _clean_old_modules } function _sync_amcli() { - echo "-----------------------------------------------------------------------------" + echo "$DIVIDING_LINE" _completion_lists - rm -f /opt/am/appman - if [ "$AMCLIPATH" = /opt/am/appman ] 2>/dev/null; then + CURRENT_AM_VERSION="$AMVERSION" + if [ "$AMCLIPATH" = /opt/am/appman ]; then + rm -f /opt/am/appman AMCLIPATH="/opt/am/APP-MANAGER" CURRENT_AM_VERSION=$("$AMCLIPATH" -v) - else - CURRENT_AM_VERSION=$("$AMCLIPATH" -v 2>/dev/null) fi - echo -ne '\n ◆ SYNCHRONIZING "'"$AMCLIUPPER"'" VERSION '"$CURRENT_AM_VERSION"'...\r'; sleep 1 - _clean_amcachedir 1>/dev/null; cd "$AMCACHEDIR" || return - if [ "$AMCLI" = am ] 2>/dev/null; then - wget -q "$AMREPO"/APP-MANAGER && chmod a+x ./APP-MANAGER + echo -ne "\n ◆ SYNCHRONIZING \"$AMCLIUPPER\" VERSION \"$CURRENT_AM_VERSION\"...\r" && sleep 0.25 + _clean_amcachedir 1>/dev/null + cd "$AMCACHEDIR" || return + if [ "$AMCLI" = am ]; then + curl -Ls "$AMREPO"/APP-MANAGER > ./APP-MANAGER && chmod a+x ./APP-MANAGER cd .. echo y | mv "$AMCACHEDIR"/APP-MANAGER /opt/am/APP-MANAGER else - wget -q "$AMREPO"/APP-MANAGER -O appman && chmod a+x ./"$AMCLI" + curl -Ls "$AMREPO"/APP-MANAGER > ./appman && chmod a+x ./"$AMCLI" cd .. echo y | mv "$AMCACHEDIR"/"$AMCLI" "$AMCLIPATH" 2>/dev/null fi - if [ ! "$CURRENT_AM_VERSION" = "$("$AMCLIPATH" -v 2>/dev/null)" ] ; then - echo -ne ' A new release of "'"$AMCLIUPPER"'" is available, please wait...\r' - echo " ◆ \"$AMCLIUPPER\" IS NOW UPDATED TO THE BRAND NEW \"$("$AMCLIPATH" -v)\" VERSION!" - echo "" - echo " Replacement of version \"$CURRENT_AM_VERSION\" currently in use, COMPLETED!" - echo "" - echo " See https://github.com/ivan-hc/AM/commits/main" - echo "" + NEW_AM_VERSION=$("$AMCLIPATH" -v) + if [ ! "$CURRENT_AM_VERSION" = "$NEW_AM_VERSION" ]; then + echo -ne " A new release of \"$AMCLIUPPER\" is available, please wait...\r" + echo " ◆ \"$AMCLIUPPER\" IS NOW UPDATED TO THE BRAND NEW \"$NEW_AM_VERSION\" VERSION!" + echo -e "\n Replacement of version \"$CURRENT_AM_VERSION\" currently in use, COMPLETED!" + echo -e "\n See https://github.com/ivan-hc/AM/commits/main\n" else echo " ◆ \"$AMCLIUPPER\" IS ALREADY UPDATED, CURRENT VERSION \"$CURRENT_AM_VERSION\"" - echo "" - echo " See https://github.com/ivan-hc/AM/commits/$AMBRANCH" - echo "" + echo -e "\n See https://github.com/ivan-hc/AM/commits/$AMBRANCH\n" fi } function _use_sync() { - if [[ "$AMREPO" = *://* ]]; then - _sync_installation_scripts + _online_check + _betatester_message_on + _sync_installation_scripts + if [ "$(realpath $0)" != "/usr/bin/am" ]; then _sync_modules _sync_amcli fi } +# UPDATE +function _list_updatable_apps() { + _check_version + cd "$APPSPATH" && + ARGS=$(find . -name 'AM-updater' -printf " %h\n" 2>/dev/null | sort -u | xargs -n 1 basename 2>/dev/null) + for arg in $ARGS; do + app_version=$(grep -w " ◆ $arg |" "$AMCACHEDIR/version-args" | sed 's:.*| ::') + echo " ◆ $arg $app_version" >> "$AMCACHEDIR"/updatable-args-list + done +} + function _update_all_apps() { for f in "$APPSPATH"/*/; do cd "$f" 2>/dev/null && if test -f ./AM-updater; then + appname=$(printf '%s\n' "${PWD##*/}") + APPNAME=$(echo "$appname" | tr '[:lower:]' '[:upper:]') if [ -w ./AM-updater ]; then - APPNAME=$(printf '%s\n' "${PWD##*/}") - start=$(date +%s) && sh -x ./AM-updater > /dev/null 2>&1 | echo -ne ' Updating "'"$APPNAME"'"...\r' && end=$(date +%s) && - echo " ◆ $(echo "$APPNAME" | tr '[:lower:]' '[:upper:]') is updated, $((end - start)) seconds elapsed!" & + start=$(date +%s) && + sh -x ./AM-updater > /dev/null 2>&1 | echo -ne ' Updating "'"$APPNAME"'"...\r' && + end=$(date +%s) && + echo " ◆ $APPNAME is updated, $((end - start)) seconds elapsed!" & else - APPNAME=$(printf '%s\n' "${PWD##*/}") - echo " - $(echo "$APPNAME" | tr '[:lower:]' '[:upper:]') is read-only, cannot update it!" + echo " ✖ $APPNAME is read-only, cannot update it!" fi else echo "" > /dev/null 2>&1 fi done wait - echo '-----------------------------------------------------------------------------' + echo "$DIVIDING_LINE" if test -f "$AMCACHEDIR"/updatable-args-list; then mv "$AMCACHEDIR"/updatable-args-list "$AMCACHEDIR"/updatable-args-list-old _list_updatable_apps @@ -878,209 +1045,140 @@ function _update_all_apps() { else echo ' No apps to update here!' fi - rm -R -f "$APPSPATH/*/tmp" + rm -Rf "$APPSPATH/*/tmp" } function _use_update() { - _update_github_api - while [ -n "$1" ]; do - case $2 in - ''|'--apps') - _clean_amcachedir - _list_updatable_apps - echo '-----------------------------------------------------------------------------' - echo " \"$AMCLIUPPER\" CAN MANAGE UPDATES FOR THE FOLLOWING PROGRAMS:" - echo "" - if test -f "$AMCACHEDIR/updatable-args-list"; then - cat "$AMCACHEDIR/updatable-args-list" - else - echo " None" - fi - echo "" - echo ' All self-updatable programs are excluded' - echo '-----------------------------------------------------------------------------' - echo ' >> START OF ALL PROCESSES <<' - echo '-----------------------------------------------------------------------------' - - _update_all_apps - - if [ -z "$2" ]; then - echo "-----------------------------------------------------------------------------" - _use_sync - fi - echo '-----------------------------------------------------------------------------' - echo ' >> END OF ALL PROCESSES << ' - echo '-----------------------------------------------------------------------------' - sleep 0.2 - exit;; - *) - if test -f "$APPSPATH"/"$2"/AM-updater; then - if [ -w "$APPSPATH"/"$2"/AM-updater ]; then - start=$(date +%s); "$APPSPATH"/"$2"/AM-updater > /dev/null 2>&1 | echo -ne " UPDATING $(echo "$2" | tr '[:lower:]' '[:upper:]')\r"; end=$(date +%s) - echo -e " ◆ $(echo "$2" | tr '[:lower:]' '[:upper:]') is updated, $((end - start)) seconds elapsed!" + _online_check + _update_github_api_key_in_the_updater_files + case $2 in + ''|'--apps') + _clean_amcachedir + _list_updatable_apps + echo -e "$DIVIDING_LINE\n \"$AMCLIUPPER\" CAN MANAGE UPDATES FOR THE FOLLOWING PROGRAMS:\n" + [ -f "$AMCACHEDIR/updatable-args-list" ] && cat "$AMCACHEDIR/updatable-args-list" || echo " None" + echo -e "\n All self-updatable programs are excluded" + echo -e "$DIVIDING_LINE\n >> START OF ALL PROCESSES <<\n$DIVIDING_LINE" + _update_all_apps + [ -z "$2" ] && echo "$DIVIDING_LINE" && _use_sync + echo -e "$DIVIDING_LINE\n >> END OF ALL PROCESSES << \n$DIVIDING_LINE" + sleep 0.2 + exit + ;; + *) + ARGS="$(echo "$@" | cut -f2- -d ' ')" + for arg in $ARGS; do + arg_upper=$(echo "$arg" | tr '[:lower:]' '[:upper:]') + if test -f "$APPSPATH"/"$arg"/AM-updater; then + if [ -w "$APPSPATH"/"$arg"/AM-updater ]; then + start=$(date +%s) + "$APPSPATH"/"$arg"/AM-updater > /dev/null 2>&1 | echo -ne " UPDATING $arg_upper\r" + end=$(date +%s) + echo " ◆ $arg_upper is updated, $((end - start)) seconds elapsed!" _clean_amcachedir _list_updatable_apps - break else - echo " - $(echo "$2" | tr '[:lower:]' '[:upper:]') is read-only, cannot update it!" - exit + echo " - $arg_upper is read-only, cannot update it!" fi else - echo " \"$AMCLIUPPER\" CANNOT MANAGE UPDATES FOR \"$(echo "$2" | tr '[:lower:]' '[:upper:]')\"" - UPDATERS=$(cd "$APPSPATH"/"$2" 2>/dev/null && find . -name "*update*" -print 2>/dev/null) - if [ -n "$UPDATERS" ]; then - echo ' This program probably includes its own update system!' - fi - exit - fi;; - esac - done - shift -} - -function _use_force_latest() { - case $2 in - '') - echo " USAGE: $AMCLI $1 [ARGUMENT]"; exit - ;; - *) - if ! test -d "$APPSPATH"/"$2"; then - echo " ERROR: \"$2\" is not installed, see \"-f\"" - elif ! test -f "$APPSPATH"/"$2"/AM-updater; then - echo " ERROR: \"$AMCLI\" cannot manage updates for \"$2\"" - elif ! grep -q "api.github.com" "$APPSPATH"/"$2"/AM-updater; then - echo " ERROR: \"$2\" source is not on Github" - elif ! grep -q "/releases | " "$APPSPATH"/"$2"/AM-updater; then - echo " ERROR: \"$2\" does not redirect to a generic \"releases\"" - else - sed -i 's#/releases | #/releases/latest | #g' "$APPSPATH"/"$2"/AM-updater - "$AMCLIPATH" -u "$2" - fi + UPDATERS=$(cd "$APPSPATH"/"$arg" 2>/dev/null && find . -name "*update*" -print 2>/dev/null) + [ -n "$UPDATERS" ] && arg_autoupdatable=", it may have its update system" + echo " ✖ Cannot manage updates for \"$arg_upper\"$arg_autoupdatable" + fi + done ;; esac } -############################################# -# FUNCTION TO HANDLE ALL THE EXTERNAL MODULES -############################################# +################################################################################ +# USAGE +################################################################################ +# HANDLE ALL THE EXTERNAL MODULES function _use_module() { # Test if module exists - if ! test -f "$AMPATH/modules/$MODULE"; then + if [ ! -f "$AMPATH/modules/$MODULE" ]; then _online_check - if curl --output /dev/null --silent --head --fail "$AMREPO/modules/$MODULE"; then - wget -q "$AMREPO/modules/$MODULE" -O "$AMPATH/modules/$MODULE" - chmod a+x "$AMPATH/modules/$MODULE" - else - echo " Module not found, run \"$AMCLI -s\" to update \"$AMCLIUPPER\"" && exit 1 + if ! wget -q "$AMREPO/modules/$MODULE" -O "$AMPATH/modules/$MODULE"; then + echo " Module not found, run \"$AMCLI -s\" to update \"$AMCLIUPPER\"" + exit 1 fi + chmod a+x "$AMPATH/modules/$MODULE" fi # Source module source "$AMPATH/modules/$MODULE" "$@" } -_am_security_check -_am_databases_check "$@" +[ -z "$1" ] && echo " USAGE: $AMCLI [OPTION]" && echo " $AMCLI [OPTION] [ARGUMENT]" && + echo "" && echo " Run the \"$AMCLI -h\" command to find out more" && exit 1 case "$1" in - '') - echo -e "\n USAGE: '$AMCLI [option]'\n '$AMCLI [option] [argument]'\n\n Run the '$AMCLI -h' command to find out more\n" - ;; - # OPTIONS BASED ON EXTERNAL MODULES - '-a'|'about'|\ - '-l'|'list'|\ - '-q'|'query') + 'about'|'-a'|\ + 'files'|'-f'|\ + 'list'|'-l'|\ + 'query'|'-q') MODULE="database.am" _use_module "$@" ;; - '-b'|'backup'|\ - '-o'|'overwrite'|\ - '-R'|'-r'|'remove'|\ - '--rollback'|'downgrade'|\ + 'backup'|'-b'|\ + 'downgrade'|'--rollback'|\ + 'launcher'|'--launcher'|\ 'lock'|'unlock'|\ - 'nolibfuse') + 'nolibfuse'|\ + 'overwrite'|'-o'|\ + 'remove'|'-R'|'-r') MODULE="management.am" _use_module "$@" ;; - '-d'|'download') - MODULE="download.am" - _online_check - _use_module "$@" - ;; - '-f'|'files') - MODULE="files.am" - _use_module "$@" - _betatester_message_on - ;; - '-h'|'help') - MODULE="help.am" - _if_appman_mode_enabled - _use_module "$@" - ;; - '-C'|'--config'|\ - '-H'|'--home'|\ - '--sandbox'|\ + 'config'|'-C'|'--config'|\ + 'home'|'-H'|'--home'|\ + 'sandbox'|'--sandbox'|\ '--disable-sandbox') MODULE="sandboxes.am" _use_module "$@" ;; - '-i'|'install'|\ - '-e'|'extra') + 'download'|'-d'|\ + 'extra'|'-e'|\ + 'install'|'-i') MODULE="install.am" _online_check _if_appman_mode_enabled _use_module "$@" ;; - '-t'|'template') + 'template'|'-t') MODULE="template.am" _online_check _use_module "$@" ;; - '--launcher') - MODULE="launcher.am" - _use_module "$@" - ;; - 'neodb'|\ - 'apikey'|\ - 'newrepo') - MODULE="devtools.am" - _online_check - _use_module "$@" - ;; # INBUILT OPTIONS - '--devmode-disable') - _use_betatester_off - ;; - '--devmode-enable') - _use_betatester_on - _betatester_message_on - ;; - '--disable-completion') - _use_disable-completion - ;; - '--enable-completion') - _use_enable_completion + '--devmode-disable'|'--devmode-enable') + _use_beta_tester "$@" ;; '--force-latest') - _online_check _use_force_latest "$@" ;; '--system') _back_to_am ;; - '--user'|'appman') + 'apikey') + _use_apikey "$@" + ;; + 'appman'|'--user') _use_appman ;; 'clean'|'-c') _use_clean ;; + 'help'|'-h') + _use_help + ;; + 'newrepo'|'neodb') + _use_newrepo "$@" + ;; 'sync'|'-s') - _online_check - _betatester_message_on _use_sync ;; 'update'|'-u'|'-U') - _online_check _use_update "$@" ;; 'version'|'-v'|'--version') diff --git a/INSTALL b/INSTALL index 80bfb7fce..381ed1962 100755 --- a/INSTALL +++ b/INSTALL @@ -26,12 +26,12 @@ RED='\033[0;31m'; LightBlue='\033[1;34m'; Green='\033[0;32m' # INSTALL "AM" _prepare_am_directory() { # CREATE AND ENTER THE MAIN DIRECTORY FOR "AM" - mkdir -p /opt/am/.cache /opt/am/modules /usr/local/bin && cd /opt/am || exit 1 + mkdir -p /opt/am/modules /usr/local/bin && cd /opt/am || exit 1 # CREATE THE SCRIPT NEEDED TO UNINSTALL "AM" printf '#!/bin/sh\n\nset -e\n' > /opt/am/remove printf '\n%s\n' 'if [ "$(id -u)" -ne 0 ]; then echo "Permission denied"; exit 1; fi' >> /opt/am/remove - printf '%s\n' 'rm -f /usr/local/bin/am /etc/bash_completion.d/am-completion.sh' >> /opt/am/remove + printf '%s\n' 'rm -f /usr/local/bin/am' >> /opt/am/remove printf '%s\n' 'rm -R -f /opt/am' >> /opt/am/remove chmod a+x /opt/am/remove || exit 1 @@ -39,21 +39,17 @@ _prepare_am_directory() { wget -q https://raw.githubusercontent.com/ivan-hc/AM/main/APP-MANAGER chmod a+x /opt/am/APP-MANAGER ln -s /opt/am/APP-MANAGER /usr/local/bin/am 2> /dev/null || printf "${RED}WARNING: Couldn't link am to \"/usr/local/bin/am\"!\033[0m\n" - - # DOWNLOAD THE LIST OF THE AVAILABLE PROGRAMS - wget -q "https://raw.githubusercontent.com/ivan-hc/AM/main/programs/$arch-apps" || exit 1 } _download_am_modules() { # DOWNLOAD MODULES cd /opt/am/modules || exit - MODULES=$(curl -Ls https://api.github.com/repos/ivan-hc/AM/contents/modules | sed 's/[()",{}]/ /g; s/ /\n/g' | grep -o 'https.*raw.*modules.*am$' | grep -v "sync\|update") - for v in $MODULES; do - MODULENAME=$(echo "$v" | sed 's:.*/::') - if ! test -f ./"$MODULENAME"; then - echo " ◆ Downloading $MODULENAME..." - wget -q "$v" - chmod a+x ./"$MODULENAME" + MODULES=$(curl -Ls https://raw.githubusercontent.com/ivan-hc/AM/main/APP-MANAGER | tr '"' '\n' | grep "[a-z]\.am$") + for module_name in $MODULES; do + if ! test -f ./"$module_name"; then + echo " ◆ Downloading $module_name..." + wget -q "https://raw.githubusercontent.com/ivan-hc/AM/main/modules/$module_name" + chmod a+x ./"$module_name" fi done cd .. @@ -62,20 +58,6 @@ _download_am_modules() { chown -R $currentuser /opt/am 2> /dev/null } -_enable_bash_completion() { - # ADD THE BASH COMPLETION SCRIPT - echo '#!/usr/bin/env bash' > /opt/am/am-completion.sh - echo 'complete -W "$(cat /opt/am/list 2>/dev/null)" am' >> /opt/am/am-completion.sh - chmod a+x /opt/am/am-completion.sh - - if test -f /etc/bash_completion.d; then - mv /opt/am/am-completion.sh /etc/bash_completion.d/ - else - mkdir -p /etc/bash_completion.d - mv /opt/am/am-completion.sh /etc/bash_completion.d/ - fi -} - echo '--------------------------------------------------------------------------' printf " ${Green}Installing \"AM\" in /opt/am\033[0m\n" _prepare_am_directory @@ -83,9 +65,6 @@ echo '-------------------------------------------------------------------------- printf " ${Green}Installing modules\033[0m\n" _download_am_modules echo '--------------------------------------------------------------------------' -printf " ${Green}Enable bash completion\033[0m\n" -_enable_bash_completion -echo '--------------------------------------------------------------------------' printf " ${Green}\"AM\" has been successfully installed!\033[0m\n" printf " Please, run \"${LightBlue}am -h\033[0m\" to see the list of the options.\n" echo '--------------------------------------------------------------------------' diff --git a/README.md b/README.md index b310330b4..af8dba296 100644 --- a/README.md +++ b/README.md @@ -102,7 +102,7 @@ Both can be updated using "[Topgrade](https://github.com/topgrade-rs/topgrade)". ### About "sudo" usage - "AppMan" can request the root password only in the very rare case in which you want to install a library; -- "AM" requires the root password only to install, remove apps, enable a sandbox for an AppImage, or enable/disable bash completion. +- "AM" requires the root password only to install, remove apps, enable a sandbox for an AppImage. All options cannot be executed with "`sudo`"/"`doas`". @@ -331,10 +331,11 @@ sudo ./INSTALL In both cases, the "INSTALL" script will create: - the script "/opt/am/APP-MANAGER" - the script "/opt/am/remove" (to remove "AM" using the command `am -R am`) -- the directory "/opt/am/.cache" (where all processes will been executed) - the directory "/opt/am/modules" (containing the .am modules for the non-core options) - the symlink "/usr/local/bin/am" for "/opt/am/APP-MANAGER" +all processes will been executed in $HOME/.cache/am, while application lists, keywords to use in bash/zsh completion and other files (for third party repos, betatesting, etcetera...) will be saved and updated in $HOME/.local/share/AM to be shared with "AppMan", if installed or you use "AM" in "AppMan Mode". + NOTE, if you don't feel comfortable having to always use root permissions, the installation method for "AppMan" is totally different. If you are interested, go [to the next paragraph](#how-to-install-appman), else [Back to "Main Index"](#main-index) or jump to "[Usage (all the available options)](#usage)". ------------------------------------------------------------------------ @@ -361,10 +362,11 @@ wget https://raw.githubusercontent.com/ivan-hc/AM/main/APP-MANAGER -O appman && ### Structure of the "AppMan" installation Unlike "AM" which needs to be placed in specific locations, "AppMan" is portable. The modules and directories will be placed in the directory you chose: - the script "appman" is wherever you want -- the directory "$HOME/path/to/your/custom/directory/.cache" (where all processes will been executed) - the directory "$HOME/path/to/your/custom/directory/modules" (containing the .am modules for the non-core options) - the configuration file "$HOME/.config/appman/appman-config" (the only fixed directory) +all processes will been executed in $HOME/.cache/appman, while application lists, keywords to use in bash/zsh completion and other files (for third party repos, betatesting, etcetera...) will be saved and updated in $HOME/.local/share/AM to be shared with "AM", if installed. + ------------------------------------------------------------------------ | [Back to "Main Index"](#main-index) | @@ -406,365 +408,222 @@ See also "[How to update or remove apps manually](#how-to-update-or-remove-apps- ___________________________________________________________________________ - ## OPTIONS - - (standard, for both "AM" and "APPMAN") - ___________________________________________________________________________ - ___________________________________________________________________________ - - `-a`, `about` - - SYNOPSIS: - - `-a {PROGRAM}` - - DESCRIPTION: Shows more info about one or more apps, all the pages are downloaded from https://portable-linux-apps.github.io - ___________________________________________________________________________ - - `-b`, `backup` - - SYNOPSIS: - - `-b {PROGRAM}` - - DESCRIPTION: Save the current version of one or more apps, each snapshot is stored into a dedicated directory, under $HOME/.am-snapshots/$PROGRAM - - To restore the snapshots see the "-o" option. - ___________________________________________________________________________ - - `-c`, `clean` - - SYNOPSIS: - - `-c` - - DESCRIPTION: Removes all the unnecessary files and folders. - __________________________________________________________________________ - - `-C`, `--config` - - SYNOPSIS: +## OPTIONS: - `-C {PROGRAM}` - - DESCRIPTION: Set a dedicated $XDD_CONFIG_HOME for one or more AppImages. - __________________________________________________________________________ - - `-d`, `download` - - SYNOPSIS: - - `-d {PROGRAM}` - - `-d --convert {PROGRAM}` - - DESCRIPTION: Download one or more installation scripts to your desktop. With the option "--convert" its converted to a standalone local installer, but AM requires AppMan to be installed to add custom directory settings. - ___________________________________________________________________________ - - `-e`, `extra` - - SYNOPSIS: - - `-e {USER}/{PROJECT} {PROGRAM}` - - `-e {USER}/{PROJECT} {PROGRAM} {KEYWORD}` - - DESCRIPTION: Install AppImages from github.com, outside the database. This allows you to install, update and manage them all like the others. Where "user/project" can be the whole URL to the github repository, give a name to the program so that it can be used from the command line. Optionally, add an "univoque" keyword if multiple AppImages are listed. - ___________________________________________________________________________ - - `-f`, `files` - - SYNOPSIS: - - `-f` - - `-f --byname` - - `-f --less` - - DESCRIPTION: Shows the list of all installed programs, with sizes. By default apps are sorted by size, use "--byname" to sort by name. With the option "--less" it shows only the number of installed apps. - ___________________________________________________________________________ - - `-h`, `help` - - SYNOPSIS: - - `-h` - - DESCRIPTION: Prints this message. - ___________________________________________________________________________ - - `-H`, `--home` - - SYNOPSIS: - - `-H {PROGRAM}` - - DESCRIPTION: Set a dedicated $HOME directory for one or more AppImages. - ___________________________________________________________________________ - - `-i`, `install` - - SYNOPSIS: - - `-i {PROGRAM}` - - `-i --debug {PROGRAM}` - - `-i --force-latest {PROGRAM}` - - DESCRIPTION: Install one or more programs or libraries from the list. With the "--debug" option you can see log messages to debug the script. For more details on "--force-latest", see the dedicated option, below. - ___________________________________________________________________________ - - `-l`, `list` - - SYNOPSIS: - - `-l` - - `-l --appimages` +### `about, -a` - DESCRIPTION: Shows the list of all the apps available in the repository. Add the "--appimages" option to list only the AppImages. - ___________________________________________________________________________ + -a {PROGRAM} - `-o`, `overwrite` +Description: Shows more info about one or more apps. - SYNOPSIS: +### `apikey` - `-o {PROGRAM}` + apikey {Github Token} + apikey delete - DESCRIPTION: Overwrite the existing version of the app with a snapshot saved previously (see the option "-b", above). - ___________________________________________________________________________ +Description: Accede to github APIs using your personal access tokens. The file named "ghapikey.txt" will be saved in ~/.local/share/AM. Use "del" to remove it. - `-q`, `query` +### `backup, -b` - SYNOPSIS: + -b {PROGRAM} - `-q {KEYWORD}` +Description: Create a snapshot of the current version of an installed program. - `-q --appimages {KEYWORD}` +### `clean, -c` - `-q --pkg {PROGRAM1} {PROGRAM2}` + -c - DESCRIPTION: Can be used to search for keywords and terms in the list of available applications packages to display matches. This can be useful if you are looking for applications having a specific feature. Add the "--appimages" option to list only the AppImages. Add the suboption "--pkg" to search only the names of one or more apps. - ___________________________________________________________________________ +Removes all the unnecessary files and folders. - `-r`, `remove` +### `config, -C, --config` - SYNOPSIS: + -C {PROGRAM} - `-r {PROGRAM}` +Description: Set a dedicated $XDG_CONFIG_HOME for one or more AppImages. - DESCRIPTION: Removes one or more apps, requires confirmation. - ___________________________________________________________________________ +### `downgrade, --rollback` - `-R` + --rollback {PROGRAM} - SYNOPSIS: +Description: Download an older or specific app version. - `-R {PROGRAM}` +### `download, -d` - DESCRIPTION: Removes one or more apps without asking. - ___________________________________________________________________________ + -d {PROGRAM} + -d --convert {PROGRAM} - `-s`, `sync` +Description: Download one or more installation scripts to your desktop or convert them to local installers for "AppMan" (the latter must be present). - SYNOPSIS: +### `extra, -e` - `-s` + -e user/project {APPNAME} + -e user/project {APPNAME} {KEYWORD} - DESCRIPTION: Updates this script to the latest version hosted. - ___________________________________________________________________________ +Description: Install AppImages from github.com, outside the database. This allows you to install, update and manage them all like the others. Where "user/project" can be the whole URL to the github repository, give a name to the program so that it can be used from the command line. Optionally, add an "univoque" keyword if multiple AppImages are listed. - `-t`, `template` +### `files, -f` - SYNOPSIS: + -f + -f --byname + -f --less - `-t {PROGRAM}` +Description: Shows the list of all installed programs, with sizes. By default apps are sorted by size, use "--byname" to sort by name. With the option "--less" it shows only the number of installed apps. - DESCRIPTION: This option allows you to generate a custom script from a list of different templates that may be vary according to the kind of app you want to upload to the "AM" repo, and the source where it is available. You can install it using the `am test /path/to/your-script` command. - ___________________________________________________________________________ +### `help -h` - `-u`, `-U`, `update` + -h - SYNOPSIS: +Description: Prints this message. - `-u` +### `home, -H, --home` - `-u apps` + -H {PROGRAM} - `-u {PROGRAM}` +Description: Set a dedicated $HOME directory for one or more AppImages. - DESCRIPTION: Update all the apps (and "am" itself) or just one. If you add the "`--apps`" suboption you only update apps. - ___________________________________________________________________________ +### `install, -i` - `-v`, `version` + -i {PROGRAM} + -i --debug {PROGRAM} + -i --force-latest {PROGRAM} - SYNOPSIS: +Description: Install one or more programs or libraries from the list. With the "--debug" option you can see log messages to debug the script. For more details on "--force-latest", see the dedicated option, below. - `-v` +### `lock` - DESCRIPTION: Shows the version. - ___________________________________________________________________________ + lock {PROGRAM} - `--disable-completion` +Description: Prevent an application being updated, if it has an"AM-updater" script. - SYNOPSIS: +### `list, -l` - `--disable-completion` + -l + -l --appimages - DESCRIPTION: Disable bash-completion. - ___________________________________________________________________________ +Description: Shows the list of all the apps available, or just the AppImages. - `--disable-sandbox` +### `newrepo, neodb` - SYNOPSIS: + newrepo add {URL}\{PATH} + newrepo select + newrepo on\off + newrepo purge + newrepo info - `--disable-sandbox {PROGRAM}` +Description: Set a new default repo, use "add" to append the path to a local directory or an online URL, then use "select" to use it by default, a message will warn you about the usage of this repo instead of the default one. Use "on"/"off" to enable/disable it. Use "purge" to remove all 3rd party repos. Use "info" to see the source from where installation scripts and lists are taken. - DESCRIPTION: Disable the sandbox for the selected app. - ___________________________________________________________________________ +### `nolibfuse` - `--enable-completion` + nolibfuse {PROGRAM} - SYNOPSIS: +Description: Convert old AppImages and get rid of "libfuse2" dependence. - `--enable-completion` +### `overwrite, -o` - DESCRIPTION: Enable bash-completion to complete a keyword with the "TAB" key, using the names of all installable applications available. - ___________________________________________________________________________ + -o {PROGRAM} - `--force-latest` +Description: Overwrite apps with snapshots saved previously (see "-b"). - SYNOPSIS: +### `query, -q` - `--force-latest {PROGRAM}` + -q {KEYWORD} + -q --appimages {KEYWORD} + -q --pkg {PROGRAM1} {PROGRAM2} - `-i --force-latest {PROGRAM}` +Description: Search for keywords in the list of available applications, add the "--appimages" option to list only the AppImages or add "--pkg" to list multiple programs at once. - DESCRIPTION: Downgrades an installed app from pre-release to "latest". This can be used with "-i" to force the installation of apps from "latest". Many scripts point to "releases" to find the latest build for GNU/Linux if the developer has not uploaded one in "latest". - ___________________________________________________________________________ +### `remove, -r` - `--launcher` + -r {PROGRAM} - SYNOPSIS: +Description: Removes one or more apps, requires confirmation. - `--launcher /path/to/${APPIMAGE}` +### `-R` - DESCRIPTION: Embed one or more local AppImages in the applications menu. I suggest dragging the files into the terminal to get the desired effect. Launchers are located in ~/.local/share/applications/AppImages by default. - ___________________________________________________________________________ + -R {PROGRAM} - `--rollback`, `downgrade` +Description: Removes one or more apps without asking. - SYNOPSIS: +### `sandbox, --sandbox` - `--rollback {PROGRAM}` + sandbox {PROGRAM} - DESCRIPTION: Download an older or specific version of the software you are interested in (only works with Github). - ___________________________________________________________________________ +Description: Run an AppImage in a sandbox using Aisap. - `--sandbox` +### `sync, -s` - SYNOPSIS: + -s - `--sandbox {PROGRAM}` +Description: Updates this script to the latest version hosted. - DESCRIPTION: Run an AppImage in a sandbox using Aisap. - ___________________________________________________________________________ +### `template, -t` - `apikey` + -t {PROGRAM} - SYNOPSIS: +Description: Generate a custom installation script. - `apikey {Github Token}` +### `unlock` - `apikey delete` + unlock {PROGRAM} - DESCRIPTION: Get unlimited access to https://api.github.com using your personal access tokens. The configuration file named "ghapikey.txt" will be saved in '$AMPATH' . Use the command "'$AMCLI' apikey delete/del/remove" to remove the file. - __________________________________________________________________________ +Description: Unlock updates for the selected program (nulls "lock"). - `dev`, `devmode` +### `update, -u, -U` - SYNOPSIS: + -u + -u --apps + -u {PROGRAM} - `dev off` +Description: Update everything. Add "--apps" to update oly the apps or write only the apps you want to update by adding their names. - `dev on` +### `version, -v` - DESCRIPTION: View the installer output during installation, use "on". It can be disabled with "off" or with the "`-s`" and "`-u`" options. - __________________________________________________________________________ - - `lock` - - SYNOPSIS: - - `lock {PROGRAM}` + -v - DESCRIPTION: Lock the selected app to the current version installed, this only works if exists a dedicated "AM-updater" installed with the app. - __________________________________________________________________________ - - `neodb` +Description: Shows the version. - SYNOPSIS: +### `--devmode-disable` - `neodb` + --devmode-disable - `neodb --silent` +Description: Undo "--devmode-enable" (see below). - DESCRIPTION: Add third-party repos to extend the existing database. Use "--silent" to hide messages about third-party repos in use. - __________________________________________________________________________ +### `--devmode-enable` - `newrepo` + --devmode-enable - SYNOPSIS: +Description: Use the development branch (at your own risk). - `newrepo {URL}` +### `--disable-sandbox` - `newrepo off` + --disable-sandbox {PROGRAM} - `newrepo on` +Description: Disable the sandbox for the selected app. - DESCRIPTION: Set the variable "$AMREPO" to a new custom repository. Use "off" to restore the default one or overwrite it with a new one. - __________________________________________________________________________ +### `--force-latest` - `nolibfuse` + --force-latest {PROGRAM} - SYNOPSIS: +Description: Downgrades an installed app from pre-release to "latest". - `nolibfuse {PROGRAM}` +### `--launcher` - DESCRIPTION: Convert an installed Type2 AppImage to get rid of libfuse2. New generation AppImages does not require libfuse2 installed. - __________________________________________________________________________ + --launcher /path/to/${APPIMAGE} - `unlock` +Description: Drag/drop one or more AppImages in the terminal and embed them in the apps menu and customize a command to use from the CLI. - SYNOPSIS: +### `--system` - `unlock {PROGRAM}` + --system - DESCRIPTION: Unlock updates for the selected program. This option nulls the option "lock" (see above). - ___________________________________________________________________________ - ___________________________________________________________________________ +Description: Switch "AM" back to "AM" from "AppMan Mode" (see "--user"). -## EXTRA OPTIONS - __________________________________________________________________________ +### `--user, appman` - `--system` + --user - SYNOPSIS: - - `--system` +Description: Made "AM" run in "AppMan Mode", locally, useful for unprivileged users. This option only works with "AM". - DESCRIPTION: Switch "AM" back to "AM" from "AppMan Mode" (see --user). - __________________________________________________________________________ - - `--user`, `appman` (only available for "AM") - - SYNOPSIS: - - `--user` - - DESCRIPTION: Run "AM" as an unprivileged user making it act as "AppMan". __________________________________________________________________________ @@ -1166,19 +1025,13 @@ EXTRA: The behavior of this option can be tested in a completely standalone way __________________________________________________________________________ ### How to enable bash completion -Bash completion is enabled in "AM" on first installation, while the "AppMan" one requires to be enabled manually. - -For both there are two options: -- `--enabe-completion` to enable it; -- `--disable-completion` to disable it. - -The file used by "AM" is "/etc/bash_completion.d/am-completion.sh", so the root password is required to use the options. The file used by "AppMan" instead is "$HOME/.bash_completion". +From version 8, BASH/ZSH completion is enabled in "AM" and "AppMan" by default. -Both use the keywords to be completed listed within the "list" file, generated from the options list and the applications list. +A file $HOME/.bash_completion will be created, or if it exists, it will be patched to allow the command `am` or `appman` to read arguments from the related "list" of arguments, or other lists, to made it more extensible. -https://user-images.githubusercontent.com/88724353/155971864-783c098c-e696-47b5-aaa8-85dab6ab3b46.mp4 +Before version 8, in "AM" were created a "/etc/bash_completion.d/am-completion.sh" using a dedicated option. -A more detailed guide on how to create your own bash completion script for your project is available [here](https://iridakos.com/programming/2018/03/01/bash-programmable-completion-tutorial). +In case you still have it, run `sudo rm -f /etc/bash_completion.d/am-completion.sh` to remove it. Its no more necessary. ------------------------------------------------------------------------ @@ -1321,9 +1174,58 @@ appman -i --debug /path/to/your-script ``` __________________________________________________________________________ ### Third-party databases for applications (NeoDB) -"AM"/"AppMan" can be extended by adding new application databases using a configuration file named "neodb". +Use the option `newrepo` or `neodb` to add new repositories to use instead of this one. This works for both online and offline repositories. + +Set a new default repo, use "add" to append the path to a local directory or an online URL: +``` +am newrepo add {URL}\{PATH} +``` +or +``` +appman newrepo add {URL}\{PATH} +``` +then use "select" to use it by default: +``` +am newrepo select +``` +or +``` +appman newrepo select +``` +a message will warn you about the usage of this repo instead of the default one. + +In the screenshot below, I'm adding an offline directory and an online "RAW" fork of "AM" +![Istantanea_2024-08-25_20-10-47](https://github.com/user-attachments/assets/599f1c11-e2dd-4343-ac51-32e0eeb2643f) + +Use "on"/"off" to enable/disable it: +``` +am newrepo on +am newrepo off +``` +or +``` +appman newrepo on +appman newrepo off +``` +Use "purge" to remove all 3rd party repos: +``` +am newrepo purge +``` +or +``` +appman newrepo purge +``` +Use "info" to see the source from where installation scripts and lists are taken. +``` +am newrepo info +``` +or +``` +appman newrepo info +``` +if no third-party repo is in use, you will see the default URLs from this repo. -For more details, see the full guide at https://github.com/ivan-hc/neodb +![Istantanea_2024-08-25_20-07-54 png](https://github.com/user-attachments/assets/793e64b9-7377-424c-a70e-a83e89c5225c) ------------------------------------------------------------------------ diff --git a/modules/database.am b/modules/database.am index 6deda083f..4daf6d9e9 100644 --- a/modules/database.am +++ b/modules/database.am @@ -4,8 +4,8 @@ # THIS MODULE INCLUDES ALL THE ACTIONS INTENDED FOR THE MANAGEMENT OF LISTS AND SINGLE PAGES ############################################################################################ -# FUNCTIONS RELATED TO "ABOUT" - +#-------------------------------------------------------------------------- +# ABOUT _about_show_markdown() { if curl -o /dev/null -sIf "$markdown_url"; then markdown_page=$(curl -Ls "$markdown_url" \ @@ -44,7 +44,7 @@ _about_page() { fi METAPACKAGES="kdegames kdeutils node platform-tools" for m in $METAPACKAGES; do - if grep -q "◆ $1 : .*\"$m\"" "$AMPATH/$arch-apps"; then + if grep -q "◆ $1 : .*\"$m\"" "$AMDATADIR/$arch-apps"; then if test -f "$APPSPATH/$m/remove"; then app_status="installed\033[0m, as part of ${Green}$m\033[0m\n\n NOTE: run ${RED}$AMCLI -a $m\033[0m instead" app_name="$m" @@ -66,44 +66,185 @@ _about_page() { _about_show_markdown } -_about_generate_3rd_party() { - disk_usage="" - app_version="" - app_status=" STATUS: NOT INSTALLED" - package_name="$1" - if grep -q "◆ $arg : " "$AMPATH/$arch-apps"; then - printf ' PACKAGE: %s\n' "$arg" | tr '[:lower:]' '[:upper:]' - if [ -f "$APPSPATH/$1/remove" ]; then - disk_usage=$(du -sm "$APPSPATH/$1" | cut -f1) - app_version=$(grep -w " ◆ $1 |" "$AMCACHEDIR"/version-args 2>/dev/null | sed 's:.*| ::') - app_status=$(printf " STATUS: INSTALLED, ABOUT $disk_usage MB OF DISK SPACE IN USE\n VERSION: $app_version") +#-------------------------------------------------------------------------- +# FILES +_files_header() { + echo "" + APPSNUMB=$(find "$APPSPATH" -type f -name 'remove' -exec grep -L 'usr/local/lib' {} \; 2>/dev/null | sed -r 's|/[^/]+$||' | sort | uniq | wc -l) + if [ "$APPSNUMB" = 1 ]; then + APPSMESSAGE="YOU HAVE INSTALLED $APPSNUMB PROGRAM" + else + APPSMESSAGE="YOU HAVE INSTALLED $APPSNUMB PROGRAMS" + fi + if grep -q 'usr/local/lib' $APPSPATH/*/remove 2> /dev/null; then + LIBNUMB=$(grep -l "usr/local/lib" "$APPSPATH"/*/remove | wc -l) + if [ "$LIBNUMB" = 1 ]; then + LIBSMESSAGE="AND $LIBNUMB LIBRARY" + else + LIBSMESSAGE="AND $LIBNUMB LIBRARIES" fi - printf '%s\n' "$app_status" - grep "◆ $arg : " < "$AMPATH/$arch-apps" | cut -d':' -f2- | sed 's/^./\n /' | sed 's# SOURCE:#\n\n SOURCE:#g' + echo "- $APPSMESSAGE $LIBSMESSAGE MANAGED BY $(echo "\"$AMCLI\"" | tr a-z A-Z)" else - printf ' "%s" IS NOT A VALID ARGUMENT\n' "$package_name" + echo "- $APPSMESSAGE MANAGED BY $(echo "\"$AMCLI\"" | tr a-z A-Z)" + fi + echo "" +} + +_files_sizes() { + if grep -q "usr/local/lib" ./$arg/remove; then + LIBNAME=$(cat $APPSPATH/$arg/remove | tr ' ' '\n' | grep "usr/local/lib" | head -1) + SIZE=$(du -sh $LIBNAME | cut -f1 | sort -rh | head -1) + else + SIZE=$(du -sh -- $arg | cut -f1 -d" ") fi + SIZE=$(echo "$SIZE" | sed 's/.$/ &/; s/$/iB/') + echo " ◆ $arg | $SIZE" >> "$AMCACHEDIR"/files-sizes } -_about_download_lib() { - printf "%s\n" " LIBRARY: $1" | tr '[:lower:]' '[:upper:]' - if [ -f "$APPSPATH/$1/remove" ]; then - disk_usage=$(find /usr/local/lib -type f -name "$(echo "$1" | sed -e "s/[0-9]//")*" -exec du -sm {} + | tr ' ' '\n' | head -1) - printf "%s\n" " STATUS: INSTALLED, ABOUT $disk_usage MB OF DISK SPACE IN USE" - else - printf "%s\n" " STATUS: NOT INSTALLED" +_files_if_binary() { + if file ./"$arg"/* | grep "static" >/dev/null 2>&1; then + echo " ◆ $arg | static-binary" >> "$AMCACHEDIR"/files-type + else + echo " ◆ $arg | dynamic-binary" >> "$AMCACHEDIR"/files-type fi - echo "" - grep "◆ $1 : " "$AMPATH/libs-list" | sed 's#.*:##; s/(/\n (/g' - printf '\n%s\n\n' " SITE/SOURCES:" - site_source=$(wget -qO- "$APPSDB/$1" | grep -Eo "(http|https)://[a-zA-Z0-9./?=_%:-]*" | head -1) - echo " $site_source" - echo "" } -#-------------------------------------------------------------------------- -# FUNCTIONS RELATED TO "LIST" AND "QUERY" +_files_if_library() { + echo " ◆ $arg | library" >> "$AMCACHEDIR"/files-type +} + +_files_if_script() { + if grep "/ffwa" "${LINK:-$FILE}" >/dev/null 2>&1; then + echo " ◆ $arg | launcher" >> "$AMCACHEDIR"/files-type + elif grep '#!.*bash' "${LINK:-$FILE}" >/dev/null 2>&1; then + echo " ◆ $arg | bash-script" >> "$AMCACHEDIR"/files-type + elif grep '#!.*dash' "${LINK:-$FILE}" >/dev/null 2>&1; then + echo " ◆ $arg | dash-script" >> "$AMCACHEDIR"/files-type + elif grep '#!.*bin.*sh' "${LINK:-$FILE}" >/dev/null 2>&1; then + echo " ◆ $arg | posix-script" >> "$AMCACHEDIR"/files-type + elif grep '#!.*awk' "${LINK:-$FILE}" >/dev/null 2>&1; then + echo " ◆ $arg | awk-script" >> "$AMCACHEDIR"/files-type + else + echo " ◆ $arg | script" >> "$AMCACHEDIR"/files-type + fi +} + +_files_if_appimage() { + if ! echo "$string" | grep 'AppImages require FUSE to run' >/dev/null 2>&1; then + if grep "SANDBOXDIR" "$FILE" >/dev/null 2>&1; then + echo " ◆ $arg | appimage🔒" >> "$AMCACHEDIR"/files-type + else + echo " ◆ $arg | appimage" >> "$AMCACHEDIR"/files-type + fi + else + if grep "SANDBOXDIR" "$FILE" >/dev/null 2>&1; then + echo " ◆ $arg | appimage🔒*" >> "$AMCACHEDIR"/files-type + else + echo " ◆ $arg | appimage*" >> "$AMCACHEDIR"/files-type + fi + fi +} + +_files_type() { + APPVERSION=$(cat "$AMCACHEDIR"/version-args | grep -w " ◆ $arg |" | sed 's:.*| ::') + string=$(strings -d ./"$arg/$arg" 2>/dev/null) + FILE=$(command -v "$arg" 2>/dev/null) + LINK=$(readlink "$FILE" 2>/dev/null) + if echo "$string" | grep -- '--appimage-extract option' >/dev/null 2>&1; then + _files_if_appimage + elif file ./"$arg"/* | grep -E 'LSB|/bin' >/dev/null 2>&1; then + _files_if_binary + elif grep "#!" "${LINK:-$FILE}" >/dev/null 2>&1; then + _files_if_script + elif grep "usr/local/lib" ./"$arg"/remove >/dev/null 2>&1; then + _files_if_library + else + echo " ◆ $arg | other" >> "$AMCACHEDIR"/files-type + fi +} + +_files_files() { + cd $APPSPATH && + INSTALLED_APPS=$(find -name 'remove' -printf "%h\n" 2>/dev/null | du -sh -- * 2> /dev/null | sort -rh | sed 's@.* @@') + if ! test -f "$AMCACHEDIR"/version-args; then + _check_version + fi + if ! test -f "$AMCACHEDIR"/files-type; then + for arg in $INSTALLED_APPS; do + if test -f ./$arg/remove 2>/dev/null; then + _files_type + fi + done + fi + rm -f "$AMCACHEDIR"/files-sizes + for arg in $INSTALLED_APPS; do + if test -f ./$arg/remove 2>/dev/null; then + _files_sizes + fi + done +} + +_files() { + _files_files + rm -f "$AMCACHEDIR"/files-args + INSTALLED_APPS=$(find -name 'remove' -printf "%h\n" 2>/dev/null | du -sh -- * 2>/dev/null | sort -rh | sed 's@.* @@') + for arg in $INSTALLED_APPS; do + if test -f ./$arg/remove 2>/dev/null; then + APPVERSION=$(grep -w " ◆ $arg |" "$AMCACHEDIR"/version-args | tr ' ' '\n' | tail -1) + APPTYPE=$(grep -w " ◆ $arg |" "$AMCACHEDIR"/files-type | tr ' ' '\n' | tail -1) + APPSYZE=$(grep -w " ◆ $arg |" "$AMCACHEDIR"/files-sizes | tr ' ' '\n' | tail -1) + echo " ◆ $arg | $APPVERSION | $APPTYPE | $APPSYZE" >> "$AMCACHEDIR"/files-args + fi + done +} + +_files_show_only_number() { + find "$APPSPATH" -type f -name 'remove' 2>/dev/null | uniq | wc -l + exit 0 +} +_files_appimage_type_notes() { + if grep -qe "appimage\*\|appimage🔒\*" "$AMCACHEDIR"/files*; then + printf " *has dependency to EOL libfuse2 library, please ask the creator to update\n" + printf "\n" + fi +} + +_files_total_size() { + if [ "$(_files_show_only_number)" = "0" ]; then + printf "\n TOTAL SIZE: $(du -ch $(find -type d -name 'modules' -printf "%h\n") 2>/dev/null | awk 'END {print $1"iB"}' | sed 's/...$/ &/') of disk space in use\n\n" + else + command -v aisap >/dev/null 2>&1 && printf '\n%s\n' " AppImages with 🔒 are sandboxed with aisap" + printf "\n TOTAL SIZE: $(du -ch $(find -type f -name 'remove' -printf "%h\n") 2>/dev/null | awk 'END {print $1"iB"}' | sed 's/...$/ &/') of disk space in use\n\n" + fi +} + +_files_sort_by_name() { + _files_header + rm -f "$AMCACHEDIR"/files-args-byname + _files + printf '%s\n' "- APPNAME | VERSION | TYPE | SIZE " >> "$AMCACHEDIR"/files-args-byname + printf '%s\n' "- ------- | ------- | ---- | ----" >> "$AMCACHEDIR"/files-args-byname + sort "$AMCACHEDIR"/files-args 2>/dev/null >> "$AMCACHEDIR"/files-args-byname + column -t "$AMCACHEDIR"/files-args-byname + _files_total_size + _files_appimage_type_notes +} + +_files_sort_by_size() { + _files_header + rm -f "$AMCACHEDIR"/files-args-bysize + _files + printf '%s\n' "- APPNAME | VERSION | TYPE | SIZE " >> "$AMCACHEDIR"/files-args-bysize + printf '%s\n' "- ------- | ------- | ---- | ----" >> "$AMCACHEDIR"/files-args-bysize + cat "$AMCACHEDIR"/files-args >> "$AMCACHEDIR"/files-args-bysize 2>/dev/null + column -t "$AMCACHEDIR"/files-args-bysize + _files_total_size + _files_appimage_type_notes +} + +#-------------------------------------------------------------------------- +# LIST/QUERY _pretty_list() { # Remove references to URLs, "-a" elements in "-l" and "-q" sed -E 's#(http|https|ftp)://[^ ]*##g; s#(SITE|SOURCE):##g; s/^/\n/g' | _colors | fold -sw 75 | sed 's/^/ /g; s/ ◆ /◆ /g; s/ :/ :/g' @@ -122,6 +263,8 @@ _colors() { } _list() { + # Check if github.com is online, if not, the function will read the offline list + wget -q --tries=10 --timeout=20 --spider https://github.com && _completion_lists # Check the number of installed apps and libraries LIBNUMBER=$(grep "usr/local/lib" "$APPSPATH"/*/remove 2> /dev/null | wc -l) ITEMSNUMBER=$(cd "$APPSPATH" && find -name 'remove' -printf "%h\n" 2>/dev/null | sort -u | wc -l) @@ -132,7 +275,7 @@ _list() { fi APPSNUMBER=$(("$ITEMSNUMBER" - "$LIBNUMBER")) # Determine the number of available apps from the list - AVAILABLE_APPS_NUMBER=$(grep -v "ffwa-\|\"kdegames\"\|\"kdeutils\"\|\"node\"\|\"platform-tools\"" "$AMPATH/$arch-apps" | grep -e "$" -c) + AVAILABLE_APPS_NUMBER=$(grep -v "ffwa-\|\"kdegames\"\|\"kdeutils\"\|\"node\"\|\"platform-tools\"" "$AMDATADIR/$arch-apps" | grep -e "$" -c) # Generate a list of the installed apps with version if test -f "$AMCACHEDIR"/version-args; then INSTALLED=$(sort "$AMCACHEDIR"/version-args 2>/dev/null | sed 's/ | / /g' | grep -v "◆ am ") @@ -142,8 +285,6 @@ _list() { INSTALLED=$(sort "$AMCACHEDIR"/version-args 2>/dev/null | sed 's/ | / /g' | grep -v "◆ am ") MESSAGE2="\n$INSTALLED\n" fi - # Check if github.com is online, if not, the function will read the offline list - wget -q --tries=10 --timeout=20 --spider https://github.com && _completion_lists # Check if among the installed apps are available libraries if [ "$LIBNUMBER" != 0 ]; then # Check if the installed libraries are more than one @@ -165,8 +306,9 @@ _list_appimages() { AVAILABLE_APPIMAGES_NUMBER=$(grep -e "$" -c "$AMCACHEDIR/$arch-appimages") } -#-------------------------------------------------------------------------- -# OPTIONS +################################################################################ +# USAGE +################################################################################ case "$1" in '-a'|'about') @@ -174,15 +316,10 @@ case "$1" in _online_check printf "%s\n" "-----------------------------------------------------------------------" [ ! -f "$AMCACHEDIR"/version-args ] && _check_version - [ ! -f "$AMPATH/libs-list" ] && wget -q "$LIBSLISTDB" -P "$AMPATH" ARGS="$(echo "$@" | cut -f2- -d ' ')" # Removes first argument for arg in $ARGS; do if curl -o /dev/null -sIf "$AMCATALOGUEMARKDOWNS/${arg}.md" 1>/dev/null; then _about_page "$arg" - elif grep -q "◆ $arg : " "$AMPATH/$arch-apps"; then - _about_generate_3rd_party "$arg" - elif grep -q "◆ $arg : " "$AMPATH/libs-list"; then - _about_download_lib "$arg" else printf " ERROR: ${RED}\"$arg\" not found\033[0m\n" fi @@ -190,6 +327,18 @@ case "$1" in done ;; + '-f'|'files') + if [ "$2" = "--less" ]; then + _files_show_only_number + elif [ "$2" = "--byname" ]; then + _files_sort_by_name + _betatester_message_on + else + _files_sort_by_size + _betatester_message_on + fi + ;; + '-l'|'list') _list if [ "$2" = --appimages ]; then @@ -197,7 +346,7 @@ case "$1" in LIST=$(sort "$AMCACHEDIR/$arch-appimages" | _pretty_list) printf "\n$MESSAGE\n$MESSAGE2\n LIST OF THE $AVAILABLE_APPIMAGES_NUMBER APPIMAGES AVAILABLE IN THE 'AM' REPOSITORY:\n$LIST\n" | less -Ir else - LIST=$(sort "$AMPATH/$arch-apps" | _pretty_list) + LIST=$(sort "$AMDATADIR/$arch-apps" | _pretty_list) printf "\n$MESSAGE\n$MESSAGE2\n LIST OF THE $AVAILABLE_APPS_NUMBER APPLICATIONS AVAILABLE IN THE 'AM' REPOSITORY:\n$LIST\n" | less -Ir fi #printf "\n$MESSAGE\n$MESSAGE2\n" @@ -213,8 +362,7 @@ case "$1" in if [ "$2" = --pkg ]; then ARGS="$(echo "$@" | cut -f3- -d ' ' | tr -s ' ' '|')" printf "\n Search results for packages: $ARGS\n\n" | tr '[:lower:]' '[:upper:]' - grep -iE "$ARGS" "$AMPATH/$arch-apps" --color=always | _pretty_list_compat - grep -iE "$ARGS" "$AMPATH/libs-list" --color=always | _pretty_list_compat + grep -iE "$ARGS" "$AMDATADIR/$arch-apps" --color=always | _pretty_list_compat elif [ "$2" = --appimages ]; then ARGS="$(echo "$@" | cut -f3- -d ' ')" printf "\n Search results for \"$ARGS\":\n\n" | tr '[:lower:]' '[:upper:]' @@ -228,8 +376,7 @@ case "$1" in ARGS="$(echo "$@" | cut -f2- -d ' ')" printf "\n Search results for \"$ARGS\":\n\n" | tr '[:lower:]' '[:upper:]' PATTERN="$(echo "$ARGS" | sed 's/ /(?=.*/g; s/$/)/g; s/(/)(/g; s/^/(?=.*/g;')" - grep -Pi "$PATTERN" "$AMPATH/$arch-apps" | _pretty_list_compat - grep -Pi "$PATTERN" "$AMPATH/libs-list" | _pretty_list_compat + grep -Pi "$PATTERN" "$AMDATADIR/$arch-apps" | _pretty_list_compat fi printf '\n' ;; diff --git a/modules/devtools.am b/modules/devtools.am deleted file mode 100644 index 8a29f66e5..000000000 --- a/modules/devtools.am +++ /dev/null @@ -1,200 +0,0 @@ -#!/usr/bin/env bash - -##################################################################################### -# THIS MODULE INCLUDES ALL ACTIONS INTENDED TO BE USED BY DEVELOPERS AND EXPERT USERS -##################################################################################### - -case "$1" in - 'neodb') - while [ -n "$1" ]; do - case $2 in - '') - echo " This option allows you to add new repositories to the existing database" - echo ' this your setup will be saved in the configuration file called "neodb"' - if ! test -f "$AMPATH/neodb"; then - echo " that will be created in $AMPATH" - else - echo " placed in $AMPATH" - fi - echo -e "\n Complete the next three prompts or leave the last two blank to exit." - echo '--------------------------------------------------------------------------' - read -r -ep " Name the new repository (optional): " reponame - case "$reponame" in - '') ;; - *) reponame="[ $reponame ]" - ;; - esac - echo '--------------------------------------------------------------------------' - read -r -ep " Copy/paste the URL of one of the installation scripts of the new repository $(echo -e '\n: ')" appsurl - case "$appsurl" in - '') exit - ;; - *) if curl --output /dev/null --silent --head --fail "$appsurl" 1>/dev/null; then - if ! wget -q "$appsurl" -O - | grep -q "#!"; then - echo '--------------------------------------------------------------------------' - echo -e " 💀 ERROR, the file is not a script, exiting."; echo -e " Invalid URL, retry! \n Visit https://github.com/ivan-hc/neodb for more information"; exit - elif ! wget -q "$appsurl" -O - | grep -q " /opt/"; then - echo '--------------------------------------------------------------------------' - echo -e ' 💀 ERROR, the script does not reference to the /opt path\n so "AM" cannot manage it, exiting.'; echo -e " Invalid script, retry! \n Visit https://github.com/ivan-hc/neodb for more information"; exit - else - appsurl=$(echo "$appsurl" | sed 's![^*/]*$!!' | sed 's:/*$::') - fi - else - echo -e " Invalid URL, retry! \n Visit https://github.com/ivan-hc/neodb for more information"; exit - fi - ;; - esac - echo '--------------------------------------------------------------------------' - read -r -ep ' Now copy/paste the URL to the "'"$arch"'-apps" file, the applications list '"$(echo -e '\n: ')"'' appslisturl - case "$appslisturl" in - '') exit - ;; - *) if curl --output /dev/null --silent --head --fail "$appslisturl" 1>/dev/null; then - if ! echo "$appslisturl" | grep -q "$arch-apps"; then - echo '--------------------------------------------------------------------------' - echo -e ' 💀 ERROR, not a valid name for this list, exiting.'; echo -e " Invalid file, retry! \n Visit https://github.com/ivan-hc/neodb for more information"; exit - elif ! wget -q "$appslisturl" -O - | grep -q "◆ "; then - echo '--------------------------------------------------------------------------' - echo -e ' 💀 ERROR, the file is not correct, missing "◆ " for options "-l"/"-q", exiting.'; echo -e " Invalid list, retry! \n Visit https://github.com/ivan-hc/neodb for more information"; exit - elif ! wget -q "$appslisturl" -O - | grep -q " : "; then - echo '--------------------------------------------------------------------------' - echo -e ' 💀 ERROR, the file is not correct, missing " : " for options "-l"/"-q", exiting.'; echo -e " Invalid list, retry! \n Visit https://github.com/ivan-hc/neodb for more information"; exit - elif ! wget -q "$appslisturl" -O - | grep -q "SOURCE:"; then - echo '--------------------------------------------------------------------------' - echo -e ' 💀 ERROR, the file is not correct, missing "SOURCE:" for option "-a", exiting.'; echo -e " Invalid list, retry! \n Visit https://github.com/ivan-hc/neodb for more information"; exit - else - if ! test -f "$AMPATH/neodb"; then - echo -e "#STATUS=quiet\n" >> "$AMPATH/neodb" - fi - if [ -z "$reponame" ]; then - echo "[ Unknown repo ]" >> "$AMPATH/neodb" - else - echo "$reponame" >> "$AMPATH/neodb" - fi - echo "Source=$appsurl" >> "$AMPATH/neodb" - echo -e "List=$appslisturl\n" >> "$AMPATH/neodb" - echo '--------------------------------------------------------------------------' - echo "SUCCESS!" - exit - fi - else - echo -e " Invalid URL, retry! \n Visit https://github.com/ivan-hc/neodb for more information"; exit - fi - ;; - esac - ;; - '--silent') - if test -f "$AMPATH/neodb"; then - sed -i 's/#STATUS=quiet/STATUS=quiet/g' "$AMPATH/neodb"; exit - else - echo "Configuration file $AMPATH/neodb not found"; exit - fi - ;; - *) echo " USAGE: $AMCLI $1" - echo " $AMCLI $1 --silent" - exit - ;; - esac - done - shift - ;; - - 'apikey') - while [ -n "$1" ]; do - case $2 in - '') echo " USAGE: $AMCLI $1 [ARGUMENT]"; exit;; - del|delete|remove) - if test -f "$AMPATH/ghapikey.txt"; then - rm -f "$AMPATH/ghapikey.txt" - echo "The file $AMPATH/ghapikey.txt has been deleted"; exit - else - echo "No file named $AMPATH/ghapikey.txt has been found"; exit - fi;; - *) - if [[ "$2" =~ ^(gh[ps]_[a-zA-Z0-9]{36}|github_pat_[a-zA-Z0-9]{22}_[a-zA-Z0-9]{59})$ ]]; then - test_apikey_output_with_wget=$(curl -Ls --header "Authorization: token $2" 'https://api.github.com/repos/ivan-hc/AM/releases' | head -1) - if [[ $(echo "$test_apikey_output_with_wget") ]]; then - rm -f "$AMPATH/ghapikey.txt" - echo "$2" >> "$AMPATH/ghapikey.txt" - echo "Validation successful!" - exit - else - echo "ERROR: This is not a valid key!" - exit - fi - else - echo "ERROR: Wrong expression, validation failed!" - exit - fi - ;; - esac - done - shift - ;; - - 'newrepo') - while [ -n "$1" ]; do - case $2 in - '') - echo -e "\n USAGE: $AMCLI $1 [URL] # Set a new repository" - echo " $AMCLI $1 [PATH] # Set a local directory as a new repository" - echo " $AMCLI $1 off # Disable the custom repository" - echo -e " $AMCLI $1 on # Enable the custom repository\n" - echo -e " [URL] EXAMPLE:\n\n https://raw.githubusercontent.com/IVAN-HC/AM/main\n" - exit - ;; - - off|OFF) - if test -f "$AMPATH/new-repo.txt"; then - mv "$AMPATH/new-repo.txt" "$AMPATH/new-repo.old" - echo "Custom repository DISABLED!" - elif test -f "$AMPATH/new-repo.old"; then - echo "Custom repository DISABLED!" - else - echo "You have not a custom repository!" - fi - exit - ;; - on|ON) - if test -f "$AMPATH/new-repo.old"; then - mv "$AMPATH/new-repo.old" "$AMPATH/new-repo.txt" - echo "Custom repository ENABLED!" - elif test -f "$AMPATH/new-repo.txt"; then - echo "Custom repository ENABLED!" - else - echo "You have not a custom repository!" - fi - exit - ;; - *) - if echo "$2" | grep -q "raw.githubusercontent.com"; then - rm -R -f "$AMPATH/new-repo.txt" - echo "$2" | sed 's/\/*$//g' >> "$AMPATH/new-repo.txt" - echo -e "\n Your NEW custom repository is:\n\n $2\n\n This will replace the main one!\n" - echo -e ' Use the command "'"$AMCLI"' newrepo off" to restore the default one!\n' - echo -e ' Repeat this command with a new URL to replace the one you just set!\n' - exit - elif curl --output /dev/null --silent --head --fail "$2" 1>/dev/null; then - rm -R -f "$AMPATH/new-repo.txt" - echo "$2" | sed 's/\/*$//g' >> "$AMPATH/new-repo.txt" - echo -e "\n Your NEW custom repository is:\n\n $2\n\n This will replace the main one!\n" - echo -e ' Use the command "'"$AMCLI"' newrepo off" to restore the default one!\n' - echo -e ' Repeat this command with a new URL to replace the one you just set!\n' - exit - elif test -d "$2"; then - rm -R -f "$AMPATH/new-repo.txt" - echo "$2" | sed 's/\/*$//g' >> "$AMPATH/new-repo.txt" - echo -e "\n Your NEW local/offline custom repository is:\n\n $2\n\n This will replace the main one!\n" - echo -e ' Use the command "'"$AMCLI"' newrepo off" to restore the default one!\n' - echo -e ' Repeat this command with a new URL to replace the one you just set!\n' - exit - else - echo "Invalid URL/PATH, try again" - exit - fi - ;; - esac - done - shift - ;; -esac \ No newline at end of file diff --git a/modules/download.am b/modules/download.am deleted file mode 100644 index ce771d383..000000000 --- a/modules/download.am +++ /dev/null @@ -1,106 +0,0 @@ -#!/usr/bin/env bash - -##################################################################################### -# THIS MODULE ALLOWS YOU TO DOWNLOAD THE INSTALLATION SCRIPTS WITHOUT INSTALLING THEM -##################################################################################### - -function _convert_to_appman_compatible_script() { - if test -f "$APPMANCONFIG"/appman-config; then - APPSPATH=$(cat "$APPMANCONFIG"/appman-config) - sed -i "s# /usr/local/bin# $HOME/.local/bin#g" ./"$arg" - sed -i "s# /usr/games# $HOME/.local/bin#g" ./"$arg" - sed -i "s# /usr/local/games# $HOME/.local/bin#g" ./"$arg" - sed -i "s# /usr/local/share/applications# $DATADIR/applications#g" ./"$arg" - sed -i "s# /usr/local/share/pixmaps# $DATADIR/icons#g" ./"$arg" - sed -i "s# /opt# $HOME/$APPSPATH#g" ./"$arg" - sed -i "s#/opt/#$HOME/$APPSPATH/#g" ./"$arg" - sed -i "s# https://api.github.com#$HeaderAuthWithGITPAT https://api.github.com#g" ./"$arg" - cat <<-HEREDOC >> ./"$arg" - - # POST INSTALLATION PATCH FOR ALL LAUNCHERS - sed -i "s#Exec=\$APP#Exec=$HOME/.local/bin/$APP#g" $DATADIR/applications/*-AM.desktop - sed -i "s#Exec=/usr/bin/#Exec=$HOME/.local/bin/#g" $DATADIR/applications/*-AM.desktop - sed -i "s#Exec=/opt/#Exec=$HOME/$APPSDIR#g" $DATADIR/applications/*-AM.desktop - sed -i "s#Icon=/opt/#Icon=$HOME/$APPSDIR#g" $DATADIR/applications/*-AM.desktop - - HEREDOC - echo -ne " Converting $arg to an AppMan-compatible script.\r" && sleep 0.25 && - echo -ne " \r" - else - echo ' 💀 ERROR: "--convert" requires a configuration file in ~/.config/appman' - fi -} - -function _download() { - if test -f "$AMPATH/neodb"; then - rm -R -f "$AMCACHEDIR/multirepo-args" - MULTIREPO=$(grep "Source=" "$AMPATH/neodb" | sed 's/Source=//g') - for anyrepo in $MULTIREPO; do - if curl --output /dev/null --silent --head --fail "$anyrepo/$arg" 1>/dev/null; then - echo "$anyrepo" >> "$AMCACHEDIR/multirepo-args" - fi - done - if test -f "$AMCACHEDIR/multirepo-args"; then - anyrepoargs=$(sort "$AMCACHEDIR/multirepo-args" 2>/dev/null | wc -l) - if [ "$anyrepoargs" -gt 0 ]; then - if curl --output /dev/null --silent --head --fail "$APPSDB/$arg" 1>/dev/null; then - echo "$APPSDB" >> "$AMCACHEDIR/multirepo-args" - fi - anyrepoargall=$(sort "$AMCACHEDIR/multirepo-args" 2>/dev/null | wc -l) - if [ "$anyrepoargall" = 1 ]; then - cd "$SCRIPTDIR" || return; wget -q "$(sort "$AMCACHEDIR/multirepo-args" | head -1)/$arg" - rm -R -f "$AMCACHEDIR/multirepo-args" - echo " ◆ \"$arg\" third-party installation script downloaded! " - else - echo -e " ◆ FOUND \"$(echo "$arg" | tr '[:lower:]' '[:upper:]')\" FROM MULTIPLE SOURCES:\n" && - printf " Select a URL from this menu (read carefully) or press CTRL+C to abort:\n\n"; sleep 1; - select d in $(cat "$AMCACHEDIR/multirepo-args"); do test -n "$d" && break; echo ">>> Invalid Selection"; done - rm -R -f "$AMCACHEDIR/multirepo-args" - cd "$SCRIPTDIR" || return; wget -q "$d/$arg" - echo " ◆ \"$arg\" installation script downloaded! " - fi - elif curl --output /dev/null --silent --head --fail "$APPSDB/$arg" 1>/dev/null; then - rm -R -f "$AMCACHEDIR/multirepo-args" - cd "$SCRIPTDIR" || return; wget -q "$APPSDB/$arg" - echo " ◆ \"$arg\" installation script downloaded! " - else - echo " 💀 ERROR: \"$arg\" does NOT exist in the database, see \"$AMCLI -l\"" - fi - elif curl --output /dev/null --silent --head --fail "$APPSDB/$arg" 1>/dev/null; then - cd "$SCRIPTDIR" || return; wget -q "$APPSDB/$arg" - echo " ◆ \"$arg\" installation script downloaded! " - else - echo " 💀 ERROR: \"$arg\" does NOT exist in the database, see \"$AMCLI -l\"" - fi - elif curl --output /dev/null --silent --head --fail "$APPSDB/$arg" 1>/dev/null; then - cd "$SCRIPTDIR" || return; wget -q "$APPSDB/$arg" - echo " ◆ \"$arg\" installation script downloaded! " - elif curl --output /dev/null --silent --head --fail "$AMREPO/testing/$arch/$arg" 1>/dev/null; then - echo " ⚠️ \"$arg\" downloaded from \"testing\", the unstable branch " - echo "" - echo " WARNING! PROGRAMS COMING FROM \"TESTING\" ARE BROKEN, USE AT YOUR OWN RISK!" - cd "$SCRIPTDIR" || return; wget -q "$AMREPO/testing/$arch/$arg" - else - echo " 💀 ERROR: \"$arg\" is NOT a valid argument" - fi -} - -case $2 in -'') - echo " USAGE: $AMCLI $1 [ARGUMENT]" - echo " $AMCLI $1 --convert [ARGUMENT]"; exit - ;; -'--convert') - ARGS="$(echo "$@" | cut -f3- -d ' ')" - for arg in $ARGS; do - _download - _convert_to_appman_compatible_script - done - ;; -*) - ARGS="$(echo "$@" | cut -f2- -d ' ')" - for arg in $ARGS; do - _download - done - ;; -esac diff --git a/modules/files.am b/modules/files.am deleted file mode 100644 index 4218f6284..000000000 --- a/modules/files.am +++ /dev/null @@ -1,188 +0,0 @@ -#!/bin/sh - -########################################################################## -# THIS MODULE ALLOWS YOU TO SEE THE MAIN INFORMATION ON THE INSTALLED APPS -########################################################################## - -_files_header() { - echo "" - APPSNUMB=$(find "$APPSPATH" -type f -name 'remove' -exec grep -L 'usr/local/lib' {} \; 2>/dev/null | sed -r 's|/[^/]+$||' | sort | uniq | wc -l) - if [ "$APPSNUMB" = 1 ]; then - APPSMESSAGE="YOU HAVE INSTALLED $APPSNUMB PROGRAM" - else - APPSMESSAGE="YOU HAVE INSTALLED $APPSNUMB PROGRAMS" - fi - if grep -q 'usr/local/lib' $APPSPATH/*/remove 2> /dev/null; then - LIBNUMB=$(grep -l "usr/local/lib" "$APPSPATH"/*/remove | wc -l) - if [ "$LIBNUMB" = 1 ]; then - LIBSMESSAGE="AND $LIBNUMB LIBRARY" - else - LIBSMESSAGE="AND $LIBNUMB LIBRARIES" - fi - echo "- $APPSMESSAGE $LIBSMESSAGE MANAGED BY $(echo "\"$AMCLI\"" | tr a-z A-Z)" - else - echo "- $APPSMESSAGE MANAGED BY $(echo "\"$AMCLI\"" | tr a-z A-Z)" - fi - echo "" -} - -_files_sizes() { - if grep -q "usr/local/lib" ./$arg/remove; then - LIBNAME=$(cat $APPSPATH/$arg/remove | tr ' ' '\n' | grep "usr/local/lib" | head -1) - SIZE=$(du -sh $LIBNAME | cut -f1 | sort -rh | head -1) - else - SIZE=$(du -sh -- $arg | cut -f1 -d" ") - fi - SIZE=$(echo "$SIZE" | sed 's/.$/ &/; s/$/iB/') - echo " ◆ $arg | $SIZE" >> "$AMCACHEDIR"/files-sizes -} - -_files_if_binary() { - if file ./"$arg"/* | grep "static" >/dev/null 2>&1; then - echo " ◆ $arg | static-binary" >> "$AMCACHEDIR"/files-type - else - echo " ◆ $arg | dynamic-binary" >> "$AMCACHEDIR"/files-type - fi -} - -_files_if_library() { - echo " ◆ $arg | library" >> "$AMCACHEDIR"/files-type -} - -_files_if_script() { - if grep "/ffwa" "${LINK:-$FILE}" >/dev/null 2>&1; then - echo " ◆ $arg | launcher" >> "$AMCACHEDIR"/files-type - elif grep '#!.*bash' "${LINK:-$FILE}" >/dev/null 2>&1; then - echo " ◆ $arg | bash-script" >> "$AMCACHEDIR"/files-type - elif grep '#!.*dash' "${LINK:-$FILE}" >/dev/null 2>&1; then - echo " ◆ $arg | dash-script" >> "$AMCACHEDIR"/files-type - elif grep '#!.*bin.*sh' "${LINK:-$FILE}" >/dev/null 2>&1; then - echo " ◆ $arg | posix-script" >> "$AMCACHEDIR"/files-type - elif grep '#!.*awk' "${LINK:-$FILE}" >/dev/null 2>&1; then - echo " ◆ $arg | awk-script" >> "$AMCACHEDIR"/files-type - else - echo " ◆ $arg | script" >> "$AMCACHEDIR"/files-type - fi -} - -_files_if_appimage() { - if ! echo "$string" | grep 'AppImages require FUSE to run' >/dev/null 2>&1; then - if grep "SANDBOXDIR" "$FILE" >/dev/null 2>&1; then - echo " ◆ $arg | appimage🔒" >> "$AMCACHEDIR"/files-type - else - echo " ◆ $arg | appimage" >> "$AMCACHEDIR"/files-type - fi - else - if grep "SANDBOXDIR" "$FILE" >/dev/null 2>&1; then - echo " ◆ $arg | appimage🔒*" >> "$AMCACHEDIR"/files-type - else - echo " ◆ $arg | appimage*" >> "$AMCACHEDIR"/files-type - fi - fi -} - -_files_type() { - APPVERSION=$(cat "$AMCACHEDIR"/version-args | grep -w " ◆ $arg |" | sed 's:.*| ::') - string=$(strings -d ./"$arg/$arg" 2>/dev/null) - FILE=$(command -v "$arg" 2>/dev/null) - LINK=$(readlink "$FILE" 2>/dev/null) - if echo "$string" | grep -- '--appimage-extract option' >/dev/null 2>&1; then - _files_if_appimage - elif file ./"$arg"/* | grep -E 'LSB|/bin' >/dev/null 2>&1; then - _files_if_binary - elif grep "#!" "${LINK:-$FILE}" >/dev/null 2>&1; then - _files_if_script - elif grep "usr/local/lib" ./"$arg"/remove >/dev/null 2>&1; then - _files_if_library - else - echo " ◆ $arg | other" >> "$AMCACHEDIR"/files-type - fi -} - -_files_files() { - cd $APPSPATH && - INSTALLED_APPS=$(find -name 'remove' -printf "%h\n" 2>/dev/null | du -sh -- * 2> /dev/null | sort -rh | sed 's@.* @@') - if ! test -f "$AMCACHEDIR"/version-args; then - _check_version - fi - if ! test -f "$AMCACHEDIR"/files-type; then - for arg in $INSTALLED_APPS; do - if test -f ./$arg/remove 2>/dev/null; then - _files_type - fi - done - fi - rm -f "$AMCACHEDIR"/files-sizes - for arg in $INSTALLED_APPS; do - if test -f ./$arg/remove 2>/dev/null; then - _files_sizes - fi - done -} - -_files() { - _files_files - rm -f "$AMCACHEDIR"/files-args - INSTALLED_APPS=$(find -name 'remove' -printf "%h\n" 2>/dev/null | du -sh -- * 2>/dev/null | sort -rh | sed 's@.* @@') - for arg in $INSTALLED_APPS; do - if test -f ./$arg/remove 2>/dev/null; then - APPVERSION=$(grep -w " ◆ $arg |" "$AMCACHEDIR"/version-args | tr ' ' '\n' | tail -1) - APPTYPE=$(grep -w " ◆ $arg |" "$AMCACHEDIR"/files-type | tr ' ' '\n' | tail -1) - APPSYZE=$(grep -w " ◆ $arg |" "$AMCACHEDIR"/files-sizes | tr ' ' '\n' | tail -1) - echo " ◆ $arg | $APPVERSION | $APPTYPE | $APPSYZE" >> "$AMCACHEDIR"/files-args - fi - done -} - -_files_show_only_number() { - find "$APPSPATH" -type f -name 'remove' 2>/dev/null | uniq | wc -l - exit 0 -} - -_files_appimage_type_notes() { - if grep -qe "appimage\*\|appimage🔒\*" "$AMCACHEDIR"/files*; then - printf " *has dependency to EOL libfuse2 library, please ask the creator to update\n" - printf "\n" - fi -} - -_files_total_size() { - if [ "$(_files_show_only_number)" = "0" ]; then - printf "\n TOTAL SIZE: $(du -ch $(find -type d -name 'modules' -printf "%h\n") 2>/dev/null | awk 'END {print $1"iB"}' | sed 's/...$/ &/') of disk space in use\n\n" - else - command -v aisap >/dev/null 2>&1 && printf '\n%s\n' " AppImages with 🔒 are sandboxed with aisap" - printf "\n TOTAL SIZE: $(du -ch $(find -type f -name 'remove' -printf "%h\n") 2>/dev/null | awk 'END {print $1"iB"}' | sed 's/...$/ &/') of disk space in use\n\n" - fi -} - -_files_sort_by_name() { - _files_header - rm -f "$AMCACHEDIR"/files-args-byname - _files - printf '%s\n' "- APPNAME | VERSION | TYPE | SIZE " >> "$AMCACHEDIR"/files-args-byname - printf '%s\n' "- ------- | ------- | ---- | ----" >> "$AMCACHEDIR"/files-args-byname - sort "$AMCACHEDIR"/files-args 2>/dev/null >> "$AMCACHEDIR"/files-args-byname - column -t "$AMCACHEDIR"/files-args-byname - _files_total_size - _files_appimage_type_notes -} - -_files_sort_by_size() { - _files_header - rm -f "$AMCACHEDIR"/files-args-bysize - _files - printf '%s\n' "- APPNAME | VERSION | TYPE | SIZE " >> "$AMCACHEDIR"/files-args-bysize - printf '%s\n' "- ------- | ------- | ---- | ----" >> "$AMCACHEDIR"/files-args-bysize - cat "$AMCACHEDIR"/files-args >> "$AMCACHEDIR"/files-args-bysize 2>/dev/null - column -t "$AMCACHEDIR"/files-args-bysize - _files_total_size - _files_appimage_type_notes -} - -if [ "$2" = "--less" ]; then - _files_show_only_number -elif [ "$2" = "--byname" ]; then - _files_sort_by_name -else - _files_sort_by_size -fi diff --git a/modules/help.am b/modules/help.am deleted file mode 100644 index df90bb9ca..000000000 --- a/modules/help.am +++ /dev/null @@ -1,406 +0,0 @@ -#!/usr/bin/env bash - -######################################### -# THIS MODULE ONLY SHOWS THE HELP MESSAGE -######################################### - -function _help_head() { - printf ' - _____ _____ - /\ \ /\ \ A A - /::\ \ /::\____\ P M - /::::\ \ /::::| | P - /::::::\ \ /:::::| | M & - /:::/\:::\ \ /::::::| | A - /:::/__\:::\ \ /:::/|::| | N - /::::\ \:::\ \ /:::/ |::| | - /::::::\ \:::\ \ /:::/ |::|___|______ - /:::/\:::\ \:::\ \ /:::/ |::::::::\ \ - /:::/ \:::\ \:::\____\/:::/ |:::::::::\____\ - \::/ \:::\ /:::/ /\::/ / ~~~~~/:::/ / - \/____/ \:::\/:::/ / \/____/ /:::/ / - \::::::/ / /:::/ / - \::::/ / /:::/ / - /:::/ / /:::/ /╔═╗╔╗╔┌─┐┌─┐┌─┐┬─┐ - /:::/ / /:::/ / ╠═╣║║║├─┤│ ┬├┤ ├┬┘ - /:::/ / /:::/ / ╩ ╩╝╚╝┴ ┴└─┘└─┘┴└─ - /:::/ /╔═╗╔═╗┬ ┬┌─┐┌─┐┌┬┐┬┌─┐┌┐┌ - \::/ / ╠═╝╠═╝│ ││ ├─┤ │ ││ ││││ - \/____/ ╩ ╩ ┴─┘┴└─┘┴ ┴ ┴ ┴└─┘┘└┘ by Ivan Alex HC - - >> 𝘋𝘢𝘵𝘢𝘣𝘢𝘴𝘦 & 𝘴𝘰𝘭𝘶𝘵𝘪𝘰𝘯𝘴 𝘧𝘰𝘳 𝘢𝘭𝘭 𝘈𝘱𝘱𝘐𝘮𝘢𝘨𝘦𝘴 𝘢𝘯𝘥 𝘱𝘰𝘳𝘵𝘢𝘣𝘭𝘦 𝘢𝘱𝘱𝘴 𝘧𝘰𝘳 𝘎𝘕𝘜/𝘓𝘪𝘯𝘶𝘹 << - - ##########################################################################' -} - -function _help_body() { - printf ' - ___________________________________________________________________________ - - CLIENT/VERSION: "'"$(echo "$AMCLI" | tr a-z A-Z)"'" v'"$($AMCLIPATH -v)"' - - USAGE: '$AMCLI' {OPTION} - - '$AMCLI' {OPTION} {PROGRAM} - __________________________________________________________________________ - - ########################################################################## - __________________________________________________________________________ - - OPTIONS - - (standard, for both "AM" AND "APPMAN") - __________________________________________________________________________ - __________________________________________________________________________ - - -a, about - - SYNOPSIS: -a {PROGRAM} - - DESCRIPTION: Shows more info about one or more apps. - __________________________________________________________________________ - - -b, backup - - SYNOPSIS: -b {PROGRAM} - - DESCRIPTION: Save the current version of one or more apps. - - Snapshots are stored in $HOME/.am-snapshots/$PROGRAM. - - To restore the snapshots see the "-o" option. - __________________________________________________________________________ - - -c, clean - - SYNOPSIS: -c - - DESCRIPTION: Removes all the unnecessary files and folders. - __________________________________________________________________________ - - -C, --config - - SYNOPSIS: -C {PROGRAM} - - DESCRIPTION: Set a dedicated $XDD_CONFIG_HOME for one or more AppImages. - __________________________________________________________________________ - - -d, download - - SYNOPSIS: -d {PROGRAM} - -d --convert {PROGRAM} - - DESCRIPTION: Download one or more installation scripts to your desktop. - - With the option "--convert" its converted to a standalone local installer, - - but AM requires AppMan to be installed to add custom directory settings. - __________________________________________________________________________ - - -e, extra - - SYNOPSIS: -e user/project {APPNAME} - -e user/project {APPNAME} {KEYWORD} - - DESCRIPTION: Install AppImages from github.com, outside the database. - - This allows you to install, update and manage them all like the others. - - Where "user/project" can be the whole URL to the github repository, - - give a name to the program so that it can be used from the command line. - - Optionally, add an "univoque" keyword if multiple AppImages are listed. - __________________________________________________________________________ - - -f, files - - SYNOPSIS: -f - -f --byname - -f --less - - DESCRIPTION: Shows the list of all installed programs, with sizes. - - By default apps are sorted by size, use "--byname" to sort by name. - - With the option "--less" it shows only the number of installed apps. - __________________________________________________________________________ - - -h, help - - SYNOPSIS: -h - - DESCRIPTION: Prints this message. - __________________________________________________________________________ - - -H, --home - - SYNOPSIS: -H {PROGRAM} - - DESCRIPTION: Set a dedicated $HOME directory for one or more AppImages. - __________________________________________________________________________ - - -i, install - - SYNOPSIS: -i {PROGRAM} - -i --debug {PROGRAM} - -i --force-latest {PROGRAM} - - DESCRIPTION: Install one or more programs or libraries from the list. - - With the "--debug" option you can see log messages to debug the script. - - For more details on "--force-latest", see the dedicated option, below. - __________________________________________________________________________ - - -l, list - - SYNOPSIS: -l - -l --appimages - - DESCRIPTION: Shows the list of all the apps available in the repository. - - Add the "--appimages" option to list only the AppImages. - __________________________________________________________________________ - - -o, overwrite - - SYNOPSIS: -o {PROGRAM} - - DESCRIPTION: Overwrite apps with snapshots saved previously (see "-b"). - __________________________________________________________________________ - - -q, query - - SYNOPSIS: -q {KEYWORD} - -q --appimages {KEYWORD} - -q --pkg {PROGRAM1} {PROGRAM2} - - DESCRIPTION: Search for keywords in the list of available applications. - - Add the "--appimages" option to list only the AppImages. - - Add the "--pkg" option to search only the names of one or more apps. - __________________________________________________________________________ - - -r, remove - - SYNOPSIS: -r {PROGRAM} - - DESCRIPTION: Removes one or more apps, requires confirmation. - __________________________________________________________________________ - - -R - - SYNOPSIS: -R {PROGRAM} - - DESCRIPTION: Removes one or more apps without asking. - __________________________________________________________________________ - - -s, sync - - SYNOPSIS: -s - - DESCRIPTION: Updates this script to the latest version hosted. - __________________________________________________________________________ - - -t, template - - SYNOPSIS: -t {PROGRAM} - - DESCRIPTION: Generate a custom installation script. - - You can install it using the "'$AMCLI' -i /path/to/your-script" command. - __________________________________________________________________________ - - -u, -U, update - - SYNOPSIS: -u - -u --apps - -u {PROGRAM} - - DESCRIPTION: Update all the apps (and "'$AMCLI'" itself) or just one. - - If you add the "--apps" suboption you only update apps. - __________________________________________________________________________ - - -v, version - - SYNOPSIS: -v - - DESCRIPTION: Shows the version. - __________________________________________________________________________ - - --devmode-disable - - SYNOPSIS: --devmode-disable - - DESCRIPTION: Undo "--devmode-enable" (see below). - __________________________________________________________________________ - - --devmode-enable - - SYNOPSIS: --devmode-enable - - DESCRIPTION: Use the development branch (at your own risk). - __________________________________________________________________________ - - --disable-completion - - SYNOPSIS: --disable-completion - - DESCRIPTION: Disable bash-completion. - __________________________________________________________________________ - - --disable-sandbox - - SYNOPSIS: --disable-sandbox {PROGRAM} - - DESCRIPTION: Disable the sandbox for the selected app. - __________________________________________________________________________ - - --enable-completion - - SYNOPSIS: --enable-completion - - DESCRIPTION: Enable bash-completion. - __________________________________________________________________________ - - --force-latest - - SYNOPSIS: --force-latest {PROGRAM} - -i --force-latest {PROGRAM} - - DESCRIPTION: Downgrades an installed app from pre-release to "latest". - - This can be used with "-i" to force the installation of apps from "latest". - - Many scripts point to "releases" to find the latest build for GNU/Linux if - - the developer has not uploaded one in "latest". - __________________________________________________________________________ - - --launcher - - SYNOPSIS: --launcher /path/to/${APPIMAGE} - - DESCRIPTION: Embed one or more local AppImages in the applications menu. - - This will also create a script to launch AppImage from $PATH as "binary". - - I suggest dragging the files into the terminal to get the desired effect. - __________________________________________________________________________ - - --rollback, downgrade - - SYNOPSIS: --rollback {PROGRAM} - - DESCRIPTION: Download an older or specific app version. - __________________________________________________________________________ - - --sandbox - - SYNOPSIS: --sandbox {PROGRAM} - - DESCRIPTION: Run an AppImage in a sandbox using Aisap. - __________________________________________________________________________ - - apikey - - SYNOPSIS: apikey {Github Token} - apikey delete - - DESCRIPTION: Accede to github APIs using your personal access tokens. - - The configuration file named "ghapikey.txt" will be saved in '$AMPATH'. - - Use the command "'$AMCLI' apikey delete/del/remove" to remove the file. - __________________________________________________________________________ - - lock - - SYNOPSIS: lock {PROGRAM} - - DESCRIPTION: Lock the selected app to the current version installed. - - Only works if exists a dedicated "AM-updater" installed with the app. - __________________________________________________________________________ - - neodb - - SYNOPSIS: neodb - newrepo --silent - - DESCRIPTION: Add third-party repos to extend the existing database. - - Use "--silent" to hide messages about third-party repos in use. - __________________________________________________________________________ - - newrepo - - SYNOPSIS: newrepo {URL} - newrepo {PATH} - newrepo off - newrepo on - - DESCRIPTION: Set the variable "$AMREPO" to a new custom repository. - - Use "off" to restore the default one or overwrite it with a new one. - __________________________________________________________________________ - - nolibfuse - - SYNOPSIS: nolibfuse {PROGRAM} - - DESCRIPTION: Convert an installed Type2 AppImage to get rid of libfuse2. - - New generation AppImages does not require libfuse2 installed. - __________________________________________________________________________ - - unlock - - SYNOPSIS: unlock {PROGRAM} - - DESCRIPTION: Unlock updates for the selected program (nulls "lock"). - __________________________________________________________________________ - __________________________________________________________________________ - - EXTRA OPTIONS - __________________________________________________________________________ - - --system - - SYNOPSIS: --system - - DESCRIPTION: Switch "AM" back to "AM" from "AppMan Mode" (see --user). - __________________________________________________________________________ - - --user, appman ( only works with "AM" ) - - SYNOPSIS: --user - - DESCRIPTION: Run "AM" as an unprivileged user making it act as "AppMan". - __________________________________________________________________________ - - ##########################################################################' -} - -function _help_footer() { - printf ' - - SITES: - - https://github.com/IVAN-HC/AM - - https://github.com/IVAN-HC/APPMAN - - ##########################################################################' -} - -function _help() { - _help_head - _help_body - _help_footer | less -} - -_help | less diff --git a/modules/install.am b/modules/install.am index 449c2c051..7c93fac17 100644 --- a/modules/install.am +++ b/modules/install.am @@ -1,12 +1,53 @@ -#!/usr/bin/env bash +#!/bin/sh ############################################################################# # THIS MODULE IS USED TO INSTALL APPS FROM THE DATABASE OR FROM LOCAL SCRIPTS ############################################################################# BINDIR="${XDG_BIN_HOME:-$HOME/.local/bin}" -SUDOCMD="$SUDOCOMMAND" +#-------------------------------------------------------------------------- +# DOWNLOAD +_convert_to_appman_compatible_script() { + if test -f "$APPMANCONFIG"/appman-config; then + APPSPATH=$(cat "$APPMANCONFIG"/appman-config) + sed -i "s# /usr/local/bin# $HOME/.local/bin#g" ./"$arg" + sed -i "s# /usr/local/share/applications# $DATADIR/applications#g" ./"$arg" + sed -i "s# /opt# $HOME/$APPSPATH#g" ./"$arg" + sed -i "s#/opt/#$HOME/$APPSPATH/#g" ./"$arg" + sed -i "s# https://api.github.com#$HeaderAuthWithGITPAT https://api.github.com#g" ./"$arg" + cat <<-HEREDOC >> ./"$arg" + + # POST INSTALLATION PATCH FOR ALL LAUNCHERS + sed -i "s#Exec=\$APP#Exec=$HOME/.local/bin/$APP#g" $DATADIR/applications/*-AM.desktop + sed -i "s#Exec=/usr/bin/#Exec=$HOME/.local/bin/#g" $DATADIR/applications/*-AM.desktop + sed -i "s#Exec=/opt/#Exec=$HOME/$APPSDIR#g" $DATADIR/applications/*-AM.desktop + sed -i "s#Icon=/opt/#Icon=$HOME/$APPSDIR#g" $DATADIR/applications/*-AM.desktop + + HEREDOC + printf " Converting $arg to an AppMan-compatible script.\r" && sleep 0.25 && + printf " \r" + else + echo ' 💀 ERROR: "--convert" requires a configuration file in ~/.config/appman' + fi +} + +_download() { + if curl --output /dev/null --silent --head --fail "$APPSDB/$arg" 1>/dev/null; then + cd "$SCRIPTDIR" || return 1 + curl --no-clobber -Os "$APPSDB/$arg" || return 1 + echo " ◆ \"$arg\" installation script downloaded! " + elif curl --output /dev/null --silent --head --fail "$AMREPO/testing/$ARCH/$arg" 1>/dev/null; then + cd "$SCRIPTDIR" || return 1 + curl --no-clobber -Os "$AMREPO/testing/$ARCH/$arg" > ./"$arg" || return 1 + echo " ⚠️ \"$arg\" downloaded from \"testing\", the unstable branch, BE AWARE!" + else + echo " 💀 ERROR: \"$arg\" is NOT a valid argument" + fi +} + +#-------------------------------------------------------------------------- +# INSTALL # If you use the --latest option, add the "latest" flag to scripts that point to a very common "release" _if_latest() { if grep -q 'force-latest' "$AMCACHEDIR"/install-args; then @@ -22,7 +63,7 @@ _spooky_check() { echo "" read -p " Do you wish to continue? (N/y): " yn if ! echo "$yn" | grep -i '^y' >/dev/null 2>&1; then - printf "\n INSTALLATION ABORTED!\n" + printf "\n INSTALLATION ABORTED! \n" return 1 fi fi @@ -36,23 +77,23 @@ _apply_patches() { -e "s#/usr/local/share#$DATADIR#g" \ -e "s#/opt/#$APPSPATH/#g" ./"$arg" else - "$SUDOCMD" mkdir -p /usr/local/{share/applications,bin} + "$SUDOCMD" mkdir -p /usr/local/share/applications /usr/local/bin fi if ! grep -q -- "--debug" "$AMCACHEDIR"/install-args && wget --version | head -1 | grep -q ' 1.'; then # Patch "wget" (version 1.x) to have a progress bar and fix errors when applying patches sed -i "s#wget #wget -q --no-verbose --show-progress --progress=bar #g" ./"$arg" fi sed -i "s# https://api.github.com#$HeaderAuthWithGITPAT https://api.github.com#g" ./"$arg" - sed -i 's#DirIcon$#DirIcon 2>/dev/null#g' ./"$arg" - sed -i 's#DirIcon ./icons/"$APP" 1#DirIcon ./icons/"$APP" 2#g' ./"$arg" + sed -i "s#DirIcon\$#DirIcon 2>/dev/null#g" ./"$arg" + sed -i "s#DirIcon ./icons/\"\$APP\" 1#DirIcon ./icons/\"\$APP\" 2#g" ./"$arg" } _am_remover_check() { # Put permission check in remove script and change ownership of directory if [ "$AMCLI" = am ]; then - $SUDOCMD sed -i '1 a [ "$(id -u)" -ne 0 ] && echo "Permission denied" && exit 1' \ + $SUDOCMD sed -i "1 a [ \"\$(id -u)\" -ne 0 ] && echo "Permission denied" && exit 1" \ "${LASTDIRPATH}"/remove 2>/dev/null - $SUDOCMD chown -R $USER ${LASTDIRPATH} 2>/dev/null + $SUDOCMD chown -R "$USER" "${LASTDIRPATH}" 2>/dev/null fi } @@ -64,7 +105,7 @@ _post_installation_processes() { _am_remover_check # Check for AM-updater script sothat CLI can manage updates [ -f "${LASTDIRPATH}"/AM-updater ] && mkdir "${LASTDIRPATH}"/.am-installer 2>/dev/null \ - && wget -q "$APPSDB"/"$arg" -O "${LASTDIRPATH}"/.am-installer/"$arg" + && curl -Ls "$APPSDB"/"$arg" > "${LASTDIRPATH}"/.am-installer/"$arg" find "${LASTDIRPATH}"/icons/* -xtype l -delete 2>/dev/null # Removes broken links # If you have a broken or missing icon in your "icons" directory, download one from the catalog [ -z "$(ls -A "${LASTDIRPATH}"/icons 2>/dev/null)" ] \ @@ -73,7 +114,7 @@ _post_installation_processes() { if [ "$AMCLI" = "appman" ]; then # Likely not needed anymore: "s#Icon=/opt#Icon=$HOME/$APPSDIR#g" sed -i -e "s#Exec=$arg#Exec=$BINDIR/$arg#g" \ - -e 's#Exec=$APP#Exec='"$BINDIR"'/$APP#g' \ + -e "s#Exec=\$APP#Exec=$BINDIR/\$APP#g" \ -e "s#Exec=/usr/bin/#Exec=$BINDIR/#g" \ -e "s#Exec=/opt/#Exec=$BINDIR/#g" "$DATADIR"/applications/*-AM.desktop 2>/dev/null fi @@ -91,15 +132,9 @@ _ending_the_installation() { echo " 💀 ERROR DURING INSTALLATION, REMOVED $APPNAME!" $AMCLIPATH -R "$LASTDIR" 1> /dev/null else - chown -R $USER "$AMCACHEDIR"/about 2>/dev/null - for metapackage in $METAPACKAGES; do - if grep -q "$metapackage" ./"$arg" 2> /dev/null; then - metascript="$LASTDIR" - fi - done APPSIZE=$(du -sm "${LASTDIRPATH}" | awk '{print $1}' ) LASTDIRNAME=$(echo "\"$LASTDIR\"" | tr '[:lower:]' '[:upper:]') - echo -ne " ${Green}$LASTDIRNAME INSTALLED\033[0m ($APPSIZE MB OF DISK SPACE)\n" + printf " ${Green}$LASTDIRNAME INSTALLED\033[0m ($APPSIZE MB OF DISK SPACE)\n" $SUDOCMD rm "$AMCACHEDIR"/"$arg" _check_version app_version=$(grep -w " ◆ $LASTDIR |" 0<"$AMCACHEDIR"/version-args | sed 's:.*| ::') @@ -130,7 +165,7 @@ for metapackage in $METAPACKAGES; do $SUDOCMD "$APPSPATH"/"$metapackage"/remove 2> /dev/null elif [ -d "$APPSPATH"/"$metapackage" ]; then METAPACKAGE_NAME=$(echo "$metapackage" | tr '[:lower:]' '[:upper:]') - echo " ◆ \"$APPNAME\" IS PART OF \"$METAPACKAGE_NAME\", ALREADY INSTALLED" + echo " ◆ $APPNAME IS PART OF \"$METAPACKAGE_NAME\", ALREADY INSTALLED" return 1 fi fi @@ -156,7 +191,7 @@ _install_arg() { sed -i 's#firefox --class#'"$(echo "$ffbrowser" | xargs -L 1 basename)"' --class#g' ./"$arg" fi elif grep -qi "^wget.*.sh.*chmod.*&&" ./"$arg"; then - appimage_bulder_script=$(grep "^wget " ./"$arg" | tr '"' '\n' | grep -i "^http" | sed 's/$APP/'"$arg"'/g') + appimage_bulder_script=$(grep "^wget " ./"$arg" | tr '"' '\n' | grep -i "^http" | sed "s/\$APP/$arg/g") if curl --output /dev/null --silent --head --fail "$appimage_bulder_script" 1> /dev/null; then for name in $app_deps; do if curl -Ls "$appimage_bulder_script" | grep "^$name" 1>/dev/null; then @@ -186,7 +221,7 @@ _install_arg() { printf "\n ⚠️ This script will install a system library in /usr/local/lib\n\n" read -p " Do you wish to continue? (N/y): " yn if ! echo "$yn" | grep -i '^y' >/dev/null 2>&1; then - printf "\n INSTALLATION ABORTED!\n" + printf "\n INSTALLATION ABORTED! \n" return 0 fi fi @@ -219,73 +254,45 @@ _install_local_script() { fi } -# This is for scripts hosted on the official online database or a third-party one +# This is for scripts hosted on the official online database _install_normally() { - mkdir -p "$AMCACHEDIR"/tmp && rm -f "$AMCACHEDIR"/tmp/* && - wget -q "$APPSDB"/"$arg" -O "$AMCACHEDIR"/tmp/"$arg" && + mkdir -p "$AMCACHEDIR"/tmp && rm -f "$AMCACHEDIR"/tmp/* || return + curl -Ls "$APPSDB"/"$arg" > "$AMCACHEDIR"/tmp/"$arg" || return cd "$AMCACHEDIR" && mkdir -p tmp && cd tmp || return cd "$AMCACHEDIR" && mv ./tmp/"$arg" ./"$arg" && rmdir ./tmp || return _install_arg } -# This function is entirely dedicated to third-party databases -_install_from_third_party_repo() { - rm -R -f "$AMCACHEDIR/multirepo-args" - MULTIREPO=$(grep "Source=" "$AMPATH/neodb" | sed 's/Source=//g') - for anyrepo in $MULTIREPO; do - if curl --output /dev/null --silent --head --fail "$anyrepo"/"$arg" 1> /dev/null; then - echo "$anyrepo" >> "$AMCACHEDIR/multirepo-args" - fi - done - if test -f "$AMCACHEDIR/multirepo-args"; then - anyrepoargs=$(sort "$AMCACHEDIR/multirepo-args" 2> /dev/null | wc -l) - if [ "$anyrepoargs" -gt 0 ]; then - if curl --output /dev/null --silent --head --fail "$APPSDB"/"$arg" 1> /dev/null; then - echo "$APPSDB" >> "$AMCACHEDIR/multirepo-args" - fi - anyrepoargall=$(sort "$AMCACHEDIR/multirepo-args" 2> /dev/null | wc -l) - if [ "$anyrepoargall" = 1 ]; then - mkdir -p "$AMCACHEDIR"/tmp && rm -f "$AMCACHEDIR"/tmp/* && - wget -q "$(head -1 "$AMCACHEDIR/multirepo-args")/$arg" -O "$AMCACHEDIR"/tmp/"$arg" && - cd "$AMCACHEDIR" && mv ./tmp/"$arg" ./"$arg" && rmdir ./tmp || return - rm -R -f "$AMCACHEDIR/multirepo-args" - _install_arg - else - printf '\n%s\n' " ◆ FOUND $APPNAME FROM MULTIPLE SOURCES:" - printf '%s\n\n' " Select a URL from this menu (read carefully) or press CTRL+C to abort:" - sleep 1 - select d in $(cat "$AMCACHEDIR/multirepo-args"); do - test -n "$d" && break - echo ">>> Invalid Selection" - done - mkdir -p "$AMCACHEDIR"/tmp && rm -f "$AMCACHEDIR"/tmp/* && - wget -q "$d/$arg" -O "$AMCACHEDIR"/tmp/"$arg" && - cd "$AMCACHEDIR" && mv ./tmp/"$arg" ./"$arg" && rmdir ./tmp || return - rm -R -f "$AMCACHEDIR/multirepo-args" - _install_arg - fi - elif curl --output /dev/null --silent --head --fail "$APPSDB"/"$arg" 1>/dev/null; then - mkdir -p "$AMCACHEDIR"/tmp && rm -f "$AMCACHEDIR"/tmp/* && - wget -q "$APPSDB"/"$arg" -O "$AMCACHEDIR"/tmp/"$arg" && - cd "$AMCACHEDIR" && mv ./tmp/"$arg" ./"$arg" && rmdir ./tmp || return - rm -R -f "$AMCACHEDIR/multirepo-args" - _install_arg +################################################################################ +# USAGE +################################################################################ + +case "$1" in + '-d'|'download') + case $2 in + '--convert') + [ -z "$3" ] && echo " USAGE: $AMCLI $1 $2 [ARGUMENT]" && exit 1 + ;; + '') + echo " USAGE: $AMCLI $1 [ARGUMENT]" + echo " USAGE: $AMCLI $1 --convert [ARGUMENT]" + exit 1 + ;; + esac + if [ "$2" = "--convert" ]; then + ARGS="$(echo "$@" | cut -f3- -d ' ')" + for arg in $ARGS; do + _download + _convert_to_appman_compatible_script + done else - echo " 💀 ERROR: \"$arg\" does NOT exist in the database, see \"$AMCLI -l\"" + ARGS="$(echo "$@" | cut -f2- -d ' ')" + for arg in $ARGS; do + _download + done fi - elif curl --output /dev/null --silent --head --fail "$APPSDB"/"$arg" 1>/dev/null; then - _install_normally - else - echo " 💀 ERROR: \"$arg\" does NOT exist in the database, see \"$AMCLI -l\"" - fi -} - -################################## -# OPTIONS AVAILABLE IN THIS MODULE -################################## + ;; -while [ -n "$1" ]; do - case "$1" in '-i'|'install') case $2 in '--debug'|'--force-latest') @@ -298,11 +305,11 @@ while [ -n "$1" ]; do exit 1 ;; esac - [ "$AMCLI" = "am" ] && { $SUDOCMD echo -ne "\r" || exit 1; } + [ "$AMCLI" = "am" ] && { $SUDOCMD printf "\r" || exit 1; } echo "============================================================================" echo "" - echo -e " ${LightBlue}START OF ALL INSTALLATION PROCESSES\033[0m" + printf " ${LightBlue}START OF ALL INSTALLATION PROCESSES\033[0m\n" echo "" echo "============================================================================" _clean_amcachedir 2>/dev/null @@ -327,7 +334,7 @@ while [ -n "$1" ]; do if [ -d "$APPSPATH"/"$arg"/tmp ]; then $SUDOCMD "$APPSPATH"/"$arg"/remove 2> /dev/null fi - # Various cases that may occur during installation (for example if you use a third-party repository) + # Various cases that may occur during installation if test -f "$APPSPATH"/"$arg"/remove; then echo " ◆ \"$arg\" is already installed!" | tr '[:lower:]' '[:upper:]' else @@ -337,8 +344,6 @@ while [ -n "$1" ]; do else echo " 💀 ERROR: the file \"$arg\" does NOT exist" fi - elif test -f "$AMPATH/neodb"; then - _install_from_third_party_repo elif curl --output /dev/null --silent --head --fail "$APPSDB"/"$arg" 1>/dev/null; then _install_normally else @@ -351,8 +356,8 @@ while [ -n "$1" ]; do done if [ -f "$AMCACHEDIR"/installed ]; then echo "============================================================================" - echo -e "\n ${LightBlue}END OF ALL INSTALLATION PROCESSES\n\033[0m" - echo -e " The following new programs have been installed:\n" + printf "\n ${LightBlue}END OF ALL INSTALLATION PROCESSES\n\033[0m" + printf "\n The following new programs have been installed:\n\n" grep -w -v "◆ am" 0<"$AMCACHEDIR"/installed echo "" echo "============================================================================" @@ -370,17 +375,17 @@ while [ -n "$1" ]; do fi mkdir -p "$CACHEDIR/extra" rm -f "$CACHEDIR/extra/$3" - wget -q "$AMREPO"/templates/AM-SAMPLE-AppImage -O "$CACHEDIR/extra/$3" || exit 1 + curl -Ls "$AMREPO"/templates/AM-SAMPLE-AppImage > "$CACHEDIR/extra/$3" || exit 1 sed -i "s#APP=SAMPLE#APP=$3#g" "$CACHEDIR/extra/$3" USER_PROJECT=$(echo "$2" | sed 's#https://github.com/##g' | cut -f1,2 -d'/') API_GITHUB_REPO="https://api.github.com/repos/$USER_PROJECT/releases" sed -i "s#REPLACETHIS#$USER_PROJECT#g" "$CACHEDIR/extra/$3" q="'" - if [ "$arch" = "x86_64" ]; then + if [ "$ARCH" = "x86_64" ]; then FILTER=' | grep -vi "i386\\|i686\\|i586\\|i486\\|aarch64\\|arm64\\|armv7l"' - elif [ "$arch" = "i686" ]; then + elif [ "$ARCH" = "i686" ]; then FILTER=' | grep -ie "i386\\|i686\\|i586\\|i486" ' - elif [ "$arch" = "aarch64" ]; then + elif [ "$ARCH" = "aarch64" ]; then FILTER=' | grep -ie "aarch64\\|arm64" ' fi FUNCTION='curl -Ls '"$API_GITHUB_REPO"' | sed '"$q"'s/[()",{} ]/\\n/g'"$q"' | grep -oi "https.*mage$"'"$FILTER"' | head -1' @@ -390,7 +395,4 @@ while [ -n "$1" ]; do "$AMCLIPATH" -i "$CACHEDIR/extra/$3" exit 1 ;; - esac -done - -shift +esac diff --git a/modules/launcher.am b/modules/launcher.am deleted file mode 100644 index 838d006e6..000000000 --- a/modules/launcher.am +++ /dev/null @@ -1,91 +0,0 @@ -#!/bin/sh - -######################################################################################################################### -# THIS MODULE HELPS YOU INTEGRATE LOCAL APPIMAGES BY DRAG/DROP THEM INTO THE TERMINAL, LIKE ANY COMMON APPIMAGE ASSISTANT -######################################################################################################################### - -_launcher_appimage_extract() { - "$arg" --appimage-extract share/icons/*/*/* 1>/dev/null - "$arg" --appimage-extract usr/share/icons/*/*/* 1>/dev/null - "$arg" --appimage-extract share/icons/*/*/*/* 1>/dev/null - "$arg" --appimage-extract usr/share/icons/*/*/*/* 1>/dev/null - "$arg" --appimage-extract *.svg 1>/dev/null - "$arg" --appimage-extract *.png 1>/dev/null - "$arg" --appimage-extract *.desktop 1>/dev/null - "$arg" --appimage-extract share/applications/*.desktop 1>/dev/null - "$arg" --appimage-extract usr/share/applications/*.desktop 1>/dev/null -} - -_launcher_appimage_integration() { - printf "[Desktop Entry]\nVersion=1.0\nType=Application\nTerminal=false\nStartupNotify=true\nExec=%s\n" "$arg %U" > ./"$appimage".desktop - cat ./squashfs-root/*.desktop | grep "^Name=" | head -1 >> ./"$appimage".desktop - cat ./squashfs-root/*.desktop | grep -F '^Name[' >> ./"$appimage".desktop - cat ./squashfs-root/*.desktop | grep "Categories=" >> ./"$appimage".desktop - cat ./squashfs-root/*.desktop | grep "Comment=" | head -1 >> ./"$appimage".desktop - cat ./squashfs-root/*.desktop | grep -F 'Comment[' >> ./"$appimage".desktop - cat ./squashfs-root/*.desktop | grep "Icon=" | head -1 >> ./"$appimage".desktop - cat ./squashfs-root/*.desktop | grep "MimeType=" | head -1 >> ./"$appimage".desktop - uniq ./"$appimage".desktop > ./"$appimage"-1.desktop && mv ./"$appimage"-1.desktop ./"$appimage".desktop - mv ./"$appimage".desktop "$DATADIR"/applications/AppImages/"$appimage".desktop 2>/dev/null - mv ./squashfs-root/*.png "$DATADIR"/icons/ 2>/dev/null - mv ./squashfs-root/*.svg "$DATADIR"/icons/ 2>/dev/null - share_dirs="usr/share share" - size_dirs="0x0 22x22 24x24 32x32 48x48 64x64 128x128 256x256 512x512" - for share in $share_dirs; do - for sizes in $size_dirs; do - mv ./squashfs-root/"${share}"/icons/hicolor/"${sizes}"/apps/*.png "$DATADIR"/icons/ 2>/dev/null - done - mv ./squashfs-root/"${share}"/icons/hicolor/scalable/apps/*.svg "$DATADIR"/icons/ 2>/dev/null - mv ./squashfs-root/"${share}"/pixmaps/*.png "$DATADIR"/icons/ 2>/dev/null - done - rm -Rf ./squashfs-root -} - -_launcher_appimage_bin() { - mkdir -p "$HOME"/.local/bin - _check_if_home_local_bin_is_not_in_path - read -r -p " Write a custom command to launch the app, or leave blank: " response - if [ -z "$response" ]; then - appimage_cmd=$(echo "$appimage" | tr '[:upper:]' '[:lower:]') - if ! echo "$appimage" | grep -q -i ".appimage"; then - printf '#!/bin/sh\n%s' "$arg" >> "$HOME"/.local/bin/"$appimage_cmd".appimage - chmod a+x "$HOME"/.local/bin/"$appimage_cmd".appimage - echo " New command: \"$appimage_cmd.appimage\" in ~/.local/bin" - else - printf '#!/bin/sh\n%s' "$arg" >> "$HOME"/.local/bin/"$appimage_cmd" - chmod a+x "$HOME"/.local/bin/"$appimage_cmd" - echo " New command: \"$appimage_cmd\" in ~/.local/bin" - fi - elif command -v "$response" 1>/dev/null; then - echo " ERROR: the \"$response\" command alredy exists, retry!" - else - ln -s "$arg" "$HOME"/.local/bin/"$response" - fi -} - -_launcher(){ - if ! test -f "$arg"; then - echo " ERROR: \"$arg\" not found" - elif ! strings -d "$arg" 2>/dev/null | grep -F -q 'if you run it with the --appimage-extract option'; then - echo " ERROR: \"$arg\" is NOT an AppImage" - else - printf " ◆ File: %s\n" "$arg" - appimage=$(basename -- "$arg") - mkdir -p "$DATADIR"/applications/AppImages - mkdir -p "$DATADIR"/icons - chmod a+x "$arg" - cd "$(dirname "$arg")" || return - - _launcher_appimage_extract 2>/dev/null - _launcher_appimage_integration 2>/dev/null - _launcher_appimage_bin - fi -} - -[ -z "$2" ] && echo " USAGE: $AMCLI $1 [ARGUMENT]" && exit 1 -ARGS="$(echo "$@" | cut -f2- -d ' ')" -for arg in $ARGS; do - echo "---------------------------------------------------------------------" - _launcher -done -echo "---------------------------------------------------------------------" diff --git a/modules/management.am b/modules/management.am index f4e84062b..7fece24a1 100644 --- a/modules/management.am +++ b/modules/management.am @@ -2,11 +2,10 @@ ############################################################################################## # THIS MODULE INCLUDES ALL THE ACTIONS INTENDED TO MANAGE THE APPS INSTALLED FROM THE DATABASE -# OPTIONS: BACKUP/RESTORE, DOWNGRADE, LOCK/UNLOCK, NOLIBFUSE, REMOVE +# AND ONE OPTION IS FOR LOCAL APPIMAGES INSTEAD +# OPTIONS: BACKUP/RESTORE, DOWNGRADE, LAUNCHER, LOCK/UNLOCK, NOLIBFUSE, REMOVE ############################################################################################## -SUDOCMD="$SUDOCOMMAND" - # BACKUP function _backup() { if [ ! -f "$APPSPATH"/"$2"/remove ]; then @@ -106,6 +105,85 @@ function _downgrade() { echo "ROLLBACK SUCCESSFUL!" } +# LAUNCHER +function _launcher_appimage_extract() { + "$arg" --appimage-extract share/icons/*/*/* 1>/dev/null + "$arg" --appimage-extract usr/share/icons/*/*/* 1>/dev/null + "$arg" --appimage-extract share/icons/*/*/*/* 1>/dev/null + "$arg" --appimage-extract usr/share/icons/*/*/*/* 1>/dev/null + "$arg" --appimage-extract *.svg 1>/dev/null + "$arg" --appimage-extract *.png 1>/dev/null + "$arg" --appimage-extract *.desktop 1>/dev/null + "$arg" --appimage-extract share/applications/*.desktop 1>/dev/null + "$arg" --appimage-extract usr/share/applications/*.desktop 1>/dev/null +} + +function _launcher_appimage_integration() { + printf "[Desktop Entry]\nVersion=1.0\nType=Application\nTerminal=false\nStartupNotify=true\nExec=%s\n" "$arg %U" > ./"$appimage".desktop + cat ./squashfs-root/*.desktop | grep "^Name=" | head -1 >> ./"$appimage".desktop + cat ./squashfs-root/*.desktop | grep -F '^Name[' >> ./"$appimage".desktop + cat ./squashfs-root/*.desktop | grep "Categories=" >> ./"$appimage".desktop + cat ./squashfs-root/*.desktop | grep "Comment=" | head -1 >> ./"$appimage".desktop + cat ./squashfs-root/*.desktop | grep -F 'Comment[' >> ./"$appimage".desktop + cat ./squashfs-root/*.desktop | grep "Icon=" | head -1 >> ./"$appimage".desktop + cat ./squashfs-root/*.desktop | grep "MimeType=" | head -1 >> ./"$appimage".desktop + uniq ./"$appimage".desktop > ./"$appimage"-1.desktop && mv ./"$appimage"-1.desktop ./"$appimage".desktop + mv ./"$appimage".desktop "$DATADIR"/applications/AppImages/"$appimage".desktop 2>/dev/null + mv ./squashfs-root/*.png "$DATADIR"/icons/ 2>/dev/null + mv ./squashfs-root/*.svg "$DATADIR"/icons/ 2>/dev/null + share_dirs="usr/share share" + size_dirs="0x0 22x22 24x24 32x32 48x48 64x64 128x128 256x256 512x512" + for share in $share_dirs; do + for sizes in $size_dirs; do + mv ./squashfs-root/"${share}"/icons/hicolor/"${sizes}"/apps/*.png "$DATADIR"/icons/ 2>/dev/null + done + mv ./squashfs-root/"${share}"/icons/hicolor/scalable/apps/*.svg "$DATADIR"/icons/ 2>/dev/null + mv ./squashfs-root/"${share}"/pixmaps/*.png "$DATADIR"/icons/ 2>/dev/null + done + rm -Rf ./squashfs-root +} + +function _launcher_appimage_bin() { + mkdir -p "$HOME"/.local/bin + _check_if_home_local_bin_is_not_in_path + read -r -p " Write a custom command to launch the app, or leave blank: " response + if [ -z "$response" ]; then + appimage_cmd=$(echo "$appimage" | tr '[:upper:]' '[:lower:]') + if ! echo "$appimage" | grep -q -i ".appimage"; then + printf '#!/bin/sh\n%s' "$arg" >> "$HOME"/.local/bin/"$appimage_cmd".appimage + chmod a+x "$HOME"/.local/bin/"$appimage_cmd".appimage + echo " New command: \"$appimage_cmd.appimage\" in ~/.local/bin" + else + printf '#!/bin/sh\n%s' "$arg" >> "$HOME"/.local/bin/"$appimage_cmd" + chmod a+x "$HOME"/.local/bin/"$appimage_cmd" + echo " New command: \"$appimage_cmd\" in ~/.local/bin" + fi + elif command -v "$response" 1>/dev/null; then + echo " ERROR: the \"$response\" command alredy exists, retry!" + else + ln -s "$arg" "$HOME"/.local/bin/"$response" + fi +} + +function _launcher(){ + if ! test -f "$arg"; then + echo " ERROR: \"$arg\" not found" + elif ! strings -d "$arg" 2>/dev/null | grep -F -q 'if you run it with the --appimage-extract option'; then + echo " ERROR: \"$arg\" is NOT an AppImage" + else + printf " ◆ File: %s\n" "$arg" + appimage=$(basename -- "$arg") + mkdir -p "$DATADIR"/applications/AppImages + mkdir -p "$DATADIR"/icons + chmod a+x "$arg" + cd "$(dirname "$arg")" || return + + _launcher_appimage_extract 2>/dev/null + _launcher_appimage_integration 2>/dev/null + _launcher_appimage_bin + fi +} + # LOCK/UNLOCK function _lock() { if [ ! -f "$APPSPATH"/"$2"/AM-updater ]; then @@ -256,6 +334,16 @@ case "$1" in done ;; + 'launcher'|'--launcher') + # Place local AppImages into the menu by dragging and dropping them into the terminal + ARGS="$(echo "$@" | cut -f2- -d ' ')" + for arg in $ARGS; do + echo "---------------------------------------------------------------------" + _launcher "${@}" + done + echo "---------------------------------------------------------------------" + ;; + 'lock') # Lock the version of an installed app ARGS="$(echo "$@" | cut -f2- -d ' ')" diff --git a/modules/sandboxes.am b/modules/sandboxes.am index fc4bbf5e8..95b12e631 100644 --- a/modules/sandboxes.am +++ b/modules/sandboxes.am @@ -4,8 +4,6 @@ # THIS MODULE INCLUDES ALL ACTIONS INTENDED TO ISOLATE DOTFILES OR CONTAINERIZE INSTALLED APPIMAGES ################################################################################################### -SUDOCMD="$SUDOCOMMAND" - # Get xdg variables for _configure_dirs_access for DIR in DESKTOP DOCUMENTS DOWNLOAD GAMES MUSIC PICTURES VIDEOS; do eval XDG_DIR="$(xdg-user-dir $DIR 2>/dev/null)" @@ -21,47 +19,47 @@ PICTURES="$(echo "${PICTURES:-~/Pictures}" | sed "s|$HOME|~|g")" VIDEOS="$(echo "${VIDEOS:-~/Videos}" | sed "s|$HOME|~|g")" _check_appimage() { - TARGET="$(command -v "$2")" - APPIMAGEDIR="$APPSPATH/$2" - APPIMAGE="$APPIMAGEDIR/$2" + TARGET="$(command -v "$1")" + APPIMAGEDIR="$APPSPATH/$1" + APPIMAGE="$APPIMAGEDIR/$1" if [ ! -d "$APPIMAGEDIR" ]; then - echo " ERROR: \"$2\" is not installed" + echo " ERROR: \"$1\" is not installed" return 1 elif ! strings -d "$APPIMAGE" | grep -- '--appimage-extract' 1>/dev/null; then - echo " ERROR: \"$2\" is NOT an AppImage" + echo " ERROR: \"$1\" is NOT an AppImage" return 1 fi } _home() { if [ -d "$APPIMAGE.home" ]; then - echo " ERROR: \"$2\" already contains a home dir" + echo " ERROR: \"$1\" already contains a home dir" return 1 fi mkdir "$APPIMAGE.home" || return 1 - echo " \$HOME set to \"$APPIMAGE.home\" for \"$2\"" + echo " \$HOME set to \"$APPIMAGE.home\" for \"$1\"" } _config() { if [ -d "$APPIMAGE.config" ]; then - echo " ERROR: \"$2\" already contains a config dir" + echo " ERROR: \"$1\" already contains a config dir" return 1 fi mkdir "$APPIMAGE.config" || return 1 - echo " \$XDG_CONFIG_HOME set to \"$APPIMAGE.config\" for \"$2\"" + echo " \$XDG_CONFIG_HOME set to \"$APPIMAGE.config\" for \"$1\"" } _disable_sandbox() { - TARGET="$(command -v "$2")" + TARGET="$(command -v "$1")" if ! grep "aisap-am sandboxing script" "$TARGET" >/dev/null 2>&1; then echo " ERROR: Not a sandboxed AppImage, aborting" return 1 fi - "$2" --disable-sandbox + "$1" --disable-sandbox } _check_aisap() { - if [ "$2" = "aisap" ]; then + if [ "$1" = "aisap" ]; then echo " Error: You can't sandbox aisap" return 1 elif ! command -v aisap 1>/dev/null; then @@ -76,16 +74,14 @@ _check_aisap() { echo " aisap installed successfully!" fi if grep "aisap-am" "$TARGET" >/dev/null 2>&1; then - echo " $2 is already sandboxed!" + echo " $1 is already sandboxed!" return 1 fi } _generate_sandbox_script() { - TMPFILE="$AMCACHEDIR/$2.tmp" - rm -f "$TMPFILE" 2>/dev/null - printf '\n%s\n' " Making aisap sandbox script for \"$2\"..." - cat <<-"HEREDOC" >> "$TMPFILE" + printf '\n%s\n' " Making aisap sandbox script for \"$1\"..." + tmpscript="$(cat <<-'HEREDOC' #!/bin/sh # aisap-am sandboxing script, aisap: https://github.com/mgord9518/aisap # Thanks a lot to mgord9518 for making aisap! @@ -110,9 +106,9 @@ _generate_sandbox_script() { DBUS="$(ls /tmp/dbus* 2>/dev/null | head -1)" # get xdg user dirs, unset if var = $HOME for DIR in DESKTOP DOCUMENTS DOWNLOAD GAMES MUSIC PICTURES VIDEOS; do - eval XDG_DIR="$(xdg-user-dir $DIR 2>/dev/null)" - [ "$XDG_DIR" = "$HOME" ] || [ "$XDG_DIR" = "$HOME/" ] && XDG_DIR="" - eval $DIR="$XDG_DIR" + eval XDG_DIR="$(xdg-user-dir $DIR 2>/dev/null)" + [ "$XDG_DIR" = "$HOME" ] || [ "$XDG_DIR" = "$HOME/" ] && XDG_DIR="" + eval $DIR="$XDG_DIR" done # Use default location if var is not set DESKTOP="${DESKTOP:-~/Desktop}" @@ -176,6 +172,7 @@ _generate_sandbox_script() { --add-device dri -- \ "$APPEXEC" "$@" HEREDOC + )" } _configure_dirs_access() { @@ -187,18 +184,18 @@ _configure_dirs_access() { printf '\033[36m' for DIR in DESKTOP DOCUMENTS DOWNLOAD GAMES MUSIC PICTURES VIDEOS; do eval XDG_DIR=\$$DIR - read -p " Allow $2 access to \"$XDG_DIR\"? (y/N) " yn + read -p " Allow $1 access to \"$XDG_DIR\"? (y/N) " yn if echo "$yn" | grep -i '^y' >/dev/null 2>&1; then - sed -i "s|--rm-file \"\$$DIR\"|--add-file \"\$$DIR\":rw|g" \ - "$TMPFILE" || return 1 + tmpscript=$(echo "$tmpscript" \ + | sed "s#--rm-file \"\$$DIR\"#--add-file \"\$$DIR\":rw#g" ) fi done sleep 0.5 printf '\033[31m' - read -p " Allow $2 access to a specific directory? (y/N) " yn + read -p " Allow $1 access to a specific directory? (y/N) " yn if echo "$yn" | grep -i '^y' >/dev/null 2>&1; then echo " WARNING: Giving access to all of $HOME or / and similar is not safe" - echo " Also aisap might not let $2 start when such paths are given" + echo " Also aisap might not let $1 start when such paths are given" printf '\033[33m%s\n' " Type the path to the directory" read -p " Example: /media/external-drive or ~/Backups: " NEWDIR case "$NEWDIR" in @@ -215,65 +212,66 @@ _configure_dirs_access() { ;; esac echo " Giving access to \"$NEWDIR\"..." - sed -i "s|--rm-file /NOPATH|--add-file \"$NEWDIR\":rw|g" \ - "$TMPFILE" || return 1 + tmpscript=$(echo "$tmpscript" \ + | sed "s#--rm-file /NOPATH#--add-file \"$NEWDIR\":rw#g") fi printf '\n\033[32m%s\n' " User directories access configured successfully!" } _install_sandbox_script() { - chmod a+x "$TMPFILE" || return 1 - sed -i "s|DUMMY|$APPIMAGE|g; s|SUDO|$SUDOCMD|g" "$TMPFILE" || return 1 + tmpscript=$(echo "$tmpscript" | sed "s#DUMMY#$APPIMAGE#g; s#SUDO#$SUDOCMD#g") # Remove exec permission from AppImage and its updater for better safety™ - chmod a-x "$APPIMAGE" && $SUDOCMD rm -f "$TARGET" || return 1 + chmod a-x "$APPIMAGE" || return 1 sed -i 's|chmod a+x|chmod a-x|g' "$APPIMAGEDIR/AM-updater" || return 1 # Install the script - $SUDOCMD mv "$TMPFILE" "$TARGET" || return 1 + $SUDOCMD rm -f "$TARGET" || return 1 + echo "$tmpscript" | $SUDOCMD tee "$TARGET" >/dev/null 2>&1 || return 1 + $SUDOCMD chmod a+x "$TARGET" SANDBOXDIR="${SANDBOXDIR:-$HOME/.local/am-sandboxes}" - printf '\033[32m\n%s\n\033[0m' " \"$2\" successfully sandboxed!" - printf '\n%s\n' " $2 will be sandboxed in \"$SANDBOXDIR\"" + printf '\033[32m\n%s\n\033[0m' " \"$1\" successfully sandboxed!" + printf '\n%s\n' " $1 will be sandboxed in \"$SANDBOXDIR\"" printf '%s\n\n' " once launched" printf '%s\n' ' Set the $SANDBOXDIR env variable to move the location' printf '\n%s' ' Use ' printf '\033[33m%s' '--disable-sandbox' printf '\033[0m%s\033[33m\n' " to revert the changes, in this case that is:" - printf '\033[33m%s\033[0m' " $2 --disable-sandbox" - printf '%s\033[33m%s\n\033[0m\n' " or " "$AMCLI --disable-sandbox $2" + printf '\033[33m%s\033[0m' " $1 --disable-sandbox" + printf '%s\033[33m%s\n\033[0m\n' " or " "$AMCLI --disable-sandbox $1" } # Main logic [ -z "$2" ] && echo " USAGE: $AMCLI $1 [ARGUMENT]" && exit 1 case "$1" in - '--sandbox') - ARGS="$(echo "$@" | cut -f2- -d ' ')" - for arg in $ARGS; do + '--sandbox') + shift + for arg in ${@}; do _check_appimage "${@}" && _check_aisap "${@}" \ && _generate_sandbox_script "${@}" \ && _configure_dirs_access "${@}" \ && _install_sandbox_script "${@}" shift done - ;; + ;; - '--disable-sandbox') - ARGS="$(echo "$@" | cut -f2- -d ' ')" - for arg in $ARGS; do + '--disable-sandbox') + shift + for arg in ${@}; do _disable_sandbox "${@}" shift done ;; - '-H'|'--home') - ARGS="$(echo "$@" | cut -f2- -d ' ')" - for arg in $ARGS; do + '-H'|'--home') + shift + for arg in ${@}; do _check_appimage "${@}" && _home "${@}" shift done ;; - '-C'|'--config') - ARGS="$(echo "$@" | cut -f2- -d ' ')" - for arg in $ARGS; do + '-C'|'--config') + shift + for arg in ${@}; do _check_appimage "${@}" && _config "${@}" shift done diff --git a/modules/sync.am b/modules/sync.am deleted file mode 100644 index 6d89b9b81..000000000 --- a/modules/sync.am +++ /dev/null @@ -1,94 +0,0 @@ -#!/usr/bin/env bash - -function _sync_installation_scripts() { - echo "-----------------------------------------------------------------------------" - echo -e " Checking for changes of the installation scripts in the online database..." - rm -R -f "$AMPATH"/.cache/sync-args && echo "" >> "$AMPATH"/.cache/sync-args - cd "$APPSPATH" && find -name 'AM-updater' -printf "%h\n" 2>/dev/null | sort -u | cut -c 3- > "$AMPATH"/.cache/sync-args - ARGS=$(cat "$AMPATH"/.cache/sync-args) - - for arg in $ARGS; do - mkdir -p "$APPSPATH/$arg/.am-installer" - if test -f "$APPSPATH/$arg/.am-installer/$arg"; then - CURRENT=$(cat "$APPSPATH"/$arg/.am-installer/$arg) - SOURCE=$(wget -q "$APPSDB"/$arg -O -) - if [ "$CURRENT" == "$SOURCE" ]; then - echo -ne "\r" 2> /dev/null - else - echo -e " ◆ Changed https://github.com/ivan-hc/AM/blob/main/programs/$arch/$arg" - fi - else - if curl --output /dev/null --silent --head --fail "$APPSDB"/$arg 1>/dev/null; then - echo -e " ◆ No installation script for $arg, downloading one..." - mkdir -p "$APPSPATH/$arg/.am-installer" - wget -q "$APPSDB/$arg" -O "$APPSPATH/$arg/.am-installer/$arg" - fi - fi - done -} - -function _sync_modules() { - echo "-----------------------------------------------------------------------------" - echo -e " Check for updates in modules..." - MODULES=$(curl -Ls $HeaderAuthWithGITPAT https://api.github.com/repos/ivan-hc/AM/contents/modules?ref="$AMBRANCH" | sed 's/[()",{}]/ /g; s/ /\n/g' | grep -o 'https.*raw.*modules.*am$') - for v in $MODULES; do - cd "$AMPATH"/modules || return - MODULENAME=$(echo "$v" | sed 's:.*/::') - if ! test -f ./$MODULENAME; then - echo " ◆ Downloading $MODULENAME (not previously installed)..." - wget -q "$v" - chmod a+x ./$MODULENAME - fi - CURRENT=$(cat ./$MODULENAME) - SOURCE=$(wget -q "$v" -O -) - if [ "$CURRENT" == "$SOURCE" ]; then - echo -ne "\r" 2> /dev/null - else - echo " ◆ Updating $MODULENAME..." - mkdir tmp - cd tmp || return - wget -q "$v" - cd .. - mv tmp/*.am ./ - chmod a+x ./*.am - rmdir tmp - fi - done -} - -function _sync_amcli() { - echo "-----------------------------------------------------------------------------" - _completion_lists - rm -f /opt/am/appman - if [ "$AMCLIPATH" == /opt/am/appman ] 2>/dev/null; then - AMCLIPATH="/opt/am/APP-MANAGER" - CURRENT_AM_VERSION=$("$AMCLIPATH" -v) - else - CURRENT_AM_VERSION=$("$AMCLIPATH" -v) - fi - echo -ne '\n ◆ SYNCHRONIZING "'"$(echo "$AMCLI" | tr a-z A-Z)"'" VERSION '"$CURRENT_AM_VERSION"'...\r'; sleep 1 - rm -R -f "$AMPATH"/.cache/* 1>/dev/null; cd "$AMPATH"/.cache || return - if [ "$AMCLI" == am ] 2>/dev/null; then - wget -q "$AMREPO"/APP-MANAGER && chmod a+x ./APP-MANAGER && chmod 777 ./APP-MANAGER - cd .. - echo y | mv "$AMPATH"/.cache/APP-MANAGER /opt/am/APP-MANAGER - else - wget -q "$AMREPO"/APP-MANAGER -O appman && chmod a+x ./"$AMCLI" - cd .. - echo y | mv "$AMPATH"/.cache/"$AMCLI" "$AMCLIPATH" - fi - if [ ! "$CURRENT_AM_VERSION" == "$("$AMCLIPATH" -v)" ] ; then - echo -ne ' A new release of "'"$(echo "$AMCLI" | tr a-z A-Z)"'" is available, please wait...\r' - echo -e ' ◆ "'"$(echo "$AMCLI" | tr a-z A-Z)"'" IS NOW UPDATED TO THE BRAND NEW '"$("$AMCLIPATH" -v)"' VERSION! \n\n Replacement of version '"$CURRENT_AM_VERSION"' currently in use, COMPLETED!' - echo -e "\n See https://github.com/ivan-hc/AM/commits/main\n" - else - echo -e ' ◆ "'"$(echo "$AMCLI" | tr a-z A-Z)"'" IS ALREADY UPDATED, CURRENT VERSION '"$CURRENT_AM_VERSION"'' - echo -e "\n See https://github.com/ivan-hc/AM/commits/$AMBRANCH\n" - fi -} - -if [[ "$AMREPO" = *://* ]]; then - _sync_installation_scripts - _sync_modules - _sync_amcli -fi diff --git a/modules/update.am b/modules/update.am deleted file mode 100644 index 48c4c0cd8..000000000 --- a/modules/update.am +++ /dev/null @@ -1,138 +0,0 @@ -#!/usr/bin/env bash - -# Function to update GitHub API key in AM-updater files -function update_github_api() { - local ghapikey_file="$AMPATH/ghapikey.txt" - if [[ -f "$ghapikey_file" ]]; then - ghapikey=$(<"$ghapikey_file") - local updater_files=("$APPSPATH"/*/AM-updater) # Assuming AM-updater is one level deeper - for f in "${updater_files[@]}"; do - if [[ -f "$f" ]] && grep -q "https://api.github.com" "$f"; then - # Check if the file already contains a valid API key - if ! grep -qE "(gh[ps]_[a-zA-Z0-9]{36}|github_pat_[a-zA-Z0-9]{22}_[a-zA-Z0-9]{59})" "$f"; then - # Insert HeaderAuthWithGITPAT before the GitHub API URL - sed -i "s#https://api.github.com#$HeaderAuthWithGITPAT https://api.github.com#g" "$f" - else - # Replace existing API key with the one from ghapikey.txt - sed -i "s#\(gh[ps]_[a-zA-Z0-9]\{36\}\|github_pat_[a-zA-Z0-9]\{22\}_[a-zA-Z0-9]\{59\}\)#$ghapikey#g" "$f" - fi - fi - done - fi -} - -function _list_updatable_apps() { - _check_version - cd "$APPSPATH" && find -name 'AM-updater' -printf " %h\n" 2>/dev/null | sort -u | xargs -n 1 basename 2>/dev/null > "$AMPATH"/.cache/updatable-args - ARGS=$(cat "$AMPATH"/.cache/updatable-args) - for arg in $ARGS; do - app_version=$(cat "$AMPATH/.cache/version-args" | grep -w " ◆ $arg |" | sed 's:.*| ::') - echo " ◆ $arg $app_version" >> $AMPATH/.cache/updatable-args-list - done -} - -case "$1" in - '-U'|'-u'|'update') - # Call update_github_api function - update_github_api - - while [ -n "$1" ]; do - case $2 in - ''|'--apps') - rm -R -f "$AMPATH"/.cache/* - - _list_updatable_apps - - echo '-----------------------------------------------------------------------------' - echo -e ' "'"$(echo "$AMCLI" | tr a-z A-Z)"'" CAN MANAGE UPDATES FOR THE FOLLOWING PROGRAMS:\n' - if test -f "$AMPATH/.cache/updatable-args-list"; then - cat "$AMPATH/.cache/updatable-args-list" - else - echo " None" - fi - echo -e '\n All self-updatable programs are excluded'; sleep 0.1 - echo '-----------------------------------------------------------------------------' - echo ' >> START OF ALL PROCESSES <<' - echo '-----------------------------------------------------------------------------' - - for f in "$APPSPATH"/*/; do - cd $f 2>/dev/null && - if test -f ./AM-updater; then - APPNAME=$(echo "$(printf '%s\n' "${PWD##*/}")") - start=$(date +%s) && sh -x ./AM-updater > /dev/null 2>&1 | echo -ne ' Updating "'"$APPNAME"'"...\r' && end=$(date +%s) && - echo -e " ◆ $(echo "$APPNAME" | tr a-z A-Z) is updated, $(($end-$start)) seconds elapsed!" & - else - echo "" > /dev/null 2>&1 - fi - done - wait - - echo '-----------------------------------------------------------------------------' - - if test -f "$AMPATH"/.cache/updatable-args-list; then - mv "$AMPATH"/.cache/updatable-args-list "$AMPATH"/.cache/updatable-args-list-old - _list_updatable_apps - OLDVER="$AMPATH/.cache/updatable-args-list-old" - NEWVER="$AMPATH/.cache/updatable-args-list" - if cmp --silent -- "$NEWVER" "$OLDVER"; then - echo ' Nothing to do here!' - else - echo -e " The following apps have been updated:\n" - diff --new-line-format="" --unchanged-line-format="" "$NEWVER" "$OLDVER" - echo "" - fi - else - echo ' No apps to update here!' - fi - - rm -R -f $APPSPATH/*/tmp - if [ -z "$2" ]; then - echo "-----------------------------------------------------------------------------" - $AMCLIPATH -s - fi - echo '-----------------------------------------------------------------------------' - echo ' >> END OF ALL PROCESSES << ' - echo '-----------------------------------------------------------------------------' - sleep 0.2 - exit;; - *) - if test -f "$APPSPATH"/$2/AM-updater; then - start=$(date +%s); "$APPSPATH"/$2/AM-updater > /dev/null 2>&1 | echo -ne " UPDATING $(echo $2 | tr a-z A-Z)\r"; end=$(date +%s) - echo -e " ◆ $(echo $2 | tr a-z A-Z) is updated, $(($end-$start)) seconds elapsed!" && break - else - echo ' "'"$(echo "$AMCLI" | tr a-z A-Z)"'" CANNOT MANAGE UPDATES FOR "'"$(echo $2 | tr a-z A-Z)"'"' - UPDATERS=$(cd "$APPSPATH"/$2 2>/dev/null && find . -name "*update*" -print 2>/dev/null) - - if [ -n "$UPDATERS" ]; then - echo ' This program probably includes its own update system!' - fi - - exit - fi - esac - done - - shift - ;; - '--force-latest') - case $2 in - '') - echo " USAGE: $AMCLI $1 [ARGUMENT]"; exit - ;; - *) - if ! test -d "$APPSPATH"/$2; then - echo ' ERROR: "'$2'" is not installed, see "-f"' - elif ! test -f "$APPSPATH"/$2/AM-updater; then - echo ' ERROR: "'$AMCLI'" cannot manage updates for "'$2'"' - elif ! grep -q "api.github.com" "$APPSPATH"/$2/AM-updater; then - echo ' ERROR: "'$2'" source is not on Github' - elif ! grep -q "/releases | jq " "$APPSPATH"/$2/AM-updater; then - echo ' ERROR: "'$2'" does not redirect to a generic "releases"' - else - sed -i 's#/releases | jq #/releases/latest | jq #g' "$APPSPATH"/$2/AM-updater - $AMCLIPATH -u $2 - fi - ;; - esac - ;; -esac