termux-packages/packages/termux-tools/pkg

218 lines
6.0 KiB
Bash
Executable File

#!/bin/bash
set -eu
USER_AGENT='Termux-PKG/1.0 mirror-checker (termux-tools @PACKAGE_VERSION@) Termux (@TERMUX_APP_PACKAGE@; install-prefix:@TERMUX_PREFIX@)'
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
}
check_mirror() {
local mirror="${1%/}"
local timeout="${2-5}"
timeout "$((timeout + 1))" curl \
--head \
--fail \
--connect-timeout "$timeout" \
--location \
--user-agent "$USER_AGENT" \
"$mirror/dists/stable/Release" >/dev/null 2>&1
}
hostname() {
echo "$1" | awk -F'[/:]' '{print $4}'
}
last_modified() {
local mtime
local now
mtime=$(date -r "$1" '+%s')
now=$(date '+%s')
echo $((now - mtime))
}
select_mirror() {
local main_repo="https://packages-cf.termux.org/apt/termux-main"
declare -A mirrors
mirrors[16]="$main_repo"
mirrors[14]="https://dl.kcubeterm.com/termux-main"
mirrors[13]="https://grimler.se/termux-packages-24"
mirrors[12]="https://termux.mentality.rip/termux-main"
mirrors[11]="https://termux.astra.in.ua/apt/termux-main"
mirrors[10]="https://termux.librehat.com/apt/termux-main"
mirrors[9]="https://mirror.mwt.me/termux/main"
mirrors[8]="https://termux.sahilister.in/apt/termux-main"
mirrors[7]="https://plug-mirror.rcac.purdue.edu/termux/termux-main"
local current_mirror
current_mirror=$(grep -m 1 -P "^\s*deb\s+" @TERMUX_PREFIX@/etc/apt/sources.list | grep -oP 'https?://[^\s]+')
# Do not update mirror if:
# * If $TERMUX_PKG_NO_MIRROR_SELECT was set.
# * Uses .cn domain - specific to Chinese users.
# * Uses mirror.bardia.tech, mirror based in Iran.
if [ -n "${TERMUX_PKG_NO_MIRROR_SELECT-}" ] || \
[[ "$(hostname "$current_mirror")" == *".cn" ]] || \
[[ "$(hostname "$current_mirror")" == *"mirror.bardia.tech"* ]]; then
return
fi
# Mirrors are rotated if 6 hours timeout has been passed or mirror is no longer accessible.
local pkgcache="@TERMUX_CACHE_DIR@/apt/pkgcache.bin"
if [ -e "$pkgcache" ] && (( $(last_modified "$pkgcache") <= 6 * 3600 )); then
if [ -n "$current_mirror" ]; then
echo -n "Checking availability of current mirror: "
if check_mirror "$current_mirror"; 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 check_mirror "${mirrors[$w]}"; 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() {
local current_host
current_host=$(sed -nE -e 's|^\s*deb\s+https?://(.+)\s+stable\s+main$|\1|p' @TERMUX_PREFIX@/etc/apt/sources.list | head -n 1)
if [ -z "$current_host" ]; then
# No primary repositories configured?
apt update
return
fi
local metadata_file
metadata_file=$(
list_prefix=$(echo "$current_host" | sed 's|/|_|g')
arch=$(dpkg --print-architecture)
echo "@TERMUX_PREFIX@/var/lib/apt/lists/${list_prefix}_dists_stable_main_binary-${arch}_Packages" | sed 's|__|_|g'
)
if [ ! -e "@TERMUX_CACHE_DIR@/apt/pkgcache.bin" ] || [ ! -e "$metadata_file" ]; then
apt update
return
fi
local cache_modified
cache_modified=$(last_modified "@TERMUX_CACHE_DIR@/apt/pkgcache.bin")
local sources_modified
sources_modified=$(last_modified "@TERMUX_PREFIX@/etc/apt/sources.list")
if (( sources_modified <= cache_modified )) || (( cache_modified > 1200 )); then
apt update
fi
}
if [ $# = 0 ]; then
show_help
fi
CMD="$1"
shift 1
case "$CMD" in
f*) dpkg -L "$@";;
h*) show_help;;
sh*|inf*) apt show "$@";;
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 "$@"
;;
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