Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
2d10241
Use static binaries as a fallback solution if missing dependencies
ivan-hc May 3, 2026
4ee7477
Merge pull request #2314 from ivan-hc/main
ivan-hc May 3, 2026
742432c
Add unxz and xzcat as opt dependencies
ivan-hc May 3, 2026
7da8a8b
Improve online check, one block for dependencies check
ivan-hc May 4, 2026
25cdd8b
Merge pull request #2317 from ivan-hc/main
ivan-hc May 4, 2026
6a0e9a9
Remove cmp dependency
ivan-hc May 4, 2026
9a2ac8c
Remove diff dependency
ivan-hc May 4, 2026
5c01b5e
Pass the custom PATH to the installation script while running
ivan-hc May 4, 2026
1cc9ff7
Add notify-send as opt dependency
ivan-hc May 4, 2026
bf25ea1
Add checksum on standard dependencies
ivan-hc May 4, 2026
90808b2
Improve checksum on standard dependencies
ivan-hc May 4, 2026
91aba33
Remove dependencies I used for tests
ivan-hc May 4, 2026
b3b33ca
Warn about temporary static binaries / only run checksum if online
ivan-hc May 5, 2026
68e5380
Export custom PATH only if it is not empty
ivan-hc May 5, 2026
0663cf0
Made "fallback binaries" message more user friendly.
ivan-hc May 5, 2026
9557f09
Fix typo
ivan-hc May 5, 2026
3658224
Allow transtaltion of new messages
ivan-hc May 5, 2026
833eb97
Update install.am, remove obsolete checks
ivan-hc May 5, 2026
1d8c5ec
Update install.am - fix installations in AppMan, it don't require PATH
ivan-hc May 5, 2026
3f8ce84
Cache the sha256sum list to improve checksum speed for binaries
ivan-hc May 6, 2026
18475bc
Remove dependencies I use for my tests
ivan-hc May 6, 2026
b1b97a9
Merge pull request #2324 from ivan-hc/main
ivan-hc May 6, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
144 changes: 123 additions & 21 deletions APP-MANAGER
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env bash

AMVERSION="10.1-4"
AMVERSION="10.1-13"

