termux-packages/packages/termux-tools/pkg
Leonid Pliushch d98a741ac6 termux-tools: pkg: when checking mirrors, force terminate curl command after 6 seconds timeout
Before this, we had only '--connect-timeout 5' option specified but unfortunately
it doesn't work in cases when remote host is behind some proxy (e.g. CloudFlare)
but is not connected to Internet.

To prevent curl from hanging for unspecified amount of time, we need to introduce
external timeout here.
2020-11-12 20:02:17 +02:00

154 lines
4.5 KiB
Bash
Executable File

#!/bin/bash
set -e -u
show_help() {
local cache_size
cache_size=$(du -sh @TERMUX_CACHE_DIR@/apt/archives 2>/dev/null | cut -f1)
echo 'Usage: pkg command [arguments]'
echo
echo 'A tool for managing packages. Commands:'
echo
echo ' autoclean - Remove all outdated packages from .deb package'
echo ' cache.'
echo
echo ' clean - Remove all packages from .deb package cache.'
[ -n "$cache_size" ] && echo " Using ${cache_size} now."
echo
echo ' files <packages> - Show all files installed by packages.'
echo
echo ' install <packages> - Install specified packages.'
echo
echo ' list-all - List all packages available in repositories.'
echo
echo ' list-installed - List installed packages.'
echo
echo ' reinstall <packages> - Reinstall specified installed packages at the'
echo ' latest version.'
echo
echo ' search <query> - Search package by query, for example by name or'
echo ' description part.'
echo
echo ' show <packages> - Show basic metadata, such as dependencies.'
echo
echo ' uninstall <packages> - Uninstall specified packages. Configuration files'
echo ' will be left intact.'
echo
echo ' upgrade - Upgrade all installed packages to the latest'
echo ' version.'
echo
exit 1
}
select_mirror() {
local main_repo="https://termux.org/packages"
declare -A mirrors
mirrors[50]="https://dl.bintray.com/termux/termux-packages-24"
mirrors[23]="https://termux.mentality.rip/termux-packages-24"
mirrors[15]="https://main.termux-mirror.ml"
mirrors[12]="https://grimler.se/termux-packages-24"
local current_mirror
current_mirror=$(grep -P "^\s*deb\s+" @TERMUX_PREFIX@/etc/apt/sources.list | grep -oP 'https?://[a-z0-9/._-]+')
# Do not update mirror if:
# * Uses .cn domain - specific to Chinese users.
# * If $TERMUX_PKG_NO_MIRROR_SELECT was set.
if [ -n "${TERMUX_PKG_NO_MIRROR_SELECT-}" ] || grep -qP '.+\.cn/' <(echo "${current_mirror-x}"); then
return
fi
# Mirrors are rotated if 6 hours timeout has been passed or mirror is no longer accessible.
if [ -n "$(find @TERMUX_CACHE_DIR@/apt/pkgcache.bin -mmin -360 2>/dev/null)" ]; then
if [ -n "${current_mirror}" ]; then
echo -n "Checking availability of current mirror: "
if timeout 6 curl --connect-timeout 5 --user-agent 'Termux-PKG/1.0 mirror-checker' --head --fail --location "${current_mirror%/}/dists/stable/Release" >/dev/null 2>&1; then
echo "ok"
return
else
echo "bad"
fi
fi
fi
# Test mirror availability, remove unaccessible mirrors from list.
echo "Testing the available mirrors:"
local w total_mirror_weight=0
for w in "${!mirrors[@]}"; do
echo -n "[*] ${mirrors[$w]}: "
if timeout 6 curl --connect-timeout 5 --user-agent 'Termux-PKG/1.0 mirror-checker' --head --fail --location "${mirrors[$w]%/}/dists/stable/Release" >/dev/null 2>&1; then
echo "ok"
total_mirror_weight=$((total_mirror_weight + w))
else
echo "bad"
unset "mirrors[$w]"
fi
done
unset w
# Weight-based mirror selection.
local selected_mirror=""
if ((total_mirror_weight > 0)); then
local w random_weight calc_weight=0
random_weight=$((RANDOM % total_mirror_weight + 1))
for w in $(echo "${!mirrors[@]}" | tr ' ' '\n' | sort -n); do
calc_weight=$((calc_weight + w))
if ((calc_weight >= random_weight)); then
echo "Picking mirror: ${mirrors[$w]}"
selected_mirror="${mirrors[$w]}"
break
fi
done
fi
if [ -n "${selected_mirror}" ]; then
echo "deb ${selected_mirror}/ stable main" > @TERMUX_PREFIX@/etc/apt/sources.list
else
echo "Using fallback mirror: ${main_repo}"
echo "deb ${main_repo}/ stable main" > @TERMUX_PREFIX@/etc/apt/sources.list
fi
}
update_apt_cache() {
if [ -z "$(find @TERMUX_CACHE_DIR@/apt/pkgcache.bin -mmin -20 2>/dev/null)" ]; then
apt update
fi
}
if [ $# = 0 ]; then
show_help
fi
CMD="$1"
shift 1
case "$CMD" in
f*) dpkg -L "$@";;
h*) show_help;;
add|i*)
select_mirror
update_apt_cache
apt install "$@"
;;
autoc*) apt autoclean;;
cl*) apt clean;;
list-a*) apt list "$@";;
list-i*) apt list --installed "$@";;
rei*) apt install --reinstall "$@";;
se*)
select_mirror
update_apt_cache
apt search "$@"
;;
sh*) apt show "$@";;
un*|rem*|rm|del*) apt remove "$@";;
up*)
select_mirror
apt update
apt full-upgrade "$@"
;;
*) echo "Unknown command: '$CMD' (run 'pkg help' for usage information)"; exit 1;;
esac