/ APP-MANAGER
APP-MANAGER
1 #!/usr/bin/env bash 2 3 AMVERSION="9.4.2" 4 5 # Determine main repository and branch 6 AMREPO="https://raw.githubusercontent.com/ivan-hc/AM/main" 7 AMBRANCH=$(basename "$AMREPO") 8 MODULES_SOURCE="$AMREPO/modules" 9 10 # Determine the name of this script and its working directory 11 export REALDIR="$PWD" 12 DIR="$( cd "$( dirname "$0" )" && pwd )" 13 CLI=$(basename "$0") 14 15 # Determine system architecture and current user 16 ARCH="$(uname -m)" 17 [ "$ARCH" = "amd64" ] && ARCH=x86_64 18 export ARCH 19 20 # Fixes issue with less on bsd 21 if uname | grep -q "BSD\|DragonFly\|DynFi\|FreeNAS\|helloSystem\|OPNsense\|pfSense\|TrueNAS\|XigmaNAS"; then 22 TERM=xterm-clear 23 export TERM 24 fi 25 26 # XDG Variables 27 export BINDIR="${XDG_BIN_HOME:-$HOME/.local/bin}" 28 export DATADIR="${XDG_DATA_HOME:-$HOME/.local/share}" 29 export CONFIGDIR="${XDG_CONFIG_HOME:-$HOME/.config}" 30 export CACHEDIR="${XDG_CACHE_HOME:-$HOME/.cache}" 31 export APPMANCONFIG="$CONFIGDIR/appman" 32 APPMANCONFIG="$CONFIGDIR/appman" 33 SCRIPTDIR="${SCRIPTDIR:-$(xdg-user-dir DESKTOP 2>/dev/null)}" 34 [ -d "$SCRIPTDIR" ] || SCRIPTDIR="$PWD" 35 export SCRIPTDIR 36 37 # Colors 38 RED='\033[0;31m' 39 Gold='\033[0;33m' 40 Green='\033[0;32m' 41 LightBlue='\033[1;34m' 42 DIVIDING_LINE="-----------------------------------------------------------------------------" 43 44 # Prevent the use of "sudo" ("AM") 45 if [ -n "${SUDO_USER:-$DOAS_USER}" ]; then 46 printf "\n Please do not use \"sudo\" to execute \"%b\", try again.\n\n" "$CLI" 47 exit 1 48 fi 49 50 if ! sed --version 2>/dev/null | grep -qi "gnu"; then 51 NO_SED_I=true 52 fi 53 54 _create_cache_dir() { 55 AMCACHEDIR="$CACHEDIR/$AMCLI" 56 mkdir -p "$AMCACHEDIR" 57 } 58 59 _clean_amcachedir() { 60 [ "$AMCLI" = am ] && [ -d "$CACHEDIR"/am ] && rm -f "$CACHEDIR"/am/* 61 [ -d "$CACHEDIR"/appman ] && rm -f "$CACHEDIR"/appman/* 62 } 63 64 # Fit texts to an acceptable width 65 _fit() { 66 fold -sw 77 | sed 's/^/ /g' 67 } 68 69 # Makes "less" optional 70 less() { 71 if ! command less "$@" 2>/dev/null; then 72 while read -r line; do echo "$line"; done 73 echo "Install 'less' if you want to scroll this list" 74 fi 75 } 76 77 # Force usage of a GNU implementation of "sed" 78 sed() { 79 if [ "$NO_SED_I" = true ] && [ "$1" = '-i' ]; then 80 if command -v gsed >/dev/null 2>&1; then 81 command gsed "$@" 82 else 83 shift 84 tmpsedYYY="$(command sed "$@" 2>/dev/null)" 85 while [ "$#" -gt 1 ]; do shift; done 86 if [ -n "$tmpsedYYY" ] && [ -f "$1" ]; then 87 echo "$tmpsedYYY" > "$1" 88 unset tmpsedYYY 89 else 90 >&2 echo " π ERROR: Your version of sed does not support '-i' flag" 91 >&2 echo " without extension, we tried to workaround and failed" 92 >&2 echo " Please install gsed" 93 unset tmpsedYYY 94 return 1 95 fi 96 fi 97 else 98 command sed "$@" 99 fi 100 } 101 102 ################################################################################ 103 # AM/APPMAN 104 ################################################################################ 105 106 # "APPMAN" CORE VARIABLES AND FUNCTIONS 107 APPMAN_SETUP_MSG="Before proceeding with any task, where do you want to install apps? 108 109 SYNTAX: /FULLPATH/TO/DIRNAME 110 EXAMPLE: $HOME/My-apps 111 112 NOTE: Any spaces in the path will be replaced for dashes 113 NOTE: If no input is given then \"~/Applications\" will be used as default 114 115 if you wish to later change the location, first remove all the programs and then edit the \"$APPMANCONFIG/appman-config\" file." 116 117 _appman_check() { 118 if [ ! -f "$APPMANCONFIG"/appman-config ]; then 119 echo "$DIVIDING_LINE" 120 [ "$AMCLI" = am ] && echo ">>> Configure AppMan" || echo ">>> Thank you for choosing AppMan!" 121 echo "$DIVIDING_LINE" 122 echo "$APPMAN_SETUP_MSG" | _fit 123 echo "$DIVIDING_LINE" 124 read -r -ep " Write the path or just press enter to use default:$(printf "\n\n ")" location 125 location="$(echo "$location" | sed 's/[ \t]/-/g; s|^\./||' 2>/dev/null)" 126 [ -z "$location" ] && location="$HOME/Applications" 127 if ! echo "$location" | grep "^/" >/dev/null 2>&1; then 128 location="$HOME/$location" 129 fi 130 if echo "$location" | grep "$BINDIR" >/dev/null 2>&1; then 131 echo "$DIVIDING_LINE" 132 echo " π ERROR, you can't install applications in \"$BINDIR\"" 133 echo " $BINDIR is normally used for executables, Please choose a different path and retry!" 134 echo "$DIVIDING_LINE" 135 exit 1 136 elif ! mkdir -p "$location" 2>/dev/null || [ ! -w "$location" ]; then 137 echo " π ERROR: You don't have write access to $location or it is invalid" 138 exit 1 139 fi 140 mkdir -p "$APPMANCONFIG" || exit 1 141 echo "${location%/}" > "$APPMANCONFIG"/appman-config || exit 1 142 echo "$DIVIDING_LINE" 143 echo " You are ready! Start installing your favorite apps locally!" 144 echo " All apps will be installed in $location" 145 echo " In case of problems, use the option \"-h\"." 146 echo "$DIVIDING_LINE" 147 fi 148 } 149 150 _appman() { 151 _appman_check 152 if ! grep -q "^/" "$APPMANCONFIG"/appman-config; then 153 APPSDIR="$HOME/$(head -1 "$APPMANCONFIG"/appman-config 2>/dev/null)" 154 else 155 APPSDIR="$(head -1 "$APPMANCONFIG"/appman-config 2>/dev/null)" 156 fi 157 [ -n "$APPSDIR" ] && mkdir -p "$APPSDIR"/appman || exit 1 158 mkdir -p "$BINDIR" "$DATADIR"/applications "$DATADIR"/icons || exit 1 159 AMCLI="appman" 160 AMCLIPATH="$DIR/$AMCLI" 161 SUDOCMD="" 162 APPSPATH="$APPSDIR" 163 AMPATH="$APPSDIR/$AMCLI" 164 _create_cache_dir 165 if [ ! -w "$APPSPATH" ]; then 166 echo "ERROR: You don't have write access to $APPSPATH" | _fit 167 exit 1 168 elif ! echo "$PATH" | grep "$BINDIR" >/dev/null 2>&1; then 169 echo "$DIVIDING_LINE" 170 printf "%b β οΈ WARNING\033[0m: \"%b%b\033[0m\" is not in PATH, local apps may not run.\n" "${RED}" "${LightBlue}" "$BINDIR" 171 fi 172 MODULES_PATH="$AMPATH/modules" 173 mkdir -p "$MODULES_PATH" || exit 1 174 } 175 176 # "AM" CORE VARIABLES 177 _am() { 178 AMCLI="am" 179 AMCLIPATH="$AMCLI" 180 if command -v sudo >/dev/null 2>&1; then 181 export SUDOCMD="sudo" 182 elif command -v doas >/dev/null 2>&1; then 183 export SUDOCMD="doas" 184 else 185 echo 'ERROR: No sudo or doas found' 186 exit 1 187 fi 188 APPSPATH="/opt" 189 AMPATH="$APPSPATH/$AMCLI" 190 _create_cache_dir 191 MODULES_PATH="$AMPATH/modules" 192 } 193 194 # DETERMINE WHEN TO USE "AM" OR "APPMAN" 195 if [ "$(realpath "$0")" = "/opt/am/APP-MANAGER" ]; then 196 _am 197 mkdir -p "$MODULES_PATH" || exit 1 198 elif [ "$(realpath "$0")" = "/usr/bin/am" ]; then 199 _am 200 AMPATH="$AMCACHEDIR" 201 MODULES_PATH="/usr/lib/am/modules" 202 else 203 _appman 204 fi 205 206 _detect_appman_apps() { 207 [ -f "$APPMANCONFIG/appman-config" ] && APPMAN_APPSPATH=$(<"$APPMANCONFIG/appman-config") 208 if ! echo "$APPMAN_APPSPATH" | grep -q "^/"; then 209 [ -f "$APPMANCONFIG/appman-config" ] && APPMAN_APPSPATH="$HOME/$(<"$APPMANCONFIG/appman-config")" 210 fi 211 } 212 213 _determine_args() { 214 ARGPATHS=$(find "$APPSPATH" -maxdepth 2 -name 'remove' -print 2>/dev/null | sort -u | sed 's|/remove||g') 215 ARGS=$(echo "$ARGPATHS" | xargs -n 1 basename 2>/dev/null) 216 if [ "$AMCLI" = am ]; then 217 _detect_appman_apps 218 if [ -d "$APPMAN_APPSPATH" ]; then 219 APPMAN_PATHS=$(find "$APPMAN_APPSPATH" -maxdepth 2 -name 'remove' -print 2>/dev/null | sort -u | sed 's|/remove||g') 220 ARGPATHS=$(printf "%b\n%b" "$ARGPATHS" "$APPMAN_PATHS") 221 ARGS=$(echo "$ARGPATHS" | xargs -n 1 basename 2>/dev/null) 222 fi 223 fi 224 # use "argpath=$(echo "$ARGPATHS" | grep "/$arg$")" to determine the full path of "arg" 225 } 226 227 _icon_theme_export_to_datadir() { 228 PNG="$(file "$APPSPATH"/*/icons/* | grep -i '.png' | awk -F":" '{print $1}' | grep -vi .png)" 229 SVG="$(file "$APPSPATH"/*/icons/* | grep -i '.svg' | awk -F":" '{print $1}' | grep -vi .svg)" 230 for file in $PNG; do ln -s "$file" "${file}".png; done 231 for file in $SVG; do ln -s "$file" "${file}".svg; done 232 if [ -n "$APPMAN_APPSPATH" ]; then 233 PNG="$(file "$APPMAN_APPSPATH"/*/icons/* | grep -i '.png' | awk -F":" '{print $1}' | grep -vi .png)" 234 SVG="$(file "$APPMAN_APPSPATH"/*/icons/* | grep -i '.svg' | awk -F":" '{print $1}' | grep -vi .svg)" 235 for file in $PNG; do ln -s "$file" "${file}".png; done 236 for file in $SVG; do ln -s "$file" "${file}".svg; done 237 fi 238 mkdir -p "$DATADIR"/icons/hicolor/scalable/apps 239 find "$DATADIR"/icons/hicolor/scalable/apps -xtype l -exec rm {} \; 240 ln -s "$APPSPATH"/*/icons/*.* "$DATADIR"/icons/hicolor/scalable/apps 241 [ -n "$APPMAN_APPSPATH" ] && ln -s "$APPMAN_APPSPATH"/*/icons/*.* "$DATADIR"/icons/hicolor/scalable/apps 242 } 243 244 ################################################################################ 245 # FINALIZE 246 ################################################################################ 247 248 AMCLIUPPER=$(echo "$AMCLI" | tr '[:lower:]' '[:upper:]') 249 250 # Create new data directory and move important files there 251 AMDATADIR="$DATADIR/AM" 252 mkdir -p "$AMDATADIR" 253 254 # DEVELOPER MODE 255 if [ -f "$AMDATADIR"/betatester ]; then 256 AMREPO="https://raw.githubusercontent.com/ivan-hc/AM/dev" 257 AMBRANCH=$(basename "$AMREPO") 258 MODULES_SOURCE="$AMREPO/modules" 259 fi 260 261 _betatester_message_on() { 262 if [ -f "$AMDATADIR"/betatester ]; then 263 echo "$DIVIDING_LINE"; echo "\"$AMCLIUPPER\" $AMVERSION: DEVELOPER MODE"; echo "$DIVIDING_LINE" 264 fi 265 } 266 267 ################################################################################ 268 # APPS DATABASE 269 ################################################################################ 270 271 # Apps database in use 272 APPSDB="${APPSDB:-$AMREPO/programs/$ARCH}" 273 APPSLISTDB="${APPSLISTDB:-$AMREPO/programs/$ARCH-apps}" 274 275 # Determine catalogue in use 276 export AMCATALOGUEMARKDOWNS="${AMCATALOGUEMARKDOWNS:-https://portable-linux-apps.github.io/apps}" 277 export AMCATALOGUEICONS="${AMCATALOGUEICONS:-https://portable-linux-apps.github.io/icons}" 278 279 ################################################################################ 280 # SECURITY 281 ################################################################################ 282 283 # SAFETY CHECKS 284 _am_dependences_check() { 285 # Check for essential commands required by the application 286 missing_deps="" 287 AMDEPENDENCES="cat chmod chown curl file grep sed wget" 288 for name in $AMDEPENDENCES; do 289 if ! command -v "$name" >/dev/null 2>&1; then 290 missing_deps="$name $missing_deps" 291 fi 292 done 293 294 # Exit if any essential command is missing 295 if [ -n "$missing_deps" ]; then 296 echo "$DIVIDING_LINE" 297 printf " ${RED}π ERROR! MISSING ESSENTIAL COMMANDS\033[0m: %s\n\n Install the above and try again! \n" "${missing_deps[*]}" 298 echo "$DIVIDING_LINE" 299 printf "%bList of the %b core dependences\033[0m:\n\n%b\n" "${Green}" "$AMCLIUPPER $AMVERSION" "$AMDEPENDENCES" | _fit 300 echo "$DIVIDING_LINE" 301 printf "If this message appears it is because you are missing some dependency and if its the first time its because something new has been introduced.\n\n" | _fit 302 printf " See %bhttps://github.com/ivan-hc/AM#core-dependences\033[0m for more information\n" "${LightBlue}" 303 echo "$DIVIDING_LINE" 304 exit 1 305 fi 306 } 307 308 _check_ubuntu_mess() { 309 if command -v unshare >/dev/null 2>&1 && ! unshare --user -p /bin/true >/dev/null 2>&1; then 310 echo "$DIVIDING_LINE" 311 printf "\n %bβ οΈ WARNING: ACCESS TO USER NAMESPACES IS RESTRICTED! \033[0m\n\n" "${RED}" 312 echo " Some apps may not run, you need to enable access to user namespaces, see" 313 printf " %bhttps://github.com/ivan-hc/AM/blob/main/docs/troubleshooting.md#ubuntu-mess\033[0m\n" "${LightBlue}" 314 echo " to know more." 315 echo "" 316 echo "$DIVIDING_LINE" 317 fi 318 } 319 320 _am_dependences_check 321 _check_ubuntu_mess 322 323 # Function to check online connections (uses github.com by default, as the database and CLI itself are stored/hosted there) 324 _online_check() { 325 if ! wget -q --tries=10 --timeout=20 --spider https://github.com; then 326 printf "\n %b is offline, please check your internet connection and try again\n\n" "$AMCLI" 327 exit 0 328 fi 329 } 330 331 # BLACKLIST FILES 332 appimagelauncher_msg="Your installation of AppImageLauncher may have been done via DEB, RPM, or AUR, which interrupts the \ 333 natural operation of \"systemd-binfmt\" in addition to launching the aforementioned daemon. To avoid problems with \"$AMCLIUPPER\" \ 334 and any other AppImages helper, it's preferable to use \"only\" the standalone AppImage of AppImageLauncher, whose official \ 335 updated release can also be installed via \"$AMCLIUPPER\". But as long as you have the currently installed version, you can't use this CLI." 336 337 _blacklisted_file() { 338 printf "\n %bπWARNING! Detected \"%b\"\033[0m\n\n" "${RED}" "$blacklisted_file" 339 echo "It will prevent \"$AMCLIUPPER\" from working correctly with AppImages, especially when extracting, integrating and updating them." | _fit 340 echo "" 341 if echo "$blacklisted_file" | grep -q appimagelauncherd; then 342 echo "$appimagelauncher_msg" | _fit 343 echo "" && echo " Please remove \"AppImageLauncher\", reboot and retry!" 344 else 345 echo " Please remove \"$blacklisted_file\", reboot and retry!" 346 fi 347 echo "" 348 exit 0 349 } 350 351 if command -v appimaged &>/dev/null; then 352 blacklisted_file=$(command -v appimaged) 353 _blacklisted_file 354 elif command -v appimagelauncherd &>/dev/null; then 355 blacklisted_file=$(command -v appimagelauncherd) 356 _blacklisted_file 357 fi 358 359 ################################################################################ 360 # 3RD PARTY 361 ################################################################################ 362 363 _use_newrepo() { 364 [ -z "$2" ] && echo " USAGE: $AMCLI $1 [ARGUMENT]" && exit 1 365 case $2 in 366 'add') 367 if [ -z "$3" ]; then 368 echo " USAGE: $AMCLI $1 $2 /path/to/dir"; echo " $AMCLI $1 $2 {URL}"; exit 1 369 else 370 echo "$3" >> "$AMDATADIR/newrepo-lists" 371 fi 372 ;; 373 'enable'|'on') 374 [ ! -f "$AMDATADIR/newrepo-lists" ] && echo " ERROR, \"$AMDATADIR/newrepo-lists\" file not found" && exit 1 375 [ -f "$AMDATADIR/newrepo-off" ] && mv "$AMDATADIR/newrepo-off" "$AMDATADIR/newrepo-on" && echo " New repo ON!" 376 ;; 377 'disable'|'off') 378 [ ! -f "$AMDATADIR/newrepo-lists" ] && echo " ERROR, \"$AMDATADIR/newrepo-lists\" file not found" && exit 1 379 [ -f "$AMDATADIR/newrepo-on" ] && mv "$AMDATADIR/newrepo-on" "$AMDATADIR/newrepo-off" && echo " New repo OFF!" 380 ;; 381 'info') 382 printf " Source: %b\n Apps: %b\n List: %b\n" "$AMREPO" "$APPSDB" "$APPSLISTDB" 383 ;; 384 'purge') 385 [ -f "$AMDATADIR/newrepo-lists" ] && rm -f "$AMDATADIR"/newrepo* && echo " Removed all 3rd party repositories" 386 ;; 387 'select') 388 [ ! -f "$AMDATADIR/newrepo-lists" ] && echo " ERROR, \"$AMDATADIR/newrepo-lists\" file not found" && exit 1 389 printf "Select a repo from the list or press CTRL+C to abort:\n%b\n" "$DIVIDING_LINE"; sleep 1 390 select repo in $(sort -u "$AMDATADIR/newrepo-lists" | uniq); do 391 test -n "$repo" && break 392 echo ">>> Invalid Selection" 393 done 394 echo "$repo" > "$AMDATADIR/newrepo-on" 395 ;; 396 esac 397 } 398 399 # 3RD PARTY DATABASES 400 _am_newrepo_check() { 401 # Determine if the CLI uses the "main" branch of https://github.com/ivan-hc/AM or an alternative one 402 if [ -f "$AMDATADIR/newrepo-on" ]; then 403 if grep -q "^http" "$AMDATADIR/newrepo-on"; then 404 AMREPO=$(<"$AMDATADIR/newrepo-on") 405 elif grep -q "^/" "$AMDATADIR/newrepo-on"; then 406 AMREPO="file://$(<"$AMDATADIR/newrepo-on")" 407 fi 408 AMBRANCH=$(basename "$AMREPO") 409 export APPSDB="$AMREPO/programs/$ARCH" 410 export APPSLISTDB="$AMREPO/programs/$ARCH-apps" 411 export MODULES_PATH="$AMPATH/modules" 412 export AMCATALOGUEMARKDOWNS="" 413 export AMCATALOGUEICONS="" 414 if [ "$1" != "newrepo" ] && [ "$1" != "neodb" ]; then 415 echo "$DIVIDING_LINE"; echo " Source: $AMREPO"; echo "$DIVIDING_LINE" 416 fi 417 fi 418 } 419 420 _am_newrepo_check "$@" 421 422 ################################################################################ 423 # 3RD PARTY SOURCES 424 ################################################################################ 425 426 third_party_flags_message="" 427 428 # APPBUNDLEHUB 429 export appbundle_repo="https://github.com/xplshn/AppBundleHUB" 430 appbundle_readme="https://raw.githubusercontent.com/xplshn/dbin-metadata/refs/heads/master/misc/cmd/AM-support/AM.txt" 431 432 _sync_appbundle_list() { 433 rm -f "$AMDATADIR/$ARCH-appbundle" 434 [ -n "$appbundle_readme" ] && curl -Ls "$appbundle_readme" | grep -v "\.appimage \|?" | grep "\.appbundle " | cut -d":" -f1 | cut -d"@" -f2 \ 435 | sed 's/^| /β /g; s/ https$//g; s/ :$//g; s/ | / : /g; s/ |$/./g; s/\.\.$/./g;' | sort > "$AMDATADIR/$ARCH-appbundle" \ 436 || touch "$AMDATADIR/$ARCH-appbundle" 437 } 438 439 # TOOLPACKS 440 toolpack_repo="https://github.com/Azathothas/Toolpacks" 441 toolpack_readme="https://bin.pkgforge.dev/${ARCH}/AM.txt" 442 [ -n "$toolpack_readme" ] && third_party_flags="$third_party_flags --toolpack" 443 [ -n "$toolpack_readme" ] && third_party_flags_message="$third_party_flags_message\n 444 ${Gold}--toolpack\033[0m 445 446 ${LightBlue}$AMCLI -i --toolpack {PROGRAM}\033[0m 447 ${LightBlue}am -i --toolpack --user {PROGRAM}\033[0m 448 ${LightBlue}$AMCLI -l --toolpack\033[0m 449 ${LightBlue}$AMCLI -q --toolpack {KEYWORD}\033[0m 450 451 Description: This is a flag to use in \"-i\" to install Toolpack programs, in \"-l\" to list all available \ 452 Toolpacks, and \"-q\" to search the Toolpack list. Toolpack is a collection of programs external to the \"AM\" \ 453 database. Visit $toolpack_repo to learn more. 454 455 NOTE, for installations you can use \".toolpack\" as the package extension instead of using the flag. 456 " 457 458 _sync_toolpacks_list() { 459 rm -f "$AMDATADIR/$ARCH-toolpack" 460 [ -n "$toolpack_readme" ] && curl -Ls "$toolpack_readme" | grep -v "\.appimage \|.appbundle \|?" | cut -d":" -f1 | cut -d"@" -f2 \ 461 | sed 's/^| /β /g; s/ | https$/. To install it use the "--toolpack" flag./g; s/ | / : /g' | sort > "$AMDATADIR/$ARCH-toolpack" \ 462 || touch "$AMDATADIR/$ARCH-toolpack" 463 } 464 465 ################################ 466 # ALL THE ABOVE 467 ################################ 468 469 export third_party_lists="appbundle toolpack" 470 471 _completion_list_third_party() { 472 [ -f "$AMDATADIR"/"$ARCH"-appbundle ] && awk '{print $2}' "$AMDATADIR"/"$ARCH"-appbundle >> "$AMDATADIR"/list 473 [ -f "$AMDATADIR"/"$ARCH"-toolpack ] && awk '{print $2}' "$AMDATADIR"/"$ARCH"-toolpack | sed -e 's/$/.toolpack/' >> "$AMDATADIR"/list 474 } 475 476 _sync_third_party_lists() { 477 _sync_appbundle_list 478 _sync_toolpacks_list 479 } 480 481 export awk_name="1" awk_description="2" awk_site="3" awk_dl="4" awk_ver="5" # Numbers to use in "awk" to determine columns 482 483 [ -z "$third_party_flags_message" ] && third_party_flags_message="none\n" 484 485 ################################################################################ 486 # UTILITIES 487 ################################################################################ 488 489 # COMPLETION LIST 490 available_options="about add apikey backup clean config disable downgrade download enable extra files home icons info \ 491 install install-appimage launcher list lock neodb newrepo nolibfuse off on overwrite purge query remove sandbox \ 492 select sync template test unlock update --all --appimages --apps --byname --config --convert --debug \ 493 --devmode-disable --devmode-enable --disable-notifications --enable-notifications --force-latest --home --icons \ 494 -ias --launcher --less --pkg --rollback --disable-sandbox --sandbox --system --user $third_party_flags" 495 496 _completion_lists() { 497 # Remove existing lists and download new ones 498 curl -Ls "$APPSLISTDB" > "$AMDATADIR/$ARCH-apps" 499 awk -v FS="(β | : )" '{print $2}' <"$AMDATADIR"/"$ARCH"-apps > "$AMDATADIR"/list 500 _completion_list_third_party 501 # Append options to the list 502 for o in $available_options; do 503 echo "$o" >> "$AMDATADIR"/list 504 done 505 } 506 507 # BASH, FISH AND ZSH COMPLETION 508 completion_file="$DATADIR/bash-completion/completions/$AMCLI" 509 mkdir -p "$DATADIR/bash-completion/completions" || exit 1 510 if ! grep -o " $AMCLI$" "$completion_file" >/dev/null 2>&1; then 511 echo "complete -W \"\$(cat $AMDATADIR/list 2>/dev/null)\" $AMCLI" >> "$completion_file" 512 if [ -f "${ZDOTDIR:-$HOME}"/.zshrc ] && echo "$SHELL" | grep -q "zsh"; then 513 cat <<-HEREDOC >> "${ZDOTDIR:-$HOME}"/.zshrc 514 autoload bashcompinit 515 bashcompinit 516 source "$completion_file" 517 HEREDOC 518 fi 519 echo "Shell completion has been enabled!" 520 fi 521 if [ -d "$DATADIR"/fish/completions ] || [ -d /etc/fish/completions ] || [ -d /usr/share/fish/completions ]; then 522 command -v fish 1>/dev/null && [ ! -f "$CONFIGDIR"/fish/completions/am.fish ] && mkdir -p "$CONFIGDIR"/fish/completions && echo "complete -c am -f -a \"(cat $DATADIR/AM/list 2>/dev/null)\"" > "$CONFIGDIR"/fish/completions/am.fish 523 fi 524 525 # VERSION OF THE INSTALLED APPS 526 # Filters 527 _check_version_filters() { 528 sed -E "s/$ARCH|amd64|x86-64|x64|basic|standard|full|help|Qt[0-9]//g; s/-/\n/g; s/_/\n/g;" |\ 529 grep -vi "appimage\|$arg\|?\|tar." | grep "[0-9]" | head -1 | sed 's/^v//g; s/^\.//g; s/\.$//g;' 530 } 531 532 _check_version_grep_numbers() { 533 grep -Eo "([0-9]{1,}\.)+[0-9]{1,}" | head -1 534 } 535 536 # Versions 537 _check_version_if_any_version_reference_is_somewhere() { 538 txt_files=$(file "$argpath"/* | awk -F: '/ASCII text/ {print $1}') 539 for txtf in $txt_files; do 540 if [ -f "$argpath"/tbb_version.json ] && grep -qi "\"version\":" "$argpath"/tbb_version.json; then 541 APPVERSION=$(sort "$argpath"/tbb_version.json | tr '"' '\n' | grep "^[0-9]" | head -1) 542 elif grep -qi "^version=" "$txtf" && grep -qi "^name=" "$txtf"; then 543 APPVERSION=$(grep -i "^version=" "$txtf" | cut -c 9- | tr -cd '[:alnum:]._-') 544 fi 545 done 546 } 547 548 _check_version_if_version_file_exists() { 549 APPVERSION=$(sort "$argpath"/version | head -1 | sed 's:.*/::' | _check_version_filters) 550 if [ -z "$APPVERSION" ]; then 551 if grep -q "download$" "$argpath"/version; then 552 APPVERSION=$(sort "$argpath"/version | tr '/' '\n' | _check_version_filters) 553 elif grep -q "://" "$argpath"/version; then 554 APPVERSION=$(sort "$argpath"/version | tr '/' '\n' | _check_version_grep_numbers) 555 elif grep -q "/v[0-9]*" "$argpath"/version; then 556 APPVERSION=$(sort "$argpath"/version | tr '/' '\n' | grep "^v[0-9]" | head -1 | sed 's/^v//g') 557 elif [ "$(sort "$argpath"/version | wc -w | sed 's/ //g')" = 1 ]; then 558 APPVERSION=$(sort "$argpath"/version | head -1) 559 fi 560 fi 561 if [ -z "$APPVERSION" ]; then 562 if grep -q "http.*download/.*[0-9].*/" "$argpath"/version; then 563 APPVERSION=$(sort "$argpath"/version | tr '/-' '\n' | grep "[0-9]" | _check_version_filters | tail -1) 564 fi 565 fi 566 } 567 568 _check_version_if_library() { 569 LIBNAME=$(sort "$argpath"/remove | tr ' ' '\n' | grep "usr/local/lib" | head -1 | sed 's:.*/::') 570 APPVERSION=$(find /usr/local/lib -type f -name "$LIBNAME" -type f | sed 's:.*.so.::' | tail -1) 571 } 572 573 _check_version_if_binary_in_place() { 574 APPVERSION=$(date -r "$argpath"/"$arg" "+%Y.%m.%d") 575 } 576 577 _check_version() { 578 rm -f "$AMCACHEDIR"/version-args 579 _determine_args 580 for arg in $ARGS; do 581 argpath=$(echo "$ARGPATHS" | grep "/$arg$") 582 if [ -f "$argpath"/remove ]; then 583 if [ -f "$argpath"/version ]; then 584 _check_version_if_version_file_exists 585 elif [ "$arg" = "$AMCLI" ]; then 586 APPVERSION="$AMVERSION" 587 elif echo "$arg" | grep -q "ffwa-"; then 588 APPVERSION="WebApp" 589 elif grep -q "usr/local/lib" "$argpath"/remove 2>/dev/null; then 590 _check_version_if_library 591 elif [ -f "$argpath"/updater ] || grep -qi "version=" "$argpath"/*; then 592 _check_version_if_any_version_reference_is_somewhere 593 else 594 APPVERSION="unknown" 595 fi 596 if [ -z "$APPVERSION" ]; then 597 [ -f "$argpath"/"$arg" ] && _check_version_if_binary_in_place || APPVERSION="unknown" 598 fi 599 echo " β $arg | $APPVERSION" >> "$AMCACHEDIR"/version-args 600 fi 601 done 602 } 603 604 _check_version_for_auto_updatable_apps() { 605 _determine_args 606 for arg in $ARGS; do 607 argpath=$(echo "$ARGPATHS" | grep "/$arg$") 608 if [ -f "$argpath"/updater ]; then 609 _check_version_if_any_version_reference_is_somewhere 610 if [ "$AMCLI" = am ] && [ -d "$CACHEDIR"/am ] && grep -q " β $arg |" "$CACHEDIR"/am/version-args; then 611 OLDAPPVERSION=$(grep " β $arg |" "$CACHEDIR"/am/version-args | awk 'END {print $NF}') 612 sed -i "/ β $arg |/s#$OLDAPPVERSION#$APPVERSION#" "$CACHEDIR"/am/*args* 613 fi 614 if [ -d "$CACHEDIR"/appman ] && grep -q " β $arg |" "$CACHEDIR"/appman/version-args; then 615 OLDAPPVERSION=$(grep " β $arg |" "$CACHEDIR"/appman/version-args | awk 'END {print $NF}') 616 sed -i "/ β $arg |/s#$OLDAPPVERSION#$APPVERSION#" "$CACHEDIR"/appman/*args* 617 fi 618 fi 619 done 620 } 621 622 if [ -f "$AMCACHEDIR"/version-args ]; then 623 _check_version_for_auto_updatable_apps 2>/dev/null 624 fi 625 626 # This function removes all info and versions from the register 627 _remove_info_files() { 628 rm -f "$AMCACHEDIR"/files* 629 rm -f "$AMCACHEDIR"/version-args 630 } 631 632 ################################################################################ 633 # APIKEY 634 ################################################################################ 635 636 ghapikey_file="$AMDATADIR/ghapikey.txt" 637 # Set header authorization if GitHub API key file exists 638 [ -f "$ghapikey_file" ] && HeaderAuthWithGITPAT=" --header \"Authorization: token $(<"$ghapikey_file")\" " 639 640 _use_apikey() { 641 case $2 in 642 'del'|'delete'|'remove') 643 [ -f "$ghapikey_file" ] || { echo " β No file named $ghapikey_file has been found"; exit 1; } 644 rm -f "$ghapikey_file" && echo " β $ghapikey_file has been removed" 645 exit 0 646 esac 647 if [[ "$2" =~ ^(gh[ps]_[a-zA-Z0-9]{36}|github_pat_[a-zA-Z0-9]{22}_[a-zA-Z0-9]{59})$ ]]; then 648 test_apikey_output_with_wget=$(curl -Ls --header "Authorization: token $2" 'https://api.github.com/repos/ivan-hc/AM/releases' | head -1) 649 [ -n "$test_apikey_output_with_wget" ] && echo "$2" > "$ghapikey_file" \ 650 && echo "Validation successful!" || echo "ERROR: This is not a valid key!" 651 else 652 echo "ERROR: Wrong expression, validation failed!" 653 fi 654 } 655 656 _update_github_api_key_in_the_updater_files() { 657 if [ -f "$ghapikey_file" ]; then 658 ghapikey=$(<"$ghapikey_file") 659 updater_files=("$APPSPATH"/*/AM-updater) # Assuming AM-updater is one level deeper 660 for f in "${updater_files[@]}"; do 661 if [ -f "$f" ] && grep -q "https://api.github.com" "$f"; then 662 # Check if the file already contains a valid API key 663 if ! grep -qE "(gh[ps]_[a-zA-Z0-9]{36}|github_pat_[a-zA-Z0-9]{22}_[a-zA-Z0-9]{59})" "$f"; then 664 # Insert HeaderAuthWithGITPAT before the GitHub API URL 665 sed -i "s#https://api.github.com#$HeaderAuthWithGITPAT https://api.github.com#g" "$f" 666 else 667 # Replace existing API key with the one from ghapikey.txt 668 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" 669 fi 670 fi 671 done 672 fi 673 } 674 675 ################################################################################ 676 # APPMAN MODE 677 ################################################################################ 678 679 APPMAN_MSG="$DIVIDING_LINE\n \"AM\" is running as \"AppMan\", use ${Green}am --system\033[0m to switch it back to \"AM\"\n$DIVIDING_LINE\n" 680 APPMAN_MSG_OFF="$DIVIDING_LINE\n \"AppMan Mode\" disabled! \n$DIVIDING_LINE\n" 681 APPMAN_MSG_THINK="$DIVIDING_LINE\nNOTE: You can also choose to simply use \"--user\" as a flag to install apps locally \ 682 (options \"-i\", \"-ia\" and \"-e\") instead of going fully into \"AppMan Mode\". \"AM\" can handle local applications as well.\n$DIVIDING_LINE\n" 683 684 _use_appman() { 685 _online_check 686 [ "$CLI" = appman ] && echo " This function only works for AM" && exit 0 687 printf "%b" "$APPMAN_MSG_THINK" | _fit 688 read -r -p " Do you wish to enter \"AppMan Mode\" (y,N)?" yn 689 if ! echo "$yn" | grep -i '^y' >/dev/null 2>&1; then 690 echo "$DIVIDING_LINE" 691 else 692 [ ! -f "$APPMANCONFIG"/appman-mode ] && mkdir -p "$APPMANCONFIG" && touch "$APPMANCONFIG"/appman-mode 693 _appman && printf "%b" "$APPMAN_MSG" 694 fi 695 } 696 697 if [ "$AMCLI" = am ]; then 698 if [ -f "$APPMANCONFIG"/appman-mode ]; then 699 [ ! -f "$APPMANCONFIG"/appman-config ] && printf "%b" "$APPMAN_MSG" 700 _appman 701 AMCLIPATH="$(realpath "$0")" 702 elif [ ! -w "$AMPATH" ]; then 703 read -r -p " \"AM\" is read-only, want to use it in \"AppMan Mode\" (Y,n)? " yn 704 if echo "$yn" | grep -i '^n' >/dev/null 2>&1; then 705 exit 0 706 else 707 echo "$DIVIDING_LINE"; echo "\"AppMan Mode\" enabled!"; echo "$DIVIDING_LINE" 708 _use_appman 1>/dev/null 709 fi 710 fi 711 fi 712 713 ################################################################################ 714 # CLEAN 715 ################################################################################ 716 717 _clean_amcachedir_message() { 718 _clean_amcachedir 719 [ "$AMCLI" = am ] && [ -d "$CACHEDIR"/am ] && echo " β Clear the contents of $CACHEDIR/am" 720 [ -d "$CACHEDIR"/appman ] && echo " β Clear the contents of $CACHEDIR/appman" 721 } 722 723 _clean_all_home_cache_directories_of_appimages() { 724 for arg in $ARGPATHS; do 725 if test -d "$arg"/*.home/.cache; then 726 rm -Rf "$arg"/*/*.home/.cache/* && echo " β Clear the contents of $arg/*.home/.cache" 727 fi 728 done 729 } 730 731 _clean_all_tmp_directories_from_appspath() { 732 _determine_args 733 for arg in $ARGPATHS; do 734 if [ -d "$arg"/tmp ]; then 735 rm -Rf "$arg"/tmp && echo " β Removed $arg/tmp" 736 fi 737 done 738 } 739 740 _clean_launchers() { 741 if [ -d "$DATADIR"/applications/AppImages ]; then 742 rm -f "$AMCACHEDIR"/mountpoints 743 for var in "$DATADIR"/applications/AppImages/*.desktop; do 744 # full path to appimage 745 appimagename=$(awk -F'=| ' '/Exec=/{print $2; exit}' "$var" | sed 's/"//g; s/\s.*$//') 746 # name of the appimage 747 launcher2del=$(basename -- "$(echo "$appimagename" | tr '[:upper:]' '[:lower:]')") 748 # removable mount point where the appimage may be stored 749 mountpoint=$(echo "$appimagename" | cut -d'/' -f1-4) 750 if [ ! -f "$appimagename" ]; then 751 if echo "$appimagename" | grep -q "^/media/\|^/mnt/"; then 752 mountpoint=$(echo "$appimagename" | cut -d'/' -f1-4) 753 unmounted_point=$(echo "$mountpoint" | cut -d'/' -f1-2) 754 elif echo "$appimagename" | grep -q "^/run/media/"; then 755 mountpoint=$(echo "$appimagename" | cut -d'/' -f1-5) 756 unmounted_point="/run/media" 757 else 758 mountpoint="" 759 fi 760 if [ -n "$mountpoint" ] && [ ! -d "$mountpoint" ]; then 761 echo "$mountpoint" >> "$AMCACHEDIR"/mountpoints 762 echo " β ERROR: cannot remove \"$(basename "$var")\"" 763 echo " related AppImage is located in an unmounted path of $unmounted_point" 764 else 765 rm -f "$var" 766 [ -n "$BINDIR" ] && [ -n "$launcher2del" ] && rm -f "$BINDIR"/"$launcher2del"* 767 fi 768 fi 769 done 770 if [ -f "$AMCACHEDIR"/mountpoints ]; then 771 mountpoints=$(sort "$AMCACHEDIR"/mountpoints) 772 for m in $mountpoints; do 773 [ ! -d "$m" ] && mountpoint_enabled=1 774 done 775 fi 776 [ -z "$mountpoint_enabled" ] && [ -n "$BINDIR" ] && cd "$BINDIR" && find . -xtype l -delete 777 rm -f "$AMCACHEDIR"/mountpoints 778 echo ' β Removed orphaned launchers produced with the "--launcher" option' 779 rmdir "$DATADIR"/applications/AppImages 780 else 781 [ -n "$BINDIR" ] && cd "$BINDIR" && find . -xtype l -delete 782 fi 783 } 784 785 _clean_old_modules() { 786 MODULES=$(sort "$(realpath "$0")" | tr '"' '\n' | grep "[a-z]\.am$" | uniq) 787 [ -z "$MODULES_PATH" ] && exit 1 788 for m in "$MODULES_PATH"/*; do 789 if [[ "${MODULES}" != *"$(basename -- "$m")"* ]];then 790 rm -f "$m" 2>/dev/null 791 echo " β Removed obsolete module named \"$(basename -- "$m")\"" 792 fi 793 done 794 } 795 796 _use_clean() { 797 echo " Cleaning temporary files and folders..." && sleep 0.1 798 i=100 && while [ "$i" -ge 0 ]; do 799 printf " %03d\r" "$i" && sleep 0.0001 && i=$((i - 1)) 800 done 801 _detect_appman_apps 802 _determine_args 803 _clean_amcachedir_message 804 _clean_all_home_cache_directories_of_appimages 805 _clean_all_tmp_directories_from_appspath 806 _clean_launchers 2>/dev/null 807 _clean_old_modules 808 } 809 810 ################################################################################ 811 # SYNC 812 ################################################################################ 813 814 _sync_installation_scripts() { 815 printf "%b\n Checking for changes of the installation scripts in the online database...\n" "$DIVIDING_LINE" 816 _determine_args 817 for arg in $ARGS; do 818 argpath=$(echo "$ARGPATHS" | grep "/$arg$") 819 if [ -f "$argpath"/AM-updater ]; then 820 mkdir -p "$argpath"/.am-installer 821 scriptname=$(ls "$argpath/.am-installer/" | head -1) 822 if [ -n "$scriptname" ]; then 823 CURRENT=$(cat "$argpath"/.am-installer/"$scriptname") 824 SOURCE=$(curl -Ls "$APPSDB"/"$scriptname") 825 if [ "$CURRENT" = "$SOURCE" ]; then 826 echo -ne "\r" 2>/dev/null 827 else 828 printf " β Changed https://github.com/ivan-hc/AM/blob/main/programs/%b/%b\n" "$ARCH" "$scriptname" 829 fi 830 else 831 if curl --output /dev/null --silent --head --fail "$APPSDB"/"$arg" 1>/dev/null; then 832 printf " β No installation script for %b, downloading one...\n" "$arg" 833 mkdir -p "$argpath"/.am-installer 834 wget -q "$APPSDB/$arg" -O "$argpath"/.am-installer/"$arg" 835 fi 836 fi 837 fi 838 done 839 } 840 841 _sync_appimages_list() { 842 APPIMAGES_LIST="${APPIMAGES_LIST:-$AMREPO/programs/$ARCH-appimages}" 843 curl -Ls "$APPIMAGES_LIST" > "$AMDATADIR/$ARCH-appimages" 844 } 845 846 _sync_databases() { 847 printf "%b\n Check and update offline lists of additional databases...\n" "$DIVIDING_LINE" 848 _sync_appimages_list 849 _sync_third_party_lists 2>/dev/null 850 _completion_lists 851 } 852 853 _sync_modules() { 854 printf "%b\n Check for updates in modules...\n" "$DIVIDING_LINE" 855 MODULES=$(curl -Ls "$AMREPO/APP-MANAGER" | tr '"' '\n' | grep "[a-z]\.am$") 856 for module_name in $MODULES; do 857 cd "$MODULES_PATH" || return 1 858 if ! test -f ./"$module_name"; then 859 echo " β Downloading $module_name (not previously installed)..." 860 curl -Os "$MODULES_SOURCE/$module_name" 2>/dev/null 861 chmod a+x ./"$MODULENAME" 862 fi 863 CURRENT=$(cat ./"$module_name" 2>/dev/null) 864 SOURCE=$(curl -Ls "$MODULES_SOURCE/$module_name") 865 if [ "$CURRENT" = "$SOURCE" ]; then 866 echo -ne "\r" 2>/dev/null 867 else 868 echo " β Updating $module_name..." 869 curl -Ls "$MODULES_SOURCE/$module_name" > ./"$module_name" 2>/dev/null 870 fi 871 done 872 _clean_old_modules 873 } 874 875 _sync_amcli() { 876 echo "$DIVIDING_LINE" 877 CURRENT_AM_VERSION="$AMVERSION" 878 echo -ne "\n β SYNCHRONIZING \"$AMCLIUPPER\" VERSION \"$CURRENT_AM_VERSION\"...\r" && sleep 0.25 879 _clean_amcachedir 1>/dev/null 880 cd "$AMCACHEDIR" || return 1 881 curl -Ls "$AMREPO"/APP-MANAGER > ./APP-MANAGER && chmod a+x ./APP-MANAGER 882 echo y | mv ./APP-MANAGER "$(realpath "$0")" 883 NEW_AM_VERSION=$("$AMCLIPATH" -v) 884 if [ ! "$CURRENT_AM_VERSION" = "$NEW_AM_VERSION" ]; then 885 echo -ne " A new release of \"$AMCLIUPPER\" is available, please wait...\r" 886 echo " β \"$AMCLIUPPER\" IS NOW UPDATED TO THE BRAND NEW \"$NEW_AM_VERSION\" VERSION!" 887 printf "\n Replacement of version \"%b\" currently in use, COMPLETED! \n" "$CURRENT_AM_VERSION" 888 printf "\n See https://github.com/ivan-hc/AM/commits/main\n\n" 889 else 890 echo " β \"$AMCLIUPPER\" IS ALREADY UPDATED, CURRENT VERSION \"$CURRENT_AM_VERSION\"" 891 printf "\n See https://github.com/ivan-hc/AM/commits/%b\n\n" "$AMBRANCH" 892 fi 893 } 894 895 _use_sync() { 896 _online_check 897 _betatester_message_on 898 _sync_installation_scripts 899 _sync_databases 900 if [ "$(realpath "$0")" != "/usr/bin/am" ] && [ "$AMSYNC" != 1 ]; then 901 _sync_modules 902 _sync_amcli 903 fi 904 echo "$DIVIDING_LINE" 905 } 906 907 ################################################################################ 908 # UPDATE 909 ################################################################################ 910 911 _update_updatable_apps_msg_head() { 912 printf " \"%b\" CAN MANAGE UPDATES FOR THE FOLLOWING PROGRAMS:\n%b\n\n" "$AMCLIUPPER" "$DIVIDING_LINE" 913 [ -f "$AMCACHEDIR/updatable-args-list" ] && grep "β" "$AMCACHEDIR/updatable-args-list" | sort || echo " None" 914 printf "\n All self-updatable programs are excluded\n" 915 echo "$DIVIDING_LINE" 916 } 917 918 _update_list_updatable_apps() { 919 _determine_args 920 _check_version 921 for arg in $ARGS; do 922 argpath=$(echo "$ARGPATHS" | grep "/$arg$") 923 if [ -d "$argpath" ]; then 924 if [ -f "$argpath/AM-updater" ]; then 925 app_version=$(grep -w " β $arg |" "$AMCACHEDIR/version-args" | sed 's:.*| ::') 926 echo " β $arg $app_version" >> "$AMCACHEDIR"/updatable-args-list 927 fi 928 fi 929 done 930 } 931 932 _update_determine_apps_version_changes() { 933 [ -z "$debug_update" ] && echo "$DIVIDING_LINE" 934 if [ -f "$AMCACHEDIR"/updatable-args-list ]; then 935 mv "$AMCACHEDIR"/updatable-args-list "$AMCACHEDIR"/updatable-args-list-old 936 _update_list_updatable_apps 937 OLDVER="$AMCACHEDIR/updatable-args-list-old" 938 NEWVER="$AMCACHEDIR/updatable-args-list" 939 if cmp --silent -- "$NEWVER" "$OLDVER"; then 940 echo ' Nothing to do here!' 941 else 942 printf " The following apps have been updated:\n\n" 943 diff "$OLDVER" "$NEWVER" | grep "^>" | sed 's/^> //g' 944 echo "" 945 fi 946 else 947 echo ' No apps to update here!' 948 fi 949 } 950 951 _update_run_updater() { 952 if grep -q "api.github.com" "$argpath"/AM-updater; then 953 GH_API_ALLOWED=$(curl -Ls $HeaderAuthWithGITPAT https://api.github.com/repos/ivan-hc/AM/releases/latest | sed 's/[()",{} ]/\n/g' | grep "^ivan-hc" | head -1) 954 if [ -z "$GH_API_ALLOWED" ]; then 955 if command -v torsocks 1>/dev/null; then 956 if [ -z "$debug_update" ]; then 957 torsocks "$argpath"/AM-updater >/dev/null 2>&1 958 else 959 torsocks "$argpath"/AM-updater 960 fi 961 else 962 echo " β $APPNAME cannot be updated, you have reached GitHub API limit. Install \"torsocks\" from your system package manager and retry!" \ 963 | fold -sw 72 | sed 's/^/ /g; s/ β/β/g' 964 fi 965 else 966 if [ -z "$debug_update" ]; then 967 "$argpath"/AM-updater >/dev/null 2>&1 968 else 969 "$argpath"/AM-updater 970 fi 971 fi 972 else 973 if [ -z "$debug_update" ]; then 974 "$argpath"/AM-updater >/dev/null 2>&1 975 else 976 "$argpath"/AM-updater 977 fi 978 fi 979 end=$(date +%s) 980 echo " β $APPNAME is updated, $((end - start)) seconds elapsed!" 981 [ -n "$debug_update" ] && echo "$DIVIDING_LINE" 982 } 983 984 _update_app() { 985 APPNAME=$(echo "$arg" | tr '[:lower:]' '[:upper:]') 986 start=$(date +%s) 987 if [ -w "$argpath"/AM-updater ]; then 988 _update_run_updater & 989 else 990 echo " β $APPNAME is read-only, cannot update it!" 991 fi 992 } 993 994 _update_all_apps() { 995 for arg in $ARGS; do 996 argpath=$(echo "$ARGPATHS" | grep "/$arg$") 997 cd "$argpath" || exit 1 998 arg=$(printf '%s\n' "${PWD##*/}") 999 if [ -f "$argpath"/AM-updater ]; then 1000 _update_app 1001 fi 1002 done 1003 wait 1004 _update_determine_apps_version_changes 1005 rm -Rf "$APPSPATH"/*/tmp 1006 [ -d "$APPMAN_APPSPATH" ] && rm -Rf "$APPMAN_APPSPATH"/*/tmp 1007 } 1008 1009 _update_launchers_not_found_msg() { 1010 MISSING_LAUNCHERS_MSG=" No launcher found." 1011 printf "%b\n%b\n%b\n" "$DIVIDING_LINE" "$MISSING_LAUNCHERS_MSG" "$DIVIDING_LINE" 1012 } 1013 1014 _update_launchers() { 1015 _clean_launchers 2>/dev/null 1>/dev/null 1016 MISSING_LAUNCHERS_MSG="No launcher found, use option \"--launcher\" to create them." 1017 [ ! -d "$DATADIR"/applications/AppImages ] && _update_launchers_not_found_msg && exit 0 1018 [ -d "$DATADIR"/applications/AppImages ] && [ -z "$( ls -A "$DATADIR"/applications/AppImages )" ] && _update_launchers_not_found_msg && exit 0 1019 if ! command -v appimageupdatetool 1>/dev/null; then 1020 update_launchers_error_message=" π ERROR! Missing command \"${RED}appimageupdatetool\033[0m\", install it and retry!" 1021 printf "%b\n%b\n%b\n" "$DIVIDING_LINE" "$update_launchers_error_message" "$DIVIDING_LINE" 1022 else 1023 echo " β Update local AppImages integrated manually" 1024 for var in "$DATADIR"/applications/AppImages/*.desktop; do 1025 appimage_full_path=$(awk -F'=| ' '/Exec=/{print $2; exit}' "$var" | sed 's/"//g; s/\s.*$//') 1026 appimagename=$(basename -- "$appimage_full_path") 1027 appimage_path=$(echo "$appimage_full_path" | sed -E 's|/[^/]+$|/|; s/\/*$//g') 1028 printf "%b\n File: %b%b\033[0m\n Path: %b" "$DIVIDING_LINE" "${Green}" "$appimagename" "$appimage_path" 1029 if [ ! -f "$appimage_full_path" ]; then 1030 echo "(unmounted)" | _fit 1031 else 1032 printf "\n\n" 1033 appimageupdatetool -Or "$appimage_full_path" 1034 fi 1035 done 1036 fi 1037 } 1038 1039 _use_update() { 1040 _online_check 1041 _update_github_api_key_in_the_updater_files 1042 _clean_all_tmp_directories_from_appspath >/dev/null 1043 1044 ENTRIES="$(echo "$@" | cut -f2- -d ' ' | tr ' ' '\n' | grep -v -- "^-\|^$1$")" 1045 FLAGS=$(echo "$@" | tr ' ' '\n' | grep -- "--" | tr '\n ' ' ') 1046 if echo "$FLAGS" | grep -q -- "--debug"; then 1047 debug_update="1" 1048 fi 1049 if [ -z "$ENTRIES" ]; then 1050 _clean_amcachedir 1051 _update_list_updatable_apps 1052 printf "%b\n >> START OF ALL PROCESSES << \n%b\n" "$DIVIDING_LINE" "$DIVIDING_LINE" 1053 if echo "$FLAGS" | grep -q -- "--apps"; then 1054 _update_updatable_apps_msg_head 1055 _update_all_apps 1056 elif echo "$FLAGS" | grep -q -- "--launcher"; then 1057 _update_launchers 1058 else 1059 _update_updatable_apps_msg_head 1060 _update_all_apps 1061 _use_sync 1062 printf " >> END OF ALL PROCESSES << \n%b\n" "$DIVIDING_LINE" 1063 sleep 0.2 1064 exit 0 1065 fi 1066 printf "%b\n >> END OF ALL PROCESSES << \n%b\n" "$DIVIDING_LINE" "$DIVIDING_LINE" 1067 sleep 0.2 1068 exit 0 1069 else 1070 [ -n "$debug_update" ] && echo "$DIVIDING_LINE" 1071 _determine_args 1072 for arg in $ENTRIES; do 1073 argpath=$(echo "$ARGPATHS" | grep "/$arg$") 1074 if [ -f "$argpath"/AM-updater ]; then 1075 cd "$argpath" 2>/dev/null || exit 1 1076 _update_app 1077 else 1078 UPDATERS=$(cd "$argpath" 2>/dev/null && find . -name "*update*" -print 2>/dev/null) 1079 [ -n "$UPDATERS" ] && arg_autoupdatable=", it may have its update system" 1080 echo " β Cannot manage updates for \"$(echo "$arg" | tr '[:lower:]' '[:upper:]')\"$arg_autoupdatable" 1081 fi 1082 done 1083 wait 1084 exit 0 1085 fi 1086 } 1087 1088 _use_force_latest() { 1089 _online_check 1090 _determine_args 1091 ENTRIES="$(echo "$@" | cut -f2- -d ' ')" 1092 for arg in $ENTRIES; do 1093 argpath=$(echo "$ARGPATHS" | grep "/$arg$") 1094 if [ ! -d "$argpath" ]; then 1095 echo " ERROR: \"$arg\" is not installed, see \"-f\"" 1096 elif [ ! -f "$argpath"/AM-updater ]; then 1097 echo " ERROR: \"$AMCLI\" cannot manage updates for \"$arg\"" 1098 elif ! grep -q "api.github.com" "$argpath"/AM-updater; then 1099 echo " ERROR: \"$arg\" source is not on Github" 1100 elif ! grep -q "/releases | " "$argpath"/AM-updater; then 1101 echo " ERROR: \"$arg\" does not redirect to a generic \"releases\"" 1102 else 1103 sed -i 's#/releases | #/releases/latest | #g' "$argpath"/AM-updater 1104 APPNAME=$(echo "$arg" | tr '[:lower:]' '[:upper:]') 1105 start=$(date +%s) 1106 _update_run_updater 1107 fi 1108 done 1109 } 1110 1111 ################################################################################ 1112 # USAGE 1113 ################################################################################ 1114 1115 # HANDLE ALL THE EXTERNAL MODULES 1116 _use_module() { 1117 # Test if module exists 1118 if [ ! -f "$MODULES_PATH/$MODULE" ]; then 1119 _online_check 1120 if ! wget -q "$MODULES_SOURCE/$MODULE" -O "$MODULES_PATH/$MODULE"; then 1121 echo " Module not found, run \"$AMCLI -s\" to update \"$AMCLIUPPER\"" 1122 exit 1 1123 fi 1124 chmod a+x "$MODULES_PATH/$MODULE" 1125 fi 1126 # Source module 1127 source "$MODULES_PATH/$MODULE" "$@" 1128 } 1129 1130 case "$1" in 1131 '') 1132 echo " USAGE: $AMCLI [OPTION]" 1133 echo " $AMCLI [OPTION] [ARGUMENT]" 1134 echo "" 1135 echo " Run the \"$AMCLI -h\" command to find out more" 1136 exit 0 1137 ;; 1138 'about'|'-a'|\ 1139 'files'|'-f'|'-fi'|\ 1140 'list'|'-l'|\ 1141 'query'|'-q') 1142 MODULE="database.am" 1143 if [ -t 1 ]; then _use_module "$@"; else _use_module "$@" | sed -e 's/\x1b\[[0-9;]*m//g'; fi 1144 ;; 1145 'backup'|'-b'|\ 1146 'downgrade'|'--rollback'|\ 1147 'icons'|'--icons'|\ 1148 'launcher'|'--launcher'|\ 1149 'lock'|'unlock'|\ 1150 'nolibfuse'|\ 1151 'overwrite'|'-o'|\ 1152 'remove'|'-R'|'-r') 1153 MODULE="management.am" 1154 _use_module "$@" 1155 ;; 1156 'config'|'-C'|'--config'|\ 1157 'home'|'-H'|'--home'|\ 1158 'sandbox'|'--sandbox'|\ 1159 '--disable-sandbox') 1160 MODULE="sandboxes.am" 1161 _use_module "$@" 1162 ;; 1163 'download'|'-d'|\ 1164 'extra'|'-e'|\ 1165 'install'|'-i'|'-ias'|\ 1166 'install-appimage'|'-ia') 1167 MODULE="install.am" 1168 _online_check 1169 [ "$CLI" = am ] && [ -f "$APPMANCONFIG"/appman-mode ] && printf "%b" "$APPMAN_MSG" 1170 _use_module "$@" 1171 ;; 1172 'template'|'-t') 1173 MODULE="template.am" 1174 _online_check 1175 _use_module "$@" 1176 ;; 1177 # INBUILT OPTIONS 1178 '--devmode-disable'|'--devmode-enable') 1179 [ "$1" = "--devmode-disable" ] && rm -f "$AMDATADIR"/betatester \ 1180 || touch "$AMDATADIR"/betatester && _betatester_message_on 1181 ;; 1182 '--force-latest') 1183 _use_force_latest "$@" 1184 ;; 1185 '--system') 1186 [ -f "$APPMANCONFIG"/appman-mode ] && rm -f "$APPMANCONFIG"/appman-mode && printf "%b" "$APPMAN_MSG_OFF" 1187 ;; 1188 'apikey') 1189 _use_apikey "$@" 1190 ;; 1191 'appman'|'--user') 1192 _use_appman 1193 ;; 1194 'clean'|'-c') 1195 _use_clean 1196 ;; 1197 'newrepo'|'neodb') 1198 _use_newrepo "$@" 1199 ;; 1200 'sync'|'-s') 1201 _use_sync 1202 ;; 1203 'update'|'-u'|'-U') 1204 _use_update "$@" 1205 ;; 1206 'version'|'-v'|'--version') 1207 echo "$AMVERSION" 1208 ;; 1209 '--disable-notifications') 1210 _determine_args 1211 for n in $ARGPATHS; do sed -e '/notify-send/ s/^#*/#/' -i "$n/AM-updater" 2>/dev/null; done 1212 ;; 1213 '--enable-notifications') 1214 _determine_args 1215 for n in $ARGPATHS; do sed -e '/notify-send/ s/^#*//' -i "$n/AM-updater" 2>/dev/null; done 1216 ;; 1217 'help'|'-h') 1218 ################################################################################ 1219 # HELP 1220 ################################################################################ 1221 1222 _use_help() { 1223 [ "$CLI" = am ] && [ -f "$APPMANCONFIG"/appman-mode ] && printf "%b" "$APPMAN_MSG" 1224 echo -e " 1225 NAME: ${Green}$AMCLIUPPER\033[0m VERSION: ${Green}$AMVERSION\033[0m 1226 1227 SYNOPSIS: ${LightBlue}$AMCLI {OPTION}\033[0m 1228 ${LightBlue}$AMCLI {OPTION} {PROGRAM}\033[0m 1229 1230 DESCRIPTION: A command line utility to install and manage AppImages and other portable programs for GNU/Linux thanks to its AUR-inspired database. 1231 1232 OPTIONS: 1233 1234 ${Gold}about, -a\033[0m 1235 1236 ${LightBlue}$AMCLI -a {PROGRAM}\033[0m 1237 1238 Description: Shows more info about one or more apps. 1239 1240 ${Gold}apikey\033[0m 1241 1242 ${LightBlue}$AMCLI apikey {Github Token} 1243 ${LightBlue}$AMCLI apikey delete\033[0m 1244 1245 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. 1246 1247 ${Gold}backup, -b\033[0m 1248 1249 ${LightBlue}$AMCLI -b {PROGRAM}\033[0m 1250 1251 Description: Create a snapshot of the current version of an installed program. 1252 1253 ${Gold}clean, -c\033[0m 1254 1255 ${LightBlue}$AMCLI -c\033[0m 1256 1257 Description: Removes all the unnecessary files and folders. 1258 1259 ${Gold}config, -C, --config\033[0m 1260 1261 ${LightBlue}$AMCLI -C {PROGRAM}\033[0m 1262 1263 Description: Set a dedicated \$XDD_CONFIG_HOME for one or more AppImages. 1264 1265 ${Gold}downgrade, --rollback\033[0m 1266 1267 ${LightBlue}$AMCLI --rollback {PROGRAM}\033[0m 1268 1269 Description: Download an older or specific app version. 1270 1271 ${Gold}download, -d\033[0m 1272 1273 ${LightBlue}$AMCLI -d {PROGRAM} 1274 ${LightBlue}$AMCLI -d --convert {PROGRAM}\033[0m 1275 1276 Description: Download one or more installation scripts to your desktop or convert them to local installers for \"AppMan\". To test the scripts, use the \"${LightBlue}$AMCLI -i '/path/to/script'\033[0m\" command or enter the directory of the script and run the \"${LightBlue}$AMCLI -i ./script\033[0m\" command, even using dedicated flags, if necessary (see \"-i\"). 1277 1278 ${Gold}extra, -e\033[0m 1279 1280 ${LightBlue}$AMCLI -e user/project {APPNAME} 1281 ${LightBlue}$AMCLI -e user/project {APPNAME} {KEYWORD}\033[0m 1282 1283 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. 1284 1285 ${Gold}files, -f, -fi\033[0m 1286 1287 ${LightBlue}$AMCLI -f 1288 ${LightBlue}$AMCLI -f --byname 1289 ${LightBlue}$AMCLI -f --less\033[0m 1290 1291 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. Option \"-fi\" only shows installed apps, not the AppImages integrated with the \"--launcher\" option. 1292 1293 ${Gold}help, -h\033[0m 1294 1295 ${LightBlue}$AMCLI -h\033[0m 1296 1297 Description: Prints this message. 1298 1299 ${Gold}home, -H, --home\033[0m 1300 1301 ${LightBlue}$AMCLI -H {PROGRAM}\033[0m 1302 1303 Description: Set a dedicated \$HOME directory for one or more AppImages. 1304 1305 ${Gold}icons, --icons\033[0m 1306 1307 ${LightBlue}$AMCLI --icons {PROGRAM} 1308 ${LightBlue}$AMCLI --icons --all\033[0m 1309 1310 Description: Allow installed apps to use system icon themes. You can specify the name of the apps to change or use the \"--all\" flag to change all of them at once. This will remove the icon path from the .desktop file and add the symbolic link of all available icons in the $DATADIR/icons/hicolor/scalable/apps directory. The \"--icons\" option can be used as \"flag\" in the \"-i\" and \"-ia\" options. 1311 1312 ${Gold}install, -i\033[0m 1313 1314 ${LightBlue}$AMCLI -i {PROGRAM} 1315 ${LightBlue}$AMCLI -i --debug {PROGRAM} 1316 ${LightBlue}$AMCLI -i --force-latest {PROGRAM} 1317 ${LightBlue}$AMCLI -i --icons {PROGRAM} 1318 ${LightBlue}$AMCLI -i --sandbox {PROGRAM}\033[0m 1319 1320 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. Use the \"--icons\" flag to allow the program to use icon themes. It can also be extended with additional flags (see third-party flags, at the bottom of this message). The \"--sandbox\" flag allows you to set sandboxes for AppImage packages. 1321 1322 ${Gold}install-appimage, -ia, -ias\033[0m 1323 1324 ${LightBlue}$AMCLI -ia {PROGRAM} 1325 ${LightBlue}$AMCLI -ia --debug {PROGRAM} 1326 ${LightBlue}$AMCLI -ia --force-latest {PROGRAM} 1327 ${LightBlue}$AMCLI -ia --icons {PROGRAM} 1328 ${LightBlue}$AMCLI -ia --sandbox {PROGRAM} 1329 ${LightBlue}$AMCLI -ias {PROGRAM}\033[0m 1330 1331 Description: Same as \"install\" (see above) but for AppImages only. Option \"-ias\" (aka Install AppImage & Sandbox) is equivalent to \"-ia --sandbox\", to set sandboxes for AppImage packages. 1332 1333 ${Gold}lock\033[0m 1334 1335 ${LightBlue}$AMCLI lock {PROGRAM}\033[0m 1336 1337 Description: Prevent an application being updated, if it has an\"AM-updater\" script. 1338 1339 ${Gold}list, -l\033[0m 1340 1341 ${LightBlue}$AMCLI -l 1342 ${LightBlue}$AMCLI -l --all 1343 ${LightBlue}$AMCLI -l --appimages\033[0m 1344 1345 Description: Shows the list of all the apps available, or just the AppImages. It can also be extended with additional flags, the \"--all\" flag allows you to consult the set of all supported databases (see third-party flags, at the bottom of this message). 1346 1347 ${Gold}newrepo, neodb\033[0m 1348 1349 ${LightBlue}$AMCLI newrepo add {URL}\\{PATH} 1350 ${LightBlue}$AMCLI newrepo select 1351 ${LightBlue}$AMCLI newrepo on\\off 1352 ${LightBlue}$AMCLI newrepo purge 1353 ${LightBlue}$AMCLI newrepo info\033[0m 1354 1355 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. 1356 1357 ${Gold}nolibfuse\033[0m 1358 1359 ${LightBlue}$AMCLI nolibfuse {PROGRAM}\033[0m 1360 1361 Description: Convert old AppImages and get rid of \"libfuse2\" dependence. 1362 1363 ${Gold}overwrite, -o\033[0m 1364 1365 ${LightBlue}$AMCLI -o {PROGRAM}\033[0m 1366 1367 Description: Overwrite apps with snapshots saved previously (see \"-b\"). 1368 1369 ${Gold}query, -q\033[0m 1370 1371 ${LightBlue}$AMCLI -q {KEYWORD} 1372 ${LightBlue}$AMCLI -q --all {KEYWORD} 1373 ${LightBlue}$AMCLI -q --appimages {KEYWORD} 1374 ${LightBlue}$AMCLI -q --pkg {PROGRAM1} {PROGRAM2}[0m 1375 1376 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. It can also be extended with additional flags, the \"--all\" flag allows you to consult the set of all supported databases (see third-party flags, at the bottom of this message). 1377 1378 ${Gold}remove, -r\033[0m 1379 1380 ${LightBlue}$AMCLI -r {PROGRAM}\033[0m 1381 1382 Description: Removes one or more apps, requires confirmation. 1383 1384 ${Gold}-R\033[0m 1385 1386 ${LightBlue}$AMCLI -R {PROGRAM}\033[0m 1387 1388 Description: Removes one or more apps without asking. 1389 1390 ${Gold}sandbox, --sandbox\033[0m 1391 1392 ${LightBlue}$AMCLI sandbox {PROGRAM}\033[0m 1393 1394 Description: Run an AppImage in a sandbox using Aisap. 1395 1396 NOTE, \"--sandbox\" can be used as a flag in \"-i\" and \"-ia\" or can be replaced using the option \"-ias\" (aka Install AppImage & Sandbox). 1397 1398 ${Gold}sync, -s\033[0m 1399 1400 ${LightBlue}$AMCLI -s\033[0m 1401 1402 Description: Updates this script to the latest version hosted. 1403 1404 ${Gold}template, -t\033[0m 1405 1406 ${LightBlue}$AMCLI -t {PROGRAM}\033[0m 1407 1408 Description: Generate a custom installation script. To test the scripts, use the \"${LightBlue}$AMCLI -i '/path/to/script'\033[0m\" command or enter the directory of the script and run the \"${LightBlue}$AMCLI -i ./script\033[0m\" command, even using dedicated flags, if necessary (see \"-i\"). 1409 1410 ${Gold}unlock\033[0m 1411 1412 ${LightBlue}$AMCLI unlock {PROGRAM}\033[0m 1413 1414 Description: Unlock updates for the selected program (nulls \"lock\"). 1415 1416 ${Gold}update, -u, -U\033[0m 1417 1418 ${LightBlue}$AMCLI -u 1419 ${LightBlue}$AMCLI -u --apps 1420 ${LightBlue}$AMCLI -u --debug 1421 ${LightBlue}$AMCLI -u --apps --debug 1422 ${LightBlue}$AMCLI -u {PROGRAM}\033[0m 1423 ${LightBlue}$AMCLI -u --debug {PROGRAM} 1424 ${LightBlue}$AMCLI -u --launcher\033[0m 1425 1426 Description: Update everything. Add \"--apps\" to update only the apps or write only the apps you want to update by adding their names. Add the \"--debug\" flag to view the output of AM-updater scripts. Add the \"--launcher\" flag to try to update only local AppImages integrated with the \"--launcher\" option (see \"--launcher\"). 1427 1428 ${Gold}version, -v\033[0m 1429 1430 ${LightBlue}$AMCLI -v\033[0m 1431 1432 Description: Shows the version. 1433 1434 ${Gold}--devmode-disable\033[0m 1435 1436 ${LightBlue}$AMCLI --devmode-disable\033[0m 1437 1438 Description: Undo \"--devmode-enable\" (see below). 1439 1440 ${Gold}--devmode-enable\033[0m 1441 1442 ${LightBlue}$AMCLI --devmode-enable\033[0m 1443 1444 Description: Use the development branch (at your own risk). 1445 1446 ${Gold}--disable-notifications\033[0m 1447 1448 ${LightBlue}$AMCLI --disable-notifications\033[0m 1449 1450 Description: Disable notifications during apps update. 1451 1452 ${Gold}--disable-sandbox\033[0m 1453 1454 ${LightBlue}$AMCLI --disable-sandbox {PROGRAM}\033[0m 1455 1456 Description: Disable the sandbox for the selected app. 1457 1458 ${Gold}--enable-notifications\033[0m 1459 1460 ${LightBlue}$AMCLI --enable-notifications\033[0m 1461 1462 Description: Enable notifications during apps update (nulls \"--disable-notifications\"). 1463 1464 ${Gold}--force-latest\033[0m 1465 1466 ${LightBlue}$AMCLI --force-latest {PROGRAM}\033[0m 1467 1468 Description: Downgrades an installed app from pre-release to \"latest\". 1469 1470 ${Gold}--launcher\033[0m 1471 1472 ${LightBlue}$AMCLI --launcher /path/to/\${APPIMAGE}\033[0m 1473 1474 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. 1475 1476 NOTE that \"--launcher\" can be used as a flag in \"-u\" to try to update the integrated AppImages (see \"-u\"). This works only if \"appimageupdatetool\" is installed and delta updates are supported. This flag does not work miracles, I strongly suggest to use options \"-ia\" and \"-e\" instead. 1477 1478 ${Gold}--system\033[0m 1479 1480 ${LightBlue}am --system\033[0m 1481 1482 ${Gold}--user\033[0m 1483 1484 ${LightBlue}am --user\033[0m 1485 1486 Description: Made \"AM\" run in \"AppMan Mode\", locally, useful for unprivileged users. This option only works with \"AM\". 1487 1488 The \"--user\" option can also be used just as a flag for installation options. For example: 1489 1490 - Use it to install applications locally, option \"-i\" or \"install\": 1491 1492 ${LightBlue}am -i --user {PROGRAM}\033[0m 1493 1494 - Also suboptions of \"-i\" can work with this flag: 1495 1496 ${LightBlue}am -i --user --debug {PROGRAM}\033[0m 1497 ${LightBlue}am -i --user --force-latest {PROGRAM} 1498 ${LightBlue}am -i --user --icons {PROGRAM} 1499 ${LightBlue}am -i --user --debug --force-latest {PROGRAM} 1500 ${LightBlue}am -i --user --debug --force-latest --icons {PROGRAM}\033[0m 1501 1502 - Same for AppImages only, option \"-ia\" or \"install-appimage\": 1503 1504 ${LightBlue}am -ia --user {PROGRAM}\033[0m 1505 ${LightBlue}am -ia --user --debug {PROGRAM} 1506 ${LightBlue}am -ia --user --force-latest {PROGRAM} 1507 ${LightBlue}am -ia --user --icons {PROGRAM} 1508 ${LightBlue}am -ia --user --debug --force-latest {PROGRAM}\033[0m 1509 ${LightBlue}am -ia --user --debug --force-latest --icons {PROGRAM}\033[0m 1510 1511 - External AppImages can be installed like this as well, option \"-e\" or \"extra\": 1512 1513 ${LightBlue}am -e --user user/project {APPNAME}\033[0m 1514 ${LightBlue}am -e --user user/project {APPNAME} {KEYWORD}\033[0m 1515 1516 NOTE, \"AM\" 9 or higher is also able to, update and manage apps locally, by default, and without having to switch to \"AppMan Mode\". 1517 1518 Description: Switch \"AM\" back to \"AM\" from \"AppMan Mode\" (see \"--user\"). 1519 1520 $DIVIDING_LINE 1521 1522 THIRD-PARTY FLAGS: $third_party_flags_message 1523 $DIVIDING_LINE 1524 1525 SITES: 1526 1527 https://github.com/ivan-hc/AM 1528 1529 https://portable-linux-apps.github.io 1530 1531 \n" | sed 's/^ //g' | _fit | less -Ir 1532 } 1533 1534 if [ -t 1 ]; then _use_help; else _use_help | sed -e 's/\x1b\[[0-9;]*m//g'; fi 1535 ;; 1536 *) 1537 exec "$AMCLIPATH" 1538 ;; 1539 esac 1540 1541 # vim:tabstop=4:shiftwidth=4:expandtab