# Determine main repository and branch
AMREPO="https://raw.githubusercontent.com/ivan-hc/AM/main"
Expand Down Expand Up @@ -492,10 +492,119 @@ _validate_and_download_lists_of_archived_and_obsolete_apps() {

# SAFETY CHECKS

# Function to check online connections (uses github.com by default, as the database and CLI itself are stored/hosted there)
_online_check_tool() {
if command -v wget >/dev/null 2>&1; then
wget -q --tries=10 --timeout=20 --spider https://github.com
elif command -v curl >/dev/null 2>&1; then
curl --output /dev/null --silent --head --fail https://github.com 1> /dev/null
else
printf $" ${RED}💀 ERROR! MISSING ESSENTIAL COMMANDS\033[0m: %s\n\n Install the above and try again! \n" "$(echo "curl, wget")"
exit 0
fi
}

_online_check() {
if ! _online_check_tool; then
printf $"\n %b is offline, please check your internet connection and try again\n\n" "$AMCLI"
exit 0
fi
}

_checksum_on_standard_dependencies() {
if [ -f "$CACHEDIR"/AMCACHEPATH/"$name" ]; then
dep_sum256_local=$(sha256sum "$CACHEDIR"/AMCACHEPATH/"$name" 2>/dev/null | awk '{print $1}')
dep_sum256_host=$(sort "$AMCACHEDIR/$ARCH.sha256sum.txt" | grep "$name-$ARCH-static$" 2>/dev/null | awk '{print $1}')
if [ "$dep_sum256_local" != "$dep_sum256_host" ]; then
rm -Rf "$CACHEDIR"/AMCACHEPATH/"$name"
_deps_dl && chmod a+x "$CACHEDIR"/AMCACHEPATH/"$name" && printf $" - %b, downloaded from https://github.com/ivan-hc/am-utils\n" "$name"
fi
fi
}

# Use static binaries as a fallback solution in case there are no dependencies
AM_core_dependencies="cat chmod chown curl grep sed wget"
AM_opt_dependencies="7z ar column file md5sum notify-send sha1sum sha256sum sha512sum tar unxz unzip xz xzcat"
AM_standard_dependencies="$AM_core_dependencies $AM_opt_dependencies"
_deps_dl() {
if command -v curl >/dev/null 2>&1; then
curl -Lo "$CACHEDIR"/AMCACHEPATH/"$name" "$AM_UTILS_SOURCE/$name-$ARCH-static" 2>/dev/null
elif command -v wget >/dev/null 2>&1; then
wget -q "$AM_UTILS_SOURCE/$name-$ARCH-static" -O "$CACHEDIR"/AMCACHEPATH/"$name"
fi
}

if [ "$ARCH" = aarch64 ] || [ "$ARCH" = x86_64 ]; then
mkdir -p "$CACHEDIR"/AMCACHEPATH
# Download static binaries if commands are not available
amutils="$AM_standard_dependencies"
AM_UTILS_SOURCE="https://github.com/ivan-hc/am-utils/releases/download/continuous-$ARCH"
for name in $amutils; do
if ! command -v "$name" >/dev/null 2>&1; then
if [ -d "$CACHEDIR"/AMCACHEPATH/"$name" ] || [ -L "$CACHEDIR"/AMCACHEPATH/"$name" ] || [ ! -f "$CACHEDIR"/AMCACHEPATH/"$name" ]; then
rm -Rf "$CACHEDIR"/AMCACHEPATH/"$name"
if [ -z "$fallback_binaries_needed" ]; then
fallback_binaries_needed="$name"
else
fallback_binaries_needed=$(echo "$fallback_binaries_needed $name" | tr ' ' '\n' | sort | xargs)
fi
fi
fi
done
if [ -n "$fallback_binaries_needed" ]; then
_online_check
printf "%b\n" "$DIVIDING_LINE"
printf $"Missing commands will be temporarily downloaded as static binaries:\n\n" | _fit
for name in $fallback_binaries_needed; do
_deps_dl && chmod a+x "$CACHEDIR"/AMCACHEPATH/"$name" && printf $" - %b, downloaded from https://github.com/ivan-hc/am-utils\n" "$name" &
done
wait
printf "\n%b\n" "$DIVIDING_LINE"
fi
# Remove static binaries and other temporary utilities if related commands are already available in PATH
amutils="appimagetool $amutils"
for name in $amutils; do
if command -v "$name" >/dev/null 2>&1 && [ -f "$CACHEDIR"/AMCACHEPATH/"$name" ]; then
rm -Rf "$CACHEDIR"/AMCACHEPATH/"$name"
fi
done
# Check AMCACHEPATH integrity
am_bins_allowed=$(echo "$amutils" | tr ' ' '\n' | sed "s#^#$CACHEDIR/AMCACHEPATH/#g")
am_bins_all=$(find "$CACHEDIR"/AMCACHEPATH -mindepth 1 -maxdepth 1 \( -type d -o -type f -o -type l \))
if [ -n "$am_bins_all" ]; then
for f in "$CACHEDIR"/AMCACHEPATH/*; do
am_bin_item=$(echo "$f" | sed 's:.*/::')
if ! echo "$am_bins_allowed" | grep -q "$am_bin_item$" 2>/dev/null; then
rm -Rf "$f"
fi
done
fi
# Check binaries integrity
if [ "$(ls -A "$CACHEDIR"/AMCACHEPATH 2>/dev/null)" ]; then
if [ ! -f "$AMCACHEDIR"/"$ARCH".sha256sum.txt ]; then
if curl --output /dev/null --silent --head --fail https://github.com 1> /dev/null; then
deps_sum256_all=$(curl -Ls "$AM_UTILS_SOURCE/$ARCH.sha256sum.txt" 2>/dev/null)
if [ -n "$deps_sum256_all" ]; then
echo "$deps_sum256_all" > "$AMCACHEDIR"/"$ARCH".sha256sum.txt
fi
fi
printf "%b\n" "$DIVIDING_LINE"
printf $"Temporary fallback binaries are in use for the commands below:\n%b%b\033[0m\nInstall them to avoid slow performance.\n" "${Green}" "$(ls "$CACHEDIR"/AMCACHEPATH/ | xargs | _fit )" | _fit
printf "%b\n" "$DIVIDING_LINE"
fi
if [ -f "$AMCACHEDIR"/"$ARCH".sha256sum.txt ]; then
for name in $AM_standard_dependencies; do
_checksum_on_standard_dependencies &
done
wait
export PATH="$CACHEDIR"/AMCACHEPATH/:"${PATH}"
fi
fi
fi

# Check for essential commands required by the application
missing_deps=""
AMDEPENDENCES="cat chmod chown curl grep sed wget"
for name in $AMDEPENDENCES; do
for name in $AM_core_dependencies; do
if ! command -v "$name" >/dev/null 2>&1; then
missing_deps="$name $missing_deps"
fi
Expand All @@ -506,7 +615,7 @@ if [ -n "$missing_deps" ]; then
echo "$DIVIDING_LINE"
printf $" ${RED}💀 ERROR! MISSING ESSENTIAL COMMANDS\033[0m: %s\n\n Install the above and try again! \n" "${missing_deps[*]}"
echo "$DIVIDING_LINE"
printf $"%bList of the %b core dependences\033[0m:\n\n%b\n" "${Green}" "$AMCLIUPPER $AMVERSION" "$AMDEPENDENCES" | _fit
printf $"%bList of the %b core dependences\033[0m:\n\n%b\n" "${Green}" "$AMCLIUPPER $AMVERSION" "$AM_core_dependencies" | _fit
echo "$DIVIDING_LINE"
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
printf $" See %bhttps://github.com/ivan-hc/AM#installation\033[0m for more information\n" "${LightBlue}"
Expand All @@ -533,21 +642,6 @@ _check_fedora_mess() {
fi
}

# Function to check online connections (uses github.com by default, as the database and CLI itself are stored/hosted there)
_online_check() {
if ! wget -q --tries=10 --timeout=20 --spider https://github.com; then
printf $"\n %b is offline, please check your internet connection and try again\n\n" "$AMCLI"
exit 0
fi
}

# Check AMCACHEPATH integrity
if [ -d "$CACHEDIR"/AMCACHEPATH ]; then
am_bins_allowed=$(echo "appimagetool" | tr ' ' '\n' | sed "s#^#$CACHEDIR/AMCACHEPATH/#g")
am_bins_all=$(find "$CACHEDIR"/AMCACHEPATH -mindepth 1 -maxdepth 1 \( -type d -o -type f -o -type l \))
for f in $am_bins_all; do if ! echo "$am_bins_allowed" | grep -q "$f$" 2>/dev/null; then rm "$f" 2>/dev/null; fi; done
fi

# Check if appimagetool is installed, and if it is not installed, download and use it where it is needed
_download_appimagetool() {
_determine_args
Expand Down Expand Up @@ -1659,7 +1753,15 @@ _update_print_updated_apps_table() {
app_header=$(printf $"App")
old_header=$(printf $"Previous")
new_header=$(printf $"Current")
diff "$OLDVER" "$NEWVER" | grep "^>" | sed 's/^> //g' | while IFS= read -r updated_app; do
awk '
NR==FNR { a[NR]=$0; next }
{
if ($0 != a[FNR]) {
print "< " a[FNR]
print "> " $0
}
}
' "$OLDVER" "$NEWVER" | grep "^>" | sed 's/^> //g' | while IFS= read -r updated_app; do
arg=$(printf "%s\n" "$updated_app" | awk '{print $2}')
old_app=$(grep -F "$arg " "$OLDVER" | head -1)
old_version=$(printf "%s\n" "$old_app" | sed "s/^ ◆ $arg //; s/\x1b\[[0-9;]*m//g; s/[✖✓🔒]//g; s/ */ /g; s/ $//")
Expand Down Expand Up @@ -1697,7 +1799,7 @@ _update_determine_apps_version_changes() {
_update_list_updatable_apps
OLDVER="$AMCACHEDIR/updatable-args-list-old"
NEWVER="$AMCACHEDIR/updatable-args-list"
if cmp --silent -- "$NEWVER" "$OLDVER"; then
if [ "$(sort "$NEWVER")" = "$(sort "$OLDVER")" ]; then
printf $" Nothing to do here! \n"
else
printf $" The following apps have been updated:\n\n"
Expand Down
39 changes: 13 additions & 26 deletions modules/install.am
Original file line number Diff line number Diff line change
Expand Up @@ -63,30 +63,18 @@ _check_argument() {
}

_check_if_optional_dependences_are_needed() {
# Determine generic build utils
app_deps="ar gcc glib-compile-schemas make tar unzip"
# Determine if the argument is a script and not something else
if head -c10 ./"$arg" 2>/dev/null | grep -q "^#!"; then
script_content=$(cat ./"$arg")
elif head -c10 ./"$arg" 2>/dev/null | grep -qa '^.ELF....AI$'; then
if head -c10 ./"$arg" 2>/dev/null | grep -qa '^.ELF....AI$'; then
printf $"💀 ERROR: this option is ment to handle installation scripts only! \n\n" | _fit
printf $" If this AppImage is not in our database, open an issue or a pull request at\n https://github.com/ivan-hc/AM\n\n" | _fit
_check_argument
return 1
else
elif ! head -c10 ./"$arg" 2>/dev/null | grep -q "^#!"; then
printf $"💀 ERROR: \"$arg\" is not a valid file! \n\n" | _fit
printf $"This option is ment to handle installation scripts only! \n\n" | _fit
_check_argument
return 1
fi
# Determine if this is an AppImage that can be compiled on-the-fly
if grep -qi "^wget.*.sh.*chmod.*&&" ./"$arg"; then
appimage_bulder_script=$(grep "^wget " ./"$arg" | tr '"' '\n' | grep -i "^http" | sed "s/\$APP/$arg/g")
if ! curl --output /dev/null --silent --head --fail "$appimage_bulder_script" 1> /dev/null; then
echo $" 💀 ERROR: cannot create \"$arg\", the builder does not exists"
return 1
fi
fi
# Determine if this script installs a Firefox webapp
if grep -q 'ffwa-' ./"$arg"; then
ffbrowser=$(find ${PATH//:/ } -maxdepth 1 -name "firefox*" | sort | head -1)
Expand All @@ -97,15 +85,6 @@ _check_if_optional_dependences_are_needed() {
sed -i 's#firefox --class#'"$(echo "$ffbrowser" | xargs -L 1 basename)"' --class#g' ./"$arg"
fi
fi
# Check missing dependency
for name in $app_deps; do
dependency_name="$name"
[ "$name" = "ar" ] && dependency_name="binutils"
if echo "$script_content" | grep -q "^$name" && ! command -v "$name" >/dev/null 2>&1; then
echo $" 💀 ERROR: cannot install \"$arg\" without \"$dependency_name\""
return 1
fi
done
}

_check_if_script_installs_a_metapackage() {
Expand Down Expand Up @@ -298,6 +277,14 @@ _ending_the_installation() {
fi
}

_install_exec_installation_script() {
if [ "$(ls -A "$CACHEDIR"/AMCACHEPATH 2>/dev/null)" ] && [ -n "$SUDOCMD" ]; then
$SUDOCMD PATH="$PATH" ./"$arg"
else
$SUDOCMD ./"$arg"
fi
}

_install_script_retry() {
# Determine if the installation has stopped when trying to download the app
test_lastdir=$(ls -td "$APPSPATH"/* | head -1 | sed 's:.*/::')
Expand All @@ -309,7 +296,7 @@ _install_script_retry() {
if [ -z "$( ls -A "$test_lastdir_tmp" )" ]; then
printf "\n The file was not downloaded, attempt %b of 5 will start in 5 seconds...\n\n" "$((TAKES_COUNT + 1))"
sleep 5
$SUDOCMD ./"$arg"
_install_exec_installation_script
fi
fi
TAKES_COUNT=$((TAKES_COUNT + 1))
Expand All @@ -326,7 +313,7 @@ _install_script_retry() {
printf -- "\n %b✔ Attempting to extend pages in progress...\033[0m\n\n" "${Gold}"
sleep 5
sed -i 's#/releases #/releases?per\_page=100 #g' ./"$arg"
$SUDOCMD ./"$arg" || printf -- "\n %b✖ Failed! \033[0m \n" "${RED}"
_install_exec_installation_script || printf -- "\n %b✖ Failed! \033[0m \n" "${RED}"
else
# No patches found
printf -- "\n %b✖ No patch available! \033[0m \n" "${RED}"
Expand Down Expand Up @@ -354,7 +341,7 @@ _install_arg() {
# Set trap to cleanup on interruption (Ctrl+C, kill, hangup, quit)
trap _installation_cleanup INT TERM HUP QUIT
# Install script
$SUDOCMD ./"$arg" || _install_script_retry
_install_exec_installation_script || _install_script_retry
echo ""
_post_installation_processes
_ending_the_installation
Expand Down