APP-MANAGER 48 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364
  1. #!/usr/bin/env bash
  2. AMVERSION="9.1.1-10"
  3. # Determine main repository and branch
  4. AMREPO="https://raw.githubusercontent.com/ivan-hc/AM/main"
  5. AMBRANCH=$(basename "$AMREPO")
  6. MODULES_SOURCE="$AMREPO/modules"
  7. # Determine catalogue in use
  8. export AMCATALOGUEMARKDOWNS="https://portable-linux-apps.github.io/apps"
  9. export AMCATALOGUEICONS="https://portable-linux-apps.github.io/icons"
  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. # Determine system architecture and current user
  15. arch="$HOSTTYPE"
  16. export ARCH="$arch"
  17. # XDG Variables
  18. export BINDIR="${XDG_BIN_HOME:-$HOME/.local/bin}"
  19. export DATADIR="${XDG_DATA_HOME:-$HOME/.local/share}"
  20. export CONFIGDIR="${XDG_CONFIG_HOME:-$HOME/.config}"
  21. export CACHEDIR="${XDG_CACHE_HOME:-$HOME/.cache}"
  22. export APPMANCONFIG="$CONFIGDIR/appman"
  23. APPMANCONFIG="$CONFIGDIR/appman"
  24. SCRIPTDIR="$(xdg-user-dir DESKTOP 2>/dev/null || echo "$HOME")"
  25. export SCRIPTDIR
  26. # Colors
  27. RED='\033[0;31m'
  28. Gold='\033[0;33m'
  29. Green='\033[0;32m'
  30. LightBlue='\033[1;34m'
  31. DIVIDING_LINE="-----------------------------------------------------------------------------"
  32. # Prevent the use of "sudo" ("AM")
  33. [ -n "$SUDO_COMMAND" ] && echo -e "\n Please do not use \"sudo\" to execute \"$CLI\", try again.\n" && exit 1
  34. function _create_cache_dir() {
  35. AMCACHEDIR="$CACHEDIR/$AMCLI"
  36. mkdir -p "$AMCACHEDIR"
  37. }
  38. function _clean_amcachedir() {
  39. [ "$AMCLI" = am ] && [ -d "$CACHEDIR"/am ] && rm -f "$CACHEDIR"/am/*
  40. [ -d "$CACHEDIR"/appman ] && rm -f "$CACHEDIR"/appman/*
  41. }
  42. ################################################################################
  43. # AM/APPMAN
  44. ################################################################################
  45. # "APPMAN" CORE VARIABLES AND FUNCTIONS
  46. APPMAN_SETUP_MSG="Before proceeding with any task, where do you want to install apps?
  47. SYNTAX: /FULLPATH/TO/DIRNAME
  48. EXAMPLE: $HOME/My-apps
  49. NOTE: Any spaces in the path will be replaced for dashes
  50. NOTE: If no input is given then \"~/Applications\" will be used as default
  51. if you wish to later change the location, first remove all the programs and then edit the \"$APPMANCONFIG/appman-config\" file."
  52. function _appman_check() {
  53. if [ ! -f "$APPMANCONFIG"/appman-config ]; then
  54. echo "$DIVIDING_LINE"
  55. [ "$AMCLI" = am ] && echo ">>> Configure AppMan" || echo ">>> Thank you for choosing AppMan!"
  56. echo "$DIVIDING_LINE"
  57. echo "$APPMAN_SETUP_MSG" | fold -sw 77 | sed 's/^/ /g'
  58. echo "$DIVIDING_LINE"
  59. read -r -ep " Write the path or just press enter to use default:$(printf "\n\n ")" location
  60. location="$(echo "$location" | sed 's/[ \t]/-/g; s|^\./||' 2>/dev/null)"
  61. [ -z "$location" ] && location="$HOME/Applications"
  62. if ! echo "$location" | grep "^/" >/dev/null 2>&1; then
  63. location="$HOME/$location"
  64. fi
  65. if echo "$location" | grep "$BINDIR" >/dev/null 2>&1; then
  66. echo "$DIVIDING_LINE"
  67. echo " 💀 ERROR, you can't install applications in \"$BINDIR\""
  68. echo " $BINDIR is normally used for executables, Please choose a different path and retry!"
  69. echo "$DIVIDING_LINE"
  70. exit 1
  71. elif ! mkdir -p "$location" 2>/dev/null || [ ! -w "$location" ]; then
  72. echo " 💀 ERROR: You don't have write access to $location or it is invalid"
  73. exit 1
  74. fi
  75. mkdir -p "$APPMANCONFIG" || exit 1
  76. echo "${location%/}" > "$APPMANCONFIG"/appman-config || exit 1
  77. echo "$DIVIDING_LINE"
  78. echo " You are ready! Start installing your favorite apps locally!"
  79. echo " All apps will be installed in $location"
  80. echo " In case of problems, use the option \"-h\"."
  81. echo "$DIVIDING_LINE"
  82. fi
  83. }
  84. function _appman() {
  85. _appman_check
  86. if ! grep -q "^/" "$APPMANCONFIG"/appman-config; then
  87. APPSDIR="$HOME/$(head -1 "$APPMANCONFIG"/appman-config 2>/dev/null)"
  88. else
  89. APPSDIR="$(head -1 "$APPMANCONFIG"/appman-config 2>/dev/null)"
  90. fi
  91. [ -n "$APPSDIR" ] && mkdir -p "$APPSDIR"/appman || exit 1
  92. mkdir -p "$BINDIR" "$DATADIR"/applications "$DATADIR"/icons || exit 1
  93. AMCLI="appman"
  94. AMCLIPATH="$DIR/$AMCLI"
  95. SUDOCMD=""
  96. APPSPATH="$APPSDIR"
  97. AMPATH="$APPSDIR/$AMCLI"
  98. _create_cache_dir
  99. if [ ! -w "$APPSPATH" ]; then
  100. echo " ERROR: You don't have write access to $APPSPATH"
  101. exit 1
  102. elif ! echo "$PATH" | grep "$BINDIR" >/dev/null 2>&1; then
  103. echo "$DIVIDING_LINE"
  104. echo " ⚠️ WARNING: \"$BINDIR\" is not in PATH, apps may not run."
  105. echo "$DIVIDING_LINE"
  106. fi
  107. MODULES_PATH="$AMPATH/modules"
  108. mkdir -p "$MODULES_PATH" || exit 1
  109. }
  110. # "AM" CORE VARIABLES
  111. function _am() {
  112. AMCLI="am"
  113. AMCLIPATH="$AMCLI"
  114. if command -v sudo >/dev/null 2>&1; then
  115. export SUDOCMD="sudo"
  116. elif command -v doas >/dev/null 2>&1; then
  117. export SUDOCMD="doas"
  118. else
  119. echo 'ERROR: No sudo or doas found'
  120. exit 1
  121. fi
  122. APPSPATH="/opt"
  123. AMPATH="$APPSPATH/$AMCLI"
  124. _create_cache_dir
  125. MODULES_PATH="$AMPATH/modules"
  126. }
  127. # DETERMINE WHEN TO USE "AM" OR "APPMAN"
  128. if [ "$(realpath "$0")" = "/opt/am/APP-MANAGER" ]; then
  129. _am
  130. mkdir -p "$MODULES_PATH" || exit 1
  131. elif [ "$(realpath "$0")" = "/usr/bin/am" ]; then
  132. _am
  133. AMPATH="$AMCACHEDIR"
  134. MODULES_PATH="/usr/lib/am/modules"
  135. else
  136. _appman
  137. fi
  138. function _detect_appman_apps() {
  139. [ -f "$APPMANCONFIG/appman-config" ] && APPMAN_APPSPATH=$(<"$APPMANCONFIG/appman-config")
  140. if ! echo "$APPMAN_APPSPATH" | grep -q "^/"; then
  141. [ -f "$APPMANCONFIG/appman-config" ] && APPMAN_APPSPATH="$HOME/$(<"$APPMANCONFIG/appman-config")"
  142. fi
  143. }
  144. function _determine_args() {
  145. ARGPATHS=$(find "$APPSPATH" -maxdepth 2 -name 'remove' -printf " %h\n" 2>/dev/null | sort -u | sed 's/ //g')
  146. ARGS=$(echo "$ARGPATHS" | xargs -n 1 basename 2>/dev/null)
  147. if [ "$AMCLI" = am ]; then
  148. _detect_appman_apps
  149. if [ -d "$APPMAN_APPSPATH" ]; then
  150. APPMAN_PATHS=$(find "$APPMAN_APPSPATH" -maxdepth 2 -name 'remove' -printf " %h\n" 2>/dev/null | sort -u | sed 's/ //g')
  151. ARGPATHS=$(echo -e "$ARGPATHS\n$APPMAN_PATHS")
  152. ARGS=$(echo "$ARGPATHS" | xargs -n 1 basename 2>/dev/null)
  153. fi
  154. fi
  155. # use "argpath=$(echo "$ARGPATHS" | grep "/$arg$")" to determine the full path of "arg"
  156. }
  157. function _icon_theme_export_to_datadir() {
  158. PNG="$(file "$APPSPATH"/*/icons/* | grep -i '.png' | awk -F":" '{print $1}' | grep -vi .png)"
  159. SVG="$(file "$APPSPATH"/*/icons/* | grep -i '.svg' | awk -F":" '{print $1}' | grep -vi .svg)"
  160. for file in $PNG; do ln -s "$file" "${file}".png; done
  161. for file in $SVG; do ln -s "$file" "${file}".svg; done
  162. if [ -n "$APPMAN_APPSPATH" ]; then
  163. PNG="$(file "$APPMAN_APPSPATH"/*/icons/* | grep -i '.png' | awk -F":" '{print $1}' | grep -vi .png)"
  164. SVG="$(file "$APPMAN_APPSPATH"/*/icons/* | grep -i '.svg' | awk -F":" '{print $1}' | grep -vi .svg)"
  165. for file in $PNG; do ln -s "$file" "${file}".png; done
  166. for file in $SVG; do ln -s "$file" "${file}".svg; done
  167. fi
  168. mkdir -p "$DATADIR"/icons/hicolor/scalable/apps
  169. find "$DATADIR"/icons/hicolor/scalable/apps -xtype l -exec rm {} \;
  170. ln -s "$APPSPATH"/*/icons/*.* "$DATADIR"/icons/hicolor/scalable/apps
  171. [ -n "$APPMAN_APPSPATH" ] && ln -s "$APPMAN_APPSPATH"/*/icons/*.* "$DATADIR"/icons/hicolor/scalable/apps
  172. }
  173. ################################################################################
  174. # FINALIZE
  175. ################################################################################
  176. AMCLIUPPER=$(echo "$AMCLI" | tr '[:lower:]' '[:upper:]')
  177. # Create new data directory and move important files there
  178. AMDATADIR="$DATADIR/AM"
  179. mkdir -p "$AMDATADIR"
  180. # DEVELOPER MODE
  181. if test -f "$AMDATADIR"/betatester; then
  182. AMREPO="https://raw.githubusercontent.com/ivan-hc/AM/dev"
  183. AMBRANCH=$(basename "$AMREPO")
  184. MODULES_SOURCE="$AMREPO/modules"
  185. fi
  186. function _betatester_message_on() {
  187. [ -f "$AMDATADIR"/betatester ] \
  188. && echo -e "$DIVIDING_LINE\n\"$AMCLIUPPER\" $AMVERSION: DEVELOPER MODE\n$DIVIDING_LINE"
  189. }
  190. # Apps database in use
  191. APPSDB="$AMREPO/programs/$arch"
  192. APPSLISTDB="$AMREPO/programs/$arch-apps"
  193. ################################################################################
  194. # SECURITY
  195. ################################################################################
  196. # SAFETY CHECKS
  197. function _am_dependences_check() {
  198. # Check for essential commands required by the application
  199. missing_deps=()
  200. AMDEPENDENCES="cat chmod chown curl grep less sed wget"
  201. for name in $AMDEPENDENCES; do
  202. if ! command -v "$name" &>/dev/null; then
  203. missing_deps+=("$name")
  204. fi
  205. done
  206. # Exit if any essential command is missing
  207. if [ -n "$missing_deps" ]; then
  208. echo "$DIVIDING_LINE"
  209. printf " ${RED}💀 ERROR! MISSING ESSENTIAL COMMANDS\033[0m: %s\n\n Install the above and try again! \n" "${missing_deps[*]}"
  210. echo -e "$DIVIDING_LINE\n ${Green}List of the $AMCLIUPPER $AMVERSION core dependences\033[0m:\n"
  211. echo "$AMDEPENDENCES" | tr ' ' ',' | sed 's/,/, /g' | sed 's/^/ /g'
  212. echo -e "\n$DIVIDING_LINE"
  213. echo " If this message appears it is because you are missing some dependency"
  214. echo " and if its the first time its because something new has been introduced."
  215. echo -e "\n See ${LightBlue}https://github.com/ivan-hc/AM#core-dependences\033[0m for more information\n$DIVIDING_LINE"
  216. exit 1
  217. fi
  218. }
  219. function _check_ubuntu_mess() {
  220. if ! unshare --user -p /bin/true >/dev/null 2>&1; then
  221. echo "$DIVIDING_LINE"
  222. echo ""
  223. echo -e " ${RED}⚠️ WARNING: ACCESS TO USER NAMESPACES IS RESTRICTED! \033[0m"
  224. echo ""
  225. echo " Some apps may not run, you need to enable access to user namespaces,"
  226. echo -e " please visit ${LightBlue}https://github.com/ivan-hc/AM#ubuntu-mess\033[0m to know more."
  227. echo ""
  228. echo "$DIVIDING_LINE"
  229. fi
  230. }
  231. _am_dependences_check
  232. _check_ubuntu_mess
  233. # Function to check online connections (uses github.com by default, as the database and CLI itself are stored/hosted there)
  234. function _online_check() {
  235. if ! wget -q --tries=10 --timeout=20 --spider https://github.com; then
  236. echo -e "\n $AMCLI is offline, please check your internet connection and try again\n"
  237. exit 0
  238. fi
  239. }
  240. # BLACKLIST FILES
  241. appimagelauncher_msg="Your installation of AppImageLauncher may have been done via DEB, RPM, or AUR, which interrupts the \
  242. natural operation of \"systemd-binfmt\" in addition to launching the aforementioned daemon. To avoid problems with \"$AMCLIUPPER\" \
  243. and any other AppImages helper, it's preferable to use \"only\" the standalone AppImage of AppImageLauncher, whose official \
  244. updated release can also be installed via \"$AMCLIUPPER\". But as long as you have the currently installed version, you can't use this CLI."
  245. function _blacklisted_file() {
  246. echo ""
  247. echo -e " ${RED}💀WARNING! Detected \"$blacklisted_file\"\033[0m"
  248. echo ""
  249. echo "It will prevent \"$AMCLIUPPER\" from working correctly with AppImages, especially when extracting, integrating and updating them." | fold -sw 77 | sed 's/^/ /g'
  250. echo ""
  251. if echo "$blacklisted_file" | grep -q appimagelauncherd; then
  252. echo "$appimagelauncher_msg" | fold -sw 77 | sed 's/^/ /g'
  253. echo "" && echo " Please remove \"AppImageLauncher\", reboot and retry!"
  254. else
  255. echo " Please remove \"$blacklisted_file\", reboot and retry!"
  256. fi
  257. echo ""
  258. exit 0
  259. }
  260. if command -v appimaged &>/dev/null; then
  261. blacklisted_file=$(command -v appimaged)
  262. _blacklisted_file
  263. elif command -v appimagelauncherd &>/dev/null; then
  264. blacklisted_file=$(command -v appimagelauncherd)
  265. _blacklisted_file
  266. fi
  267. ################################################################################
  268. # 3RD PARTY
  269. ################################################################################
  270. function _use_newrepo() {
  271. [ -z "$2" ] && echo " USAGE: $AMCLI $1 [ARGUMENT]" && exit 1
  272. case $2 in
  273. 'add')
  274. [ -z "$3" ] && echo -e " USAGE: $AMCLI $1 $2 /path/to/dir\n $AMCLI $1 $2 {URL}" && exit 1
  275. echo "$3" >> "$AMDATADIR/newrepo-lists"
  276. ;;
  277. 'enable'|'on')
  278. [ ! -f "$AMDATADIR/newrepo-lists" ] && echo " ERROR, \"$AMDATADIR/newrepo-lists\" file not found" && exit 1
  279. [ -f "$AMDATADIR/newrepo-off" ] && mv "$AMDATADIR/newrepo-off" "$AMDATADIR/newrepo-on" && echo " New repo ON!"
  280. ;;
  281. 'disable'|'off')
  282. [ ! -f "$AMDATADIR/newrepo-lists" ] && echo " ERROR, \"$AMDATADIR/newrepo-lists\" file not found" && exit 1
  283. [ -f "$AMDATADIR/newrepo-on" ] && mv "$AMDATADIR/newrepo-on" "$AMDATADIR/newrepo-off" && echo " New repo OFF!"
  284. ;;
  285. 'info')
  286. echo -e " Source: $AMREPO\n Apps: $APPSDB\n List: $APPSLISTDB"
  287. ;;
  288. 'purge')
  289. [ -f "$AMDATADIR/newrepo-lists" ] && rm -f "$AMDATADIR"/newrepo* && echo " Removed all 3rd party repositories"
  290. ;;
  291. 'select')
  292. [ ! -f "$AMDATADIR/newrepo-lists" ] && echo " ERROR, \"$AMDATADIR/newrepo-lists\" file not found" && exit 1
  293. echo -e "Select a repo from the list or press CTRL+C to abort:\n$DIVIDING_LINE\n"; sleep 1
  294. select repo in $(sort -u "$AMDATADIR/newrepo-lists" | uniq); do
  295. test -n "$repo" && break
  296. echo ">>> Invalid Selection"
  297. done
  298. echo "$repo" > "$AMDATADIR/newrepo-on"
  299. ;;
  300. esac
  301. }
  302. # 3RD PARTY DATABASES
  303. function _am_newrepo_check() {
  304. # Determine if the CLI uses the "main" branch of https://github.com/ivan-hc/AM or an alternative one
  305. if [ -f "$AMDATADIR/newrepo-on" ]; then
  306. if grep -q "^http" "$AMDATADIR/newrepo-on"; then
  307. AMREPO=$(<"$AMDATADIR/newrepo-on")
  308. elif grep -q "^/" "$AMDATADIR/newrepo-on"; then
  309. AMREPO="file://$(<"$AMDATADIR/newrepo-on")"
  310. fi
  311. AMBRANCH=$(basename "$AMREPO")
  312. export APPSDB="$AMREPO/programs/$arch"
  313. export APPSLISTDB="$AMREPO/programs/$arch-apps"
  314. export MODULES_PATH="$AMPATH/modules"
  315. export AMCATALOGUEMARKDOWNS=""
  316. export AMCATALOGUEICONS=""
  317. [ "$1" != "newrepo" ] && [ "$1" != "neodb" ] && echo -e "$DIVIDING_LINE\n Source: $AMREPO\n$DIVIDING_LINE"
  318. fi
  319. }
  320. _am_newrepo_check "$@"
  321. # 3RD PARTY SOURCES -- TOOLPACK
  322. toolpack_repo="https://github.com/Azathothas/Toolpacks"
  323. toolpack_readme="https://bin.pkgforge.dev/${ARCH}/AM.txt"
  324. export toolpack_name="1" toolpack_description="2" toolpack_site="3" toolpack_dl="4" toolpack_ver="5"
  325. ################################################################################
  326. # UTILITIES
  327. ################################################################################
  328. # COMPLETION LIST
  329. available_options="about add apikey backup clean config disable downgrade download enable extra files home icons info \
  330. install install-appimage launcher list lock neodb newrepo nolibfuse off on overwrite purge query remove sandbox \
  331. select sync template test unlock update --all --appimages --apps --byname --config --convert --debug \
  332. --devmode-disable --devmode-enable --disable-notifications --enable-notifications --force-latest --home --icons \
  333. --launcher --less --pkg --rollback --disable-sandbox --sandbox --system --toolpack --user"
  334. function _completion_lists() {
  335. # Remove existing lists and download new ones
  336. curl -Ls "$APPSLISTDB" > "$AMDATADIR/$arch-apps"
  337. awk -v FS="(◆ | : )" '{print $2}' <"$AMDATADIR"/"$arch"-apps > "$AMDATADIR"/list
  338. [ -f "$AMDATADIR"/"$ARCH"-toolpack ] && awk '{print $2}' "$AMDATADIR"/"$ARCH"-toolpack | sed -e 's/$/.toolpack/' >> "$AMDATADIR"/list
  339. # Append options to the list
  340. for o in $available_options; do
  341. echo "$o" >> "$AMDATADIR"/list
  342. done
  343. }
  344. # BASH AND ZSH COMPLETION
  345. completion_file="$DATADIR/bash-completion/completions/$AMCLI"
  346. mkdir -p "$DATADIR/bash-completion/completions" || exit 1
  347. [ -f "$HOME"/.bash_completion ] && sed -i "/ $AMCLI$/d" "$HOME"/.bash_completion
  348. if ! grep -o " $AMCLI$" "$completion_file" >/dev/null 2>&1; then
  349. echo "complete -W \"\$(cat $AMDATADIR/list 2>/dev/null)\" $AMCLI" >> "$completion_file"
  350. if [ -f "${ZDOTDIR:-$HOME}"/.zshrc ] && echo "$SHELL" | grep -q "zsh"; then
  351. cat <<-HEREDOC >> "${ZDOTDIR:-$HOME}"/.zshrc
  352. autoload bashcompinit
  353. bashcompinit
  354. source "$completion_file"
  355. HEREDOC
  356. fi
  357. echo "Shell completion has been enabled!"
  358. fi
  359. # VERSION OF THE INSTALLED APPS
  360. # Filters
  361. function _check_version_filters() {
  362. sed -E "s/$arch|amd64|x86-64|x64|basic|standard|full|help|Qt[0-9]//g; s/-/\n/g; s/_/\n/g;" |\
  363. grep -vi "appimage\|$arg\|?\|tar." | grep "[0-9]" | head -1 | sed 's/^v//g; s/^\.//g; s/\.$//g;'
  364. }
  365. function _check_version_grep_numbers() {
  366. grep -Eo "([0-9]{1,}\.)+[0-9]{1,}" | head -1
  367. }
  368. # Versions
  369. function _check_version_if_any_version_reference_is_somewhere() {
  370. APPVERSION=$(grep -i "version=" "$argpath"/* 2>/dev/null | _check_version_grep_numbers)
  371. }
  372. function _check_version_if_version_file_exists() {
  373. APPVERSION=$(sort "$argpath"/version | head -1 | sed 's:.*/::' | _check_version_filters)
  374. if [ -z "$APPVERSION" ]; then
  375. if grep -q "download$" "$argpath"/version; then
  376. APPVERSION=$(sort "$argpath"/version | tr '/' '\n' | _check_version_filters)
  377. elif grep -q "://" "$argpath"/version; then
  378. APPVERSION=$(sort "$argpath"/version | tr '/' '\n' | _check_version_grep_numbers)
  379. elif grep -q "/v[0-9]*" "$argpath"/version; then
  380. APPVERSION=$(sort "$argpath"/version | tr '/' '\n' | grep "^v[0-9]" | head -1 | sed 's/^v//g')
  381. elif [ "$(sort "$argpath"/version | wc -w)" = 1 ]; then
  382. APPVERSION=$(sort "$argpath"/version | head -1)
  383. fi
  384. fi
  385. if [ -z "$APPVERSION" ]; then
  386. if grep -q "http.*download/.*[0-9].*/" "$argpath"/version; then
  387. APPVERSION=$(sort "$argpath"/version | tr '/-' '\n' | grep "[0-9]" | _check_version_filters | tail -1)
  388. fi
  389. fi
  390. }
  391. function _check_version_if_an_updater_exists() {
  392. APPVERSION=$("$argpath"/updater -d "$argpath"/"$arg" 2>/dev/null | grep -i "$arg" |\
  393. _check_version_grep_numbers)
  394. [ -z "$APPVERSION" ] && _check_version_if_any_version_reference_is_somewhere
  395. }
  396. function _check_version_if_library() {
  397. LIBNAME=$(sort "$argpath"/remove | tr ' ' '\n' | grep "usr/local/lib" | head -1 | sed 's:.*/::')
  398. APPVERSION=$(find /usr/local/lib -type f -name "$LIBNAME" -type f | sed 's:.*.so.::' | tail -1)
  399. }
  400. function _check_version_if_binary_in_place() {
  401. APPVERSION=$(date -r "$argpath"/"$arg" "+%Y.%m.%d")
  402. }
  403. function _check_version() {
  404. rm -f "$AMCACHEDIR"/version-args
  405. _determine_args
  406. for arg in $ARGS; do
  407. argpath=$(echo "$ARGPATHS" | grep "/$arg$")
  408. if test -f "$argpath"/remove 2>/dev/null; then
  409. if test -f "$argpath"/version 2>/dev/null; then
  410. _check_version_if_version_file_exists
  411. elif test -f "$argpath"/updater 2>/dev/null; then
  412. _check_version_if_an_updater_exists
  413. elif [ "$arg" = "$AMCLI" ]; then
  414. APPVERSION="$AMVERSION"
  415. elif grep -qi "version=" "$argpath"/* 2>/dev/null; then
  416. _check_version_if_any_version_reference_is_somewhere
  417. elif echo "$arg" | grep -q "ffwa-"; then
  418. APPVERSION="WebApp"
  419. elif grep -q "usr/local/lib" "$argpath"/remove 2>/dev/null; then
  420. _check_version_if_library
  421. else
  422. APPVERSION="unknown"
  423. fi
  424. if [ -z "$APPVERSION" ]; then
  425. [ -f "$argpath"/"$arg" ] && _check_version_if_binary_in_place || APPVERSION="unknown"
  426. fi
  427. echo " ◆ $arg | $APPVERSION" >> "$AMCACHEDIR"/version-args
  428. fi
  429. done
  430. }
  431. function _check_version_for_auto_updatable_apps() {
  432. _determine_args
  433. for arg in $ARGS; do
  434. argpath=$(echo "$ARGPATHS" | grep "/$arg$")
  435. if test -f "$argpath"/updater 2>/dev/null; then
  436. _check_version_if_an_updater_exists
  437. OLDAPPVERSION=$(grep " ◆ $arg |" "$AMCACHEDIR"/version-args | tr '|' '\n' | sed 's/ //g' | head -2 | tail -1)
  438. sed -i "/ ◆ $arg |/s#$OLDAPPVERSION#$APPVERSION#" "$AMCACHEDIR"/*
  439. fi
  440. done
  441. }
  442. if test -f "$AMCACHEDIR"/version-args; then
  443. _check_version_for_auto_updatable_apps 2>/dev/null
  444. fi
  445. # This function removes all info and versions from the register
  446. function _remove_info_files() {
  447. rm -f "$AMCACHEDIR"/files*
  448. rm -f "$AMCACHEDIR"/version-args
  449. }
  450. ################################################################################
  451. # APIKEY
  452. ################################################################################
  453. ghapikey_file="$AMDATADIR/ghapikey.txt"
  454. # Set header authorization if GitHub API key file exists
  455. [ -f "$ghapikey_file" ] && HeaderAuthWithGITPAT=" --header \"Authorization: token $(<"$ghapikey_file")\" "
  456. function _use_apikey() {
  457. case $2 in
  458. 'del'|'delete'|'remove')
  459. [ -f "$ghapikey_file" ] || { echo " ✖ No file named $ghapikey_file has been found"; exit 1; }
  460. rm -f "$ghapikey_file" && echo " ✔ $ghapikey_file has been removed"
  461. exit 0
  462. esac
  463. if [[ "$2" =~ ^(gh[ps]_[a-zA-Z0-9]{36}|github_pat_[a-zA-Z0-9]{22}_[a-zA-Z0-9]{59})$ ]]; then
  464. test_apikey_output_with_wget=$(curl -Ls --header "Authorization: token $2" 'https://api.github.com/repos/ivan-hc/AM/releases' | head -1)
  465. [ -n "$test_apikey_output_with_wget" ] && echo "$2" > "$ghapikey_file" \
  466. && echo "Validation successful!" || echo "ERROR: This is not a valid key!"
  467. else
  468. echo "ERROR: Wrong expression, validation failed!"
  469. fi
  470. }
  471. function _update_github_api_key_in_the_updater_files() {
  472. if [ -f "$ghapikey_file" ]; then
  473. ghapikey=$(<"$ghapikey_file")
  474. updater_files=("$APPSPATH"/*/AM-updater) # Assuming AM-updater is one level deeper
  475. for f in "${updater_files[@]}"; do
  476. if [ -f "$f" ] && grep -q "https://api.github.com" "$f"; then
  477. # Check if the file already contains a valid API key
  478. if ! grep -qE "(gh[ps]_[a-zA-Z0-9]{36}|github_pat_[a-zA-Z0-9]{22}_[a-zA-Z0-9]{59})" "$f"; then
  479. # Insert HeaderAuthWithGITPAT before the GitHub API URL
  480. sed -i "s#https://api.github.com#$HeaderAuthWithGITPAT https://api.github.com#g" "$f"
  481. else
  482. # Replace existing API key with the one from ghapikey.txt
  483. 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"
  484. fi
  485. fi
  486. done
  487. fi
  488. }
  489. ################################################################################
  490. # APPMAN MODE
  491. ################################################################################
  492. 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"
  493. APPMAN_MSG_OFF="$DIVIDING_LINE\n \"AppMan Mode\" disabled! \n$DIVIDING_LINE"
  494. APPMAN_MSG_THINK="$DIVIDING_LINE\nNOTE: You can also choose to simply use \"--user\" as a flag to install apps locally \
  495. (options \"-i\", \"-ia\" and \"-e\") instead of going fully into \"AppMan Mode\". \"AM\" can handle local applications as well.\n$DIVIDING_LINE"
  496. function _use_appman() {
  497. _online_check
  498. [ "$CLI" = appman ] && echo " This function only works for AM" && exit 0
  499. echo -e "$APPMAN_MSG_THINK" | fold -sw 77 | sed 's/^/ /g'
  500. read -r -p " Do you wish to enter \"AppMan Mode\" (y,N)?" yn
  501. if ! echo "$yn" | grep -i '^y' >/dev/null 2>&1; then
  502. echo "$DIVIDING_LINE"
  503. else
  504. [ ! -f "$APPMANCONFIG"/appman-mode ] && mkdir -p "$APPMANCONFIG" && touch "$APPMANCONFIG"/appman-mode
  505. _appman && echo -e "$APPMAN_MSG"
  506. fi
  507. }
  508. if [ "$AMCLI" = am ]; then
  509. if test -f "$APPMANCONFIG"/appman-mode; then
  510. [ ! -f "$APPMANCONFIG"/appman-config ] && echo -e "$APPMAN_MSG"
  511. _appman
  512. AMCLIPATH="$(realpath "$0")"
  513. elif [ ! -w "$AMPATH" ]; then
  514. read -r -p " \"AM\" is read-only, want to use it in \"AppMan Mode\" (Y,n)? " yn
  515. if echo "$yn" | grep -i '^n' >/dev/null 2>&1; then
  516. exit 0
  517. else
  518. echo -e "$DIVIDING_LINE\n \"AppMan Mode\" enabled! \n$DIVIDING_LINE"
  519. _use_appman 1>/dev/null
  520. fi
  521. fi
  522. fi
  523. ################################################################################
  524. # CLEAN
  525. ################################################################################
  526. function _clean_amcachedir_message() {
  527. _clean_amcachedir
  528. [ "$AMCLI" = am ] && [ -d "$CACHEDIR"/am ] && echo " ✔ Clear the contents of $CACHEDIR/am"
  529. [ -d "$CACHEDIR"/appman ] && echo " ✔ Clear the contents of $CACHEDIR/appman"
  530. }
  531. function _clean_all_home_cache_directories_of_appimages() {
  532. for arg in $ARGPATHS; do
  533. if test -d "$arg"/*.home/.cache; then
  534. rm -Rf "$arg"/*/*.home/.cache/* && echo " ✔ Clear the contents of $arg/*.home/.cache"
  535. fi
  536. done
  537. }
  538. function _clean_all_tmp_directories_from_appspath() {
  539. for arg in $ARGPATHS; do
  540. if test -d "$arg"/tmp; then
  541. rm -Rf "$arg"/tmp && echo " ✔ Removed $arg/tmp"
  542. fi
  543. done
  544. }
  545. function _clean_launchers() {
  546. if test -d "$DATADIR"/applications/AppImages; then
  547. for var in "$DATADIR"/applications/AppImages/*.desktop; do
  548. # full path to appimage
  549. appimagename=$(grep "Exec=" 0<"$var" 2>/dev/null | head -1 | cut -c 6- | sed 's/"//g; s/\s.*$//')
  550. # name of the appimage
  551. launcher2del=$(basename -- "$(echo "$appimagename" | tr '[:upper:]' '[:lower:]')")
  552. # removable mount point where the appimage may be stored
  553. mountpoint=$(echo "$appimagename" | cut -d'/' -f1-4)
  554. if ! test -f "$appimagename"; then
  555. if echo "$appimagename" | grep -q "^/media/\|^/mnt/"; then
  556. mountpoint=$(echo "$appimagename" | cut -d'/' -f1-4)
  557. unmounted_point=$(echo "$mountpoint" | cut -d'/' -f1-2)
  558. elif echo "$appimagename" | grep -q "^/run/media/"; then
  559. mountpoint=$(echo "$appimagename" | cut -d'/' -f1-5)
  560. unmounted_point="/run/media"
  561. else
  562. mountpoint=""
  563. fi
  564. if [ -n "$mountpoint" ] && ! test -d "$mountpoint"; then
  565. echo " ✖ ERROR: cannot remove \"$(basename "$var")\""
  566. echo " related AppImage is located in an unmounted path of $unmounted_point"
  567. else
  568. rm -f "$var"
  569. [ -n "$BINDIR" ] && [ -n "$launcher2del" ] && rm -f "$BINDIR"/"$launcher2del"*
  570. fi
  571. fi
  572. done
  573. grep -q "^Exec=/media/\|^Exec=/mnt/\|^Exec=/run/media/\|^Exec=\"/media/\|^Exec=\"/mnt/\|^Exec=\"/run/media/" "$DATADIR"/applications/AppImages/* && mountpoint_enabled=1
  574. [ -z "$mountpoint_enabled" ] && [ -n "$BINDIR" ] && cd "$BINDIR" && find . -xtype l -delete
  575. echo ' ✔ Removed orphaned launchers produced with the "--launcher" option'
  576. rmdir "$DATADIR"/applications/AppImages
  577. else
  578. [ -n "$BINDIR" ] && cd "$BINDIR" && find . -xtype l -delete
  579. fi
  580. }
  581. function _clean_old_modules() {
  582. MODULES=$(sort "$(realpath "$0")" | tr '"' '\n' | grep "[a-z]\.am$" | uniq)
  583. [ -z "$MODULES_PATH" ] && exit 1
  584. for m in "$MODULES_PATH"/*; do
  585. if [[ "${MODULES}" != *"$(basename -- "$m")"* ]];then
  586. rm -f "$m" 2>/dev/null
  587. echo " ✔ Removed obsolete module named \"$(basename -- "$m")\""
  588. fi
  589. done
  590. }
  591. function _use_clean() {
  592. echo " Cleaning temporary files and folders..." && sleep 0.1
  593. for i in {100..000}; do
  594. echo -ne " $i\r" && sleep 0.0001
  595. done
  596. _detect_appman_apps
  597. _determine_args
  598. _clean_amcachedir_message
  599. _clean_all_home_cache_directories_of_appimages
  600. _clean_all_tmp_directories_from_appspath
  601. _clean_launchers 2>/dev/null
  602. _clean_old_modules
  603. }
  604. ################################################################################
  605. # SYNC
  606. ################################################################################
  607. function _sync_installation_scripts() {
  608. echo -e "$DIVIDING_LINE\n Checking for changes of the installation scripts in the online database..."
  609. _determine_args
  610. for arg in $ARGS; do
  611. argpath=$(echo "$ARGPATHS" | grep "/$arg$")
  612. if [ -f "$argpath"/AM-updater ]; then
  613. mkdir -p "$argpath"/.am-installer
  614. if test -f "$argpath/.am-installer"/*; then
  615. scriptname=$(ls "$argpath/.am-installer/" | head -1)
  616. CURRENT=$(cat "$argpath"/.am-installer/"$scriptname")
  617. SOURCE=$(curl -Ls "$APPSDB"/"$scriptname")
  618. if [ "$CURRENT" = "$SOURCE" ]; then
  619. echo -ne "\r" 2>/dev/null
  620. else
  621. echo -e " ◆ Changed https://github.com/ivan-hc/AM/blob/main/programs/$arch/$scriptname"
  622. fi
  623. else
  624. if curl --output /dev/null --silent --head --fail "$APPSDB"/"$arg" 1>/dev/null; then
  625. echo -e " ◆ No installation script for $arg, downloading one..."
  626. mkdir -p "$argpath"/.am-installer
  627. wget -q "$APPSDB/$arg" -O "$argpath"/.am-installer/"$arg"
  628. fi
  629. fi
  630. fi
  631. done
  632. }
  633. function _sync_appimages_list() {
  634. APPIMAGES_LIST="https://raw.githubusercontent.com/Portable-Linux-Apps/Portable-Linux-Apps.github.io/refs/heads/main/x86_64-appimages"
  635. if [ "$ARCH" = x86_64 ]; then
  636. curl -Ls "$APPIMAGES_LIST" > "$AMDATADIR/$ARCH-appimages"
  637. else
  638. rm -f "$AMDATADIR/$ARCH-appimages"
  639. APPIMAGE_NAMES=$(curl -Ls "$APPIMAGES_LIST" | awk -v FS="(◆ | : )" '{print $2}')
  640. for appimage in $APPIMAGE_NAMES; do
  641. grep "◆ $appimage :" "$AMDATADIR/$ARCH-apps" >> "$AMDATADIR/$ARCH-appimages" &
  642. done
  643. wait
  644. fi
  645. }
  646. function _sync_toolpacks_list() {
  647. rm -f "$AMDATADIR/$ARCH-toolpack"
  648. curl -Ls "$toolpack_readme" | grep -v "\.appimage \|?" | cut -d":" -f1 | cut -d"@" -f2 | sed 's/^| /◆ /g; s/ | https$/. To install it use the "--toolpack" flag./g; s/ | / : /g' > "$AMDATADIR/$ARCH-toolpack"
  649. }
  650. function _sync_databases() {
  651. echo -e "$DIVIDING_LINE\n Check and update offline lists of additional databases..."
  652. _sync_appimages_list
  653. _sync_toolpacks_list
  654. _completion_lists
  655. }
  656. function _sync_modules() {
  657. echo -e "$DIVIDING_LINE\n Check for updates in modules..."
  658. MODULES=$(curl -Ls "$AMREPO/APP-MANAGER" | tr '"' '\n' | grep "[a-z]\.am$")
  659. for module_name in $MODULES; do
  660. cd "$MODULES_PATH" || return 1
  661. if ! test -f ./"$module_name"; then
  662. echo " ◆ Downloading $module_name (not previously installed)..."
  663. curl -Os "$MODULES_SOURCE/$module_name" 2>/dev/null
  664. chmod a+x ./"$MODULENAME"
  665. fi
  666. CURRENT=$(cat ./"$module_name" 2>/dev/null)
  667. SOURCE=$(curl -Ls "$MODULES_SOURCE/$module_name")
  668. if [ "$CURRENT" = "$SOURCE" ]; then
  669. echo -ne "\r" 2>/dev/null
  670. else
  671. echo " ◆ Updating $module_name..."
  672. curl -Ls "$MODULES_SOURCE/$module_name" > ./"$module_name" 2>/dev/null
  673. fi
  674. done
  675. _clean_old_modules
  676. }
  677. function _sync_amcli() {
  678. echo "$DIVIDING_LINE"
  679. CURRENT_AM_VERSION="$AMVERSION"
  680. echo -ne "\n ◆ SYNCHRONIZING \"$AMCLIUPPER\" VERSION \"$CURRENT_AM_VERSION\"...\r" && sleep 0.25
  681. _clean_amcachedir 1>/dev/null
  682. cd "$AMCACHEDIR" || return 1
  683. curl -Ls "$AMREPO"/APP-MANAGER > ./APP-MANAGER && chmod a+x ./APP-MANAGER
  684. echo y | mv ./APP-MANAGER "$(realpath "$0")"
  685. NEW_AM_VERSION=$("$AMCLIPATH" -v)
  686. if [ ! "$CURRENT_AM_VERSION" = "$NEW_AM_VERSION" ]; then
  687. echo -ne " A new release of \"$AMCLIUPPER\" is available, please wait...\r"
  688. echo " ◆ \"$AMCLIUPPER\" IS NOW UPDATED TO THE BRAND NEW \"$NEW_AM_VERSION\" VERSION!"
  689. echo -e "\n Replacement of version \"$CURRENT_AM_VERSION\" currently in use, COMPLETED!"
  690. echo -e "\n See https://github.com/ivan-hc/AM/commits/main\n"
  691. else
  692. echo " ◆ \"$AMCLIUPPER\" IS ALREADY UPDATED, CURRENT VERSION \"$CURRENT_AM_VERSION\""
  693. echo -e "\n See https://github.com/ivan-hc/AM/commits/$AMBRANCH\n"
  694. fi
  695. }
  696. function _use_sync() {
  697. _online_check
  698. _betatester_message_on
  699. _sync_installation_scripts
  700. _sync_databases
  701. if [ "$(realpath "$0")" != "/usr/bin/am" ]; then
  702. _sync_modules
  703. _sync_amcli
  704. fi
  705. echo "$DIVIDING_LINE"
  706. }
  707. ################################################################################
  708. # UPDATE
  709. ################################################################################
  710. function _update_list_updatable_apps() {
  711. _determine_args
  712. _check_version
  713. for arg in $ARGS; do
  714. argpath=$(echo "$ARGPATHS" | grep "/$arg$")
  715. if [ -d "$argpath" ]; then
  716. if [ -f "$argpath/AM-updater" ]; then
  717. app_version=$(grep -w " ◆ $arg |" "$AMCACHEDIR/version-args" | sed 's:.*| ::')
  718. echo " ◆ $arg $app_version" >> "$AMCACHEDIR"/updatable-args-list
  719. fi
  720. fi
  721. done
  722. }
  723. function _update_determine_apps_version_changes() {
  724. if test -f "$AMCACHEDIR"/updatable-args-list; then
  725. mv "$AMCACHEDIR"/updatable-args-list "$AMCACHEDIR"/updatable-args-list-old
  726. _update_list_updatable_apps
  727. OLDVER="$AMCACHEDIR/updatable-args-list-old"
  728. NEWVER="$AMCACHEDIR/updatable-args-list"
  729. if cmp --silent -- "$NEWVER" "$OLDVER"; then
  730. echo ' Nothing to do here!'
  731. else
  732. echo -e " The following apps have been updated:\n"
  733. diff --new-line-format="" --unchanged-line-format="" "$NEWVER" "$OLDVER"
  734. echo ""
  735. fi
  736. else
  737. echo ' No apps to update here!'
  738. fi
  739. }
  740. function _update_updated_app_msg() {
  741. end=$(date +%s)
  742. echo " ◆ $APPNAME is updated, $((end - start)) seconds elapsed!"
  743. }
  744. function _update_run_updater() {
  745. if grep -q "api.github.com" "$argpath"/AM-updater; then
  746. 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)
  747. if [ -z "$GH_API_ALLOWED" ]; then
  748. if command -v torsocks 1>/dev/null; then
  749. torsocks "$argpath"/AM-updater >/dev/null 2>&1 && _update_updated_app_msg
  750. else
  751. echo " ✖ $APPNAME cannot be updated, you have reached GitHub API limit. Install \"torsocks\" from your system package manager and retry!" \
  752. | fold -sw 72 | sed 's/^/ /g; s/ ✖/✖/g'
  753. fi
  754. else
  755. "$argpath"/AM-updater >/dev/null 2>&1 && _update_updated_app_msg
  756. fi
  757. else
  758. "$argpath"/AM-updater >/dev/null 2>&1 && _update_updated_app_msg
  759. fi
  760. }
  761. function _update_app() {
  762. APPNAME=$(echo "$arg" | tr '[:lower:]' '[:upper:]')
  763. start=$(date +%s)
  764. if [ -w "$argpath"/AM-updater ]; then
  765. _update_run_updater &
  766. else
  767. echo " ✖ $APPNAME is read-only, cannot update it!"
  768. fi
  769. }
  770. function _update_all_apps() {
  771. for arg in $ARGS; do
  772. argpath=$(echo "$ARGPATHS" | grep "/$arg$")
  773. cd "$argpath" || exit 1
  774. arg=$(printf '%s\n' "${PWD##*/}")
  775. if test -f "$argpath"/AM-updater; then
  776. _update_app
  777. fi
  778. done
  779. wait
  780. echo "$DIVIDING_LINE"
  781. _update_determine_apps_version_changes
  782. rm -Rf "$APPSPATH"/*/tmp
  783. [ -d "$APPMAN_APPSPATH" ] && rm -Rf "$APPMAN_APPSPATH"/*/tmp
  784. }
  785. function _use_update() {
  786. _online_check
  787. _update_github_api_key_in_the_updater_files
  788. _clean_all_tmp_directories_from_appspath >/dev/null
  789. case $2 in
  790. ''|'--apps')
  791. _clean_amcachedir
  792. _update_list_updatable_apps
  793. echo -e "$DIVIDING_LINE\n \"$AMCLIUPPER\" CAN MANAGE UPDATES FOR THE FOLLOWING PROGRAMS:\n"
  794. [ -f "$AMCACHEDIR/updatable-args-list" ] && grep "◆" "$AMCACHEDIR/updatable-args-list" | sort || echo " None"
  795. echo -e "\n All self-updatable programs are excluded"
  796. echo -e "$DIVIDING_LINE\n >> START OF ALL PROCESSES <<\n$DIVIDING_LINE"
  797. _update_all_apps
  798. [ -z "$2" ] && echo "$DIVIDING_LINE" && _use_sync
  799. echo -e "$DIVIDING_LINE\n >> END OF ALL PROCESSES << \n$DIVIDING_LINE"
  800. sleep 0.2
  801. exit 0
  802. ;;
  803. *)
  804. _determine_args
  805. ENTRIES="$(echo "$@" | cut -f2- -d ' ')"
  806. for arg in $ENTRIES; do
  807. argpath=$(echo "$ARGPATHS" | grep "/$arg$")
  808. if test -f "$argpath"/AM-updater; then
  809. cd "$argpath" 2>/dev/null || exit 1
  810. _update_app
  811. else
  812. UPDATERS=$(cd "$argpath" 2>/dev/null && find . -name "*update*" -print 2>/dev/null)
  813. [ -n "$UPDATERS" ] && arg_autoupdatable=", it may have its update system"
  814. echo " ✖ Cannot manage updates for \"$(echo "$arg" | tr '[:lower:]' '[:upper:]')\"$arg_autoupdatable"
  815. fi
  816. done
  817. wait
  818. exit 0
  819. ;;
  820. esac
  821. }
  822. function _use_force_latest() {
  823. _online_check
  824. _determine_args
  825. ENTRIES="$(echo "$@" | cut -f2- -d ' ')"
  826. for arg in $ENTRIES; do
  827. argpath=$(echo "$ARGPATHS" | grep "/$arg$")
  828. if ! test -d "$argpath"; then
  829. echo " ERROR: \"$arg\" is not installed, see \"-f\""
  830. elif ! test -f "$argpath"/AM-updater; then
  831. echo " ERROR: \"$AMCLI\" cannot manage updates for \"$arg\""
  832. elif ! grep -q "api.github.com" "$argpath"/AM-updater; then
  833. echo " ERROR: \"$arg\" source is not on Github"
  834. elif ! grep -q "/releases | " "$argpath"/AM-updater; then
  835. echo " ERROR: \"$arg\" does not redirect to a generic \"releases\""
  836. else
  837. sed -i 's#/releases | #/releases/latest | #g' "$argpath"/AM-updater
  838. APPNAME=$(echo "$arg" | tr '[:lower:]' '[:upper:]')
  839. start=$(date +%s)
  840. _update_run_updater
  841. fi
  842. done
  843. }
  844. ################################################################################
  845. # USAGE
  846. ################################################################################
  847. # HANDLE ALL THE EXTERNAL MODULES
  848. function _use_module() {
  849. # Test if module exists
  850. if [ ! -f "$MODULES_PATH/$MODULE" ]; then
  851. _online_check
  852. if ! wget -q "$MODULES_SOURCE/$MODULE" -O "$MODULES_PATH/$MODULE"; then
  853. echo " Module not found, run \"$AMCLI -s\" to update \"$AMCLIUPPER\""
  854. exit 1
  855. fi
  856. chmod a+x "$MODULES_PATH/$MODULE"
  857. fi
  858. # Source module
  859. source "$MODULES_PATH/$MODULE" "$@"
  860. }
  861. case "$1" in
  862. '')
  863. echo " USAGE: $AMCLI [OPTION]"
  864. echo " $AMCLI [OPTION] [ARGUMENT]"
  865. echo ""
  866. echo " Run the \"$AMCLI -h\" command to find out more"
  867. exit 0
  868. ;;
  869. 'about'|'-a'|\
  870. 'files'|'-f'|\
  871. 'list'|'-l'|\
  872. 'query'|'-q')
  873. MODULE="database.am"
  874. if [ -t 1 ]; then _use_module "$@"; else _use_module "$@" | sed -e 's/\x1b\[[0-9;]*m//g'; fi
  875. ;;
  876. 'backup'|'-b'|\
  877. 'downgrade'|'--rollback'|\
  878. 'icons'|'--icons'|\
  879. 'launcher'|'--launcher'|\
  880. 'lock'|'unlock'|\
  881. 'nolibfuse'|\
  882. 'overwrite'|'-o'|\
  883. 'remove'|'-R'|'-r')
  884. MODULE="management.am"
  885. _use_module "$@"
  886. ;;
  887. 'config'|'-C'|'--config'|\
  888. 'home'|'-H'|'--home'|\
  889. 'sandbox'|'--sandbox'|\
  890. '--disable-sandbox')
  891. MODULE="sandboxes.am"
  892. _use_module "$@"
  893. ;;
  894. 'download'|'-d'|\
  895. 'extra'|'-e'|\
  896. 'install'|'-i'|\
  897. 'install-appimage'|'-ia')
  898. MODULE="install.am"
  899. _online_check
  900. [ "$CLI" = am ] && [ -f "$APPMANCONFIG"/appman-mode ] && echo -e "$APPMAN_MSG"
  901. _use_module "$@"
  902. ;;
  903. 'template'|'-t')
  904. MODULE="template.am"
  905. _online_check
  906. _use_module "$@"
  907. ;;
  908. # INBUILT OPTIONS
  909. '--devmode-disable'|'--devmode-enable')
  910. [ "$1" = "--devmode-disable" ] && rm -f "$AMDATADIR"/betatester \
  911. || touch "$AMDATADIR"/betatester && _betatester_message_on
  912. ;;
  913. '--force-latest')
  914. _use_force_latest "$@"
  915. ;;
  916. '--system')
  917. [ -f "$APPMANCONFIG"/appman-mode ] && rm -f "$APPMANCONFIG"/appman-mode && echo -e "$APPMAN_MSG_OFF"
  918. ;;
  919. 'apikey')
  920. _use_apikey "$@"
  921. ;;
  922. 'appman'|'--user')
  923. _use_appman
  924. ;;
  925. 'clean'|'-c')
  926. _use_clean
  927. ;;
  928. 'newrepo'|'neodb')
  929. _use_newrepo "$@"
  930. ;;
  931. 'sync'|'-s')
  932. _use_sync
  933. ;;
  934. 'update'|'-u'|'-U')
  935. _use_update "$@"
  936. ;;
  937. 'version'|'-v'|'--version')
  938. echo "$AMVERSION"
  939. ;;
  940. '--disable-notifications')
  941. _determine_args
  942. for n in $ARGPATHS; do sed -e '/notify-send/ s/^#*/#/' -i "$n/AM-updater" 2>/dev/null; done
  943. ;;
  944. '--enable-notifications')
  945. _determine_args
  946. for n in $ARGPATHS; do sed -e '/notify-send/ s/^#*//' -i "$n/AM-updater" 2>/dev/null; done
  947. ;;
  948. 'help'|'-h')
  949. ################################################################################
  950. # HELP
  951. ################################################################################
  952. function _use_help() {
  953. [ "$CLI" = am ] && [ -f "$APPMANCONFIG"/appman-mode ] && echo -e "$APPMAN_MSG"
  954. echo -e "
  955. NAME: ${Green}$AMCLIUPPER\033[0m VERSION: ${Green}$AMVERSION\033[0m
  956. SYNOPSIS: ${LightBlue}$AMCLI {OPTION}\033[0m
  957. ${LightBlue}$AMCLI {OPTION} {PROGRAM}\033[0m
  958. DESCRIPTION: A command line utility to install and manage AppImages and other portable programs for GNU/Linux thanks to its AUR-inspired database.
  959. OPTIONS:
  960. ${Gold}about, -a\033[0m
  961. ${LightBlue}$AMCLI -a {PROGRAM}\033[0m
  962. Description: Shows more info about one or more apps.
  963. ${Gold}apikey\033[0m
  964. ${LightBlue}$AMCLI apikey {Github Token}
  965. ${LightBlue}$AMCLI apikey delete\033[0m
  966. 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.
  967. ${Gold}backup, -b\033[0m
  968. ${LightBlue}$AMCLI -b {PROGRAM}\033[0m
  969. Description: Create a snapshot of the current version of an installed program.
  970. ${Gold}clean, -c\033[0m
  971. ${LightBlue}$AMCLI -c\033[0m
  972. Description: Removes all the unnecessary files and folders.
  973. ${Gold}config, -C, --config\033[0m
  974. ${LightBlue}$AMCLI -C {PROGRAM}\033[0m
  975. Description: Set a dedicated \$XDD_CONFIG_HOME for one or more AppImages.
  976. ${Gold}downgrade, --rollback\033[0m
  977. ${LightBlue}$AMCLI --rollback {PROGRAM}\033[0m
  978. Description: Download an older or specific app version.
  979. ${Gold}download, -d\033[0m
  980. ${LightBlue}$AMCLI -d {PROGRAM}
  981. ${LightBlue}$AMCLI -d --convert {PROGRAM}\033[0m
  982. Description: Download one or more installation scripts to your desktop or convert them to local installers for \"AppMan\".
  983. ${Gold}extra, -e\033[0m
  984. ${LightBlue}$AMCLI -e user/project {APPNAME}
  985. ${LightBlue}$AMCLI -e user/project {APPNAME} {KEYWORD}\033[0m
  986. 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.
  987. ${Gold}files, -f\033[0m
  988. ${LightBlue}$AMCLI -f
  989. ${LightBlue}$AMCLI -f --byname
  990. ${LightBlue}$AMCLI -f --less\033[0m
  991. 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.
  992. ${Gold}help, -h\033[0m
  993. ${LightBlue}$AMCLI -h\033[0m
  994. Description: Prints this message.
  995. ${Gold}home, -H, --home\033[0m
  996. ${LightBlue}$AMCLI -H {PROGRAM}\033[0m
  997. Description: Set a dedicated \$HOME directory for one or more AppImages.
  998. ${Gold}icons, --icons\033[0m
  999. ${LightBlue}$AMCLI --icons {PROGRAM}
  1000. ${LightBlue}$AMCLI --icons --all\033[0m
  1001. 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.
  1002. ${Gold}install, -i\033[0m
  1003. ${LightBlue}$AMCLI -i {PROGRAM}
  1004. ${LightBlue}$AMCLI -i --debug {PROGRAM}
  1005. ${LightBlue}$AMCLI -i --force-latest {PROGRAM}
  1006. ${LightBlue}$AMCLI -i --icons {PROGRAM}\033[0m
  1007. 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 \"--toolpack\").
  1008. ${Gold}install-appimage, -ia\033[0m
  1009. ${LightBlue}$AMCLI -ia {PROGRAM}
  1010. ${LightBlue}$AMCLI -ia --debug {PROGRAM}
  1011. ${LightBlue}$AMCLI -ia --force-latest {PROGRAM}
  1012. ${LightBlue}$AMCLI -ia --icons {PROGRAM}\033[0m
  1013. Description: Same as \"install\" (see above) but for AppImages only.
  1014. ${Gold}lock\033[0m
  1015. ${LightBlue}$AMCLI lock {PROGRAM}\033[0m
  1016. Description: Prevent an application being updated, if it has an\"AM-updater\" script.
  1017. ${Gold}list, -l\033[0m
  1018. ${LightBlue}$AMCLI -l
  1019. ${LightBlue}$AMCLI -l --all
  1020. ${LightBlue}$AMCLI -l --appimages
  1021. ${LightBlue}$AMCLI -l --toolpack {KEYWORD}\033[0m
  1022. 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 \"--toolpack\").
  1023. ${Gold}newrepo, neodb\033[0m
  1024. ${LightBlue}$AMCLI newrepo add {URL}\\{PATH}
  1025. ${LightBlue}$AMCLI newrepo select
  1026. ${LightBlue}$AMCLI newrepo on\\off
  1027. ${LightBlue}$AMCLI newrepo purge
  1028. ${LightBlue}$AMCLI newrepo info\033[0m
  1029. 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.
  1030. ${Gold}nolibfuse\033[0m
  1031. ${LightBlue}$AMCLI nolibfuse {PROGRAM}\033[0m
  1032. Description: Convert old AppImages and get rid of \"libfuse2\" dependence.
  1033. ${Gold}overwrite, -o\033[0m
  1034. ${LightBlue}$AMCLI -o {PROGRAM}\033[0m
  1035. Description: Overwrite apps with snapshots saved previously (see \"-b\").
  1036. ${Gold}query, -q\033[0m
  1037. ${LightBlue}$AMCLI -q {KEYWORD}
  1038. ${LightBlue}$AMCLI -q --all {KEYWORD}
  1039. ${LightBlue}$AMCLI -q --appimages {KEYWORD}
  1040. ${LightBlue}$AMCLI -q --pkg {PROGRAM1} {PROGRAM2}
  1041. ${LightBlue}$AMCLI -q --toolpack {KEYWORD}\033[0m
  1042. 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 \"--toolpack\").
  1043. ${Gold}remove, -r\033[0m
  1044. ${LightBlue}$AMCLI -r {PROGRAM}\033[0m
  1045. Description: Removes one or more apps, requires confirmation.
  1046. ${Gold}-R\033[0m
  1047. ${LightBlue}$AMCLI -R {PROGRAM}\033[0m
  1048. Description: Removes one or more apps without asking.
  1049. ${Gold}sandbox, --sandbox\033[0m
  1050. ${LightBlue}$AMCLI sandbox {PROGRAM}\033[0m
  1051. Description: Run an AppImage in a sandbox using Aisap.
  1052. ${Gold}sync, -s\033[0m
  1053. ${LightBlue}$AMCLI -s\033[0m
  1054. Description: Updates this script to the latest version hosted.
  1055. ${Gold}template, -t\033[0m
  1056. ${LightBlue}$AMCLI -t {PROGRAM}\033[0m
  1057. Description: Generate a custom installation script.
  1058. ${Gold}unlock\033[0m
  1059. ${LightBlue}$AMCLI unlock {PROGRAM}\033[0m
  1060. Description: Unlock updates for the selected program (nulls \"lock\").
  1061. ${Gold}update, -u, -U\033[0m
  1062. ${LightBlue}$AMCLI -u
  1063. ${LightBlue}$AMCLI -u --apps
  1064. ${LightBlue}$AMCLI -u {PROGRAM}\033[0m
  1065. Description: Update everything. Add \"--apps\" to update only the apps or write only the apps you want to update by adding their names.
  1066. ${Gold}version, -v\033[0m
  1067. ${LightBlue}$AMCLI -v\033[0m
  1068. Description: Shows the version.
  1069. ${Gold}--devmode-disable\033[0m
  1070. ${LightBlue}$AMCLI --devmode-disable\033[0m
  1071. Description: Undo \"--devmode-enable\" (see below).
  1072. ${Gold}--devmode-enable\033[0m
  1073. ${LightBlue}$AMCLI --devmode-enable\033[0m
  1074. Description: Use the development branch (at your own risk).
  1075. ${Gold}--disable-notifications\033[0m
  1076. ${LightBlue}$AMCLI --disable-notifications\033[0m
  1077. Description: Disable notifications during apps update.
  1078. ${Gold}--disable-sandbox\033[0m
  1079. ${LightBlue}$AMCLI --disable-sandbox {PROGRAM}\033[0m
  1080. Description: Disable the sandbox for the selected app.
  1081. ${Gold}--enable-notifications\033[0m
  1082. ${LightBlue}$AMCLI --enable-notifications\033[0m
  1083. Description: Eable notifications during apps update (nulls \"--disable-notifications\").
  1084. ${Gold}--force-latest\033[0m
  1085. ${LightBlue}$AMCLI --force-latest {PROGRAM}\033[0m
  1086. Description: Downgrades an installed app from pre-release to \"latest\".
  1087. ${Gold}--launcher\033[0m
  1088. ${LightBlue}$AMCLI --launcher /path/to/\${APPIMAGE}\033[0m
  1089. 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.
  1090. ${Gold}--system\033[0m
  1091. ${LightBlue}am --system\033[0m
  1092. Description: Switch \"AM\" back to \"AM\" from \"AppMan Mode\" (see \"--user\").
  1093. ${Gold}--toolpack\033[0m
  1094. ${LightBlue}$AMCLI -i --toolpack {PROGRAM}\033[0m
  1095. ${LightBlue}am -i --toolpack --user {PROGRAM}
  1096. ${LightBlue}$AMCLI -l --toolpack
  1097. ${LightBlue}$AMCLI -q --toolpack {KEYWORD}\033[0m
  1098. Description: This is a flag to use in \"-i\" to install Toolpack programs, in \"-l\" to list all available Toolpacks, and \"-q\" to search the Toolpack list. Toolpack is a collection of programs external to the \"AM\" database. Visit $toolpack_repo to learn more.
  1099. NOTE, for installations you can use \".toolpack\" as the package extension instead of using the flag.
  1100. ${Gold}--user\033[0m
  1101. ${LightBlue}am --user\033[0m
  1102. Description: Made \"AM\" run in \"AppMan Mode\", locally, useful for unprivileged users. This option only works with \"AM\".
  1103. The \"--user\" option can also be used just as a flag for installation options. For example:
  1104. - Use it to install applications locally, option \"-i\" or \"install\":
  1105. ${LightBlue}am -i --user {PROGRAM}\033[0m
  1106. - Also suboptions of \"-i\" can work with this flag:
  1107. ${LightBlue}am -i --user --debug {PROGRAM}\033[0m
  1108. ${LightBlue}am -i --user --force-latest {PROGRAM}
  1109. ${LightBlue}am -i --user --icons {PROGRAM}
  1110. ${LightBlue}am -i --user --debug --force-latest {PROGRAM}
  1111. ${LightBlue}am -i --user --debug --force-latest --icons {PROGRAM}\033[0m
  1112. - Same for AppImages only, option \"-ia\" or \"install-appimage\":
  1113. ${LightBlue}am -ia --user {PROGRAM}\033[0m
  1114. ${LightBlue}am -ia --user --debug {PROGRAM}
  1115. ${LightBlue}am -ia --user --force-latest {PROGRAM}
  1116. ${LightBlue}am -ia --user --icons {PROGRAM}
  1117. ${LightBlue}am -ia --user --debug --force-latest {PROGRAM}
  1118. ${LightBlue}am -ia --user --debug --force-latest --icons {PROGRAM}\033[0m
  1119. - External AppImages can be installed like this as well, option \"-e\" or \"extra\":
  1120. ${LightBlue}am -e --user user/project {APPNAME}
  1121. ${LightBlue}am -e --user user/project {APPNAME} {KEYWORD}\033[0m
  1122. NOTE, \"AM\" 9 or higher is also able to, update and manage apps locally, by default, and without having to switch to \"AppMan Mode\".
  1123. $DIVIDING_LINE
  1124. SITES:
  1125. https://github.com/ivan-hc/AM
  1126. https://portable-linux-apps.github.io
  1127. \n" | sed 's/^ //g' | fold -sw 77 | sed 's/^/ /g' | less -Ir
  1128. }
  1129. if [ -t 1 ]; then _use_help; else _use_help | sed -e 's/\x1b\[[0-9;]*m//g'; fi
  1130. ;;
  1131. *)
  1132. exec "$AMCLIPATH"
  1133. ;;
  1134. esac
  1135. # vim:tabstop=4:shiftwidth=4:expandtab