mirror of
https://github.com/termux-pacman/termux-packages.git
synced 2026-01-10 21:03:25 +00:00
319 lines
9.6 KiB
Bash
Executable File
319 lines
9.6 KiB
Bash
Executable File
#!/bin/bash
|
|
set -eu
|
|
|
|
# Setup TERMUX_APP_PACKAGE_MANAGER
|
|
source "@TERMUX_PREFIX@/bin/termux-setup-package-manager" || exit 1
|
|
|
|
show_help() {
|
|
local cache_size
|
|
local cache_dir=""
|
|
if [ "$TERMUX_APP_PACKAGE_MANAGER" = "apt" ]; then
|
|
cache_dir="@TERMUX_CACHE_DIR@/apt/archives"
|
|
elif [ "$TERMUX_APP_PACKAGE_MANAGER" = "pacman" ]; then
|
|
cache_dir="@TERMUX_PREFIX@/var/cache/pacman/pkg"
|
|
fi
|
|
cache_size=$(du -sh "$cache_dir" 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 "Termux-PKG/1.0 mirror-checker (termux-tools @PACKAGE_VERSION@) Termux (@TERMUX_APP_PACKAGE@; install-prefix:@TERMUX_PREFIX@)" \
|
|
"$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[15]="https://dl.kcubeterm.com/termux-main"
|
|
mirrors[14]="https://grimler.se/termux-packages-24"
|
|
mirrors[13]="https://termux.mentality.rip/termux-main"
|
|
mirrors[12]="https://termux.astra.in.ua/apt/termux-main"
|
|
mirrors[11]="https://termux.librehat.com/apt/termux-main"
|
|
mirrors[10]="https://mirror.mwt.me/termux/main"
|
|
mirrors[4]="https://termux.sahilister.in/apt/termux-main"
|
|
mirrors[3]="https://plug-mirror.rcac.purdue.edu/termux/termux-main"
|
|
mirrors[2]="https://packages.nscdn.top/apt/termux-main"
|
|
|
|
local current_mirror current_weight
|
|
current_mirror=$(grep -m 1 -P "^\s*deb\s+" @TERMUX_PREFIX@/etc/apt/sources.list | grep -oP 'https?://[^\s]+')
|
|
if [ -n "$current_mirror" ]; then
|
|
current_mirror="${current_mirror%/}"
|
|
for weight in "${!mirrors[@]}"; do [[ ${mirrors[$weight]} == "$current_mirror" ]] && current_weight="$weight" && break; done
|
|
fi
|
|
|
|
# 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 "Checking availability of current mirror:"
|
|
echo -n "[*] (${current_weight-}) $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 parallel_jobs_max_count=10
|
|
|
|
if [[ ! "$parallel_jobs_max_count" =~ ^[0-9]+$ ]] || \
|
|
[[ "$parallel_jobs_max_count" -lt 1 ]] || \
|
|
[[ "$parallel_jobs_max_count" -gt 1000 ]]; then
|
|
parallel_jobs_max_count=1
|
|
fi
|
|
|
|
declare -a parallel_jobs_mirrors=()
|
|
declare -a parallel_jobs_wights=()
|
|
declare -a parallel_jobs_urls=()
|
|
declare -a parallel_jobs_numbers=()
|
|
declare -a parallel_jobs_pids=()
|
|
declare -a parallel_jobs_return_values=()
|
|
|
|
local i j mirror weight url job_number job_pid return_value
|
|
local total_mirror_weight=0
|
|
local total_mirrors=${#mirrors[@]}
|
|
local parallel_jobs_current_count=1
|
|
|
|
set +e
|
|
i=0
|
|
for mirror in "${!mirrors[@]}"; do
|
|
weight="$mirror" # mirror will be file path in future #9889
|
|
url="${mirrors[$weight]}"
|
|
|
|
if [[ ! "$weight" =~ ^[0-9]+$ ]]; then
|
|
echo "Invalid weight \"$weight\" for mirror \"$url\"" 1>&2
|
|
set -e; return 1
|
|
fi
|
|
|
|
job_number=$parallel_jobs_current_count
|
|
parallel_jobs_current_count=$((parallel_jobs_current_count + 1))
|
|
|
|
# Start mirror check in background
|
|
check_mirror "$url" &
|
|
job_pid=$!
|
|
|
|
parallel_jobs_mirrors=("${parallel_jobs_mirrors[@]}" "$mirror")
|
|
parallel_jobs_wights=("${parallel_jobs_wights[@]}" "$weight")
|
|
parallel_jobs_urls=("${parallel_jobs_urls[@]}" "$url")
|
|
parallel_jobs_numbers=("${parallel_jobs_numbers[@]}" "$job_number")
|
|
parallel_jobs_pids=("${parallel_jobs_pids[@]}" "$job_pid")
|
|
|
|
# If current job count has reached max value or is the last mirror, wait for already started jobs to finish
|
|
if [ "$job_number" -ge $parallel_jobs_max_count ] || \
|
|
[ "$i" -ge $((total_mirrors - 1)) ]; then
|
|
|
|
j=0
|
|
# For pids of all jobs
|
|
for job_pid in "${parallel_jobs_pids[@]}"; do
|
|
# Wait for job with matching pid to return
|
|
#echo "waiting for check_mirror job ${parallel_jobs_numbers[j]} for mirror \"${parallel_jobs_urls[j]}\" with pid ${parallel_jobs_pids[j]}"
|
|
wait "$job_pid"
|
|
return_value=$?
|
|
|
|
parallel_jobs_return_values=("${parallel_jobs_return_values[@]}" "$return_value")
|
|
j=$((j + 1))
|
|
done
|
|
|
|
j=0
|
|
# For return_values of all jobs
|
|
for return_value in "${parallel_jobs_return_values[@]}"; do
|
|
echo -n "[*] (${parallel_jobs_wights[j]}) ${parallel_jobs_urls[j]}: "
|
|
if [ "$return_value" -eq 0 ]; then
|
|
echo "ok"
|
|
total_mirror_weight=$((total_mirror_weight + parallel_jobs_wights[j]))
|
|
else
|
|
echo "bad"
|
|
#echo "check_mirror job ${parallel_jobs_numbers[j]} for mirror \"${parallel_jobs_urls[j]}\" with pid ${parallel_jobs_pids[j]} failed with exit code $return_value"
|
|
unset "mirrors[${parallel_jobs_mirrors[j]}]"
|
|
fi
|
|
|
|
j=$((j + 1))
|
|
done
|
|
|
|
# Reset job related variables
|
|
parallel_jobs_current_count=1
|
|
parallel_jobs_mirrors=()
|
|
parallel_jobs_wights=()
|
|
parallel_jobs_urls=()
|
|
parallel_jobs_numbers=()
|
|
parallel_jobs_pids=()
|
|
parallel_jobs_return_values=()
|
|
fi
|
|
|
|
i=$((i + 1))
|
|
done
|
|
set -e
|
|
|
|
# Weight-based mirror selection.
|
|
local selected_mirror=""
|
|
if ((total_mirror_weight > 0)); then
|
|
local random_weight calc_weight=0
|
|
random_weight=$((RANDOM % total_mirror_weight + 1))
|
|
for weight in $(echo "${!mirrors[@]}" | tr ' ' '\n' | sort -n); do
|
|
calc_weight=$((calc_weight + weight))
|
|
|
|
if ((calc_weight >= random_weight)); then
|
|
echo "Picking mirror: ($weight) ${mirrors[$weight]}"
|
|
selected_mirror="${mirrors[$weight]}"
|
|
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 || $(echo "$1" | grep "^h") ]]; then
|
|
show_help
|
|
fi
|
|
|
|
CMD="$1"
|
|
shift 1
|
|
ERROR=false
|
|
|
|
case "$TERMUX_APP_PACKAGE_MANAGER" in
|
|
apt)
|
|
case "$CMD" in
|
|
f*) dpkg -L "$@";;
|
|
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 "$@";;
|
|
*) ERROR=true;;
|
|
esac;;
|
|
pacman)
|
|
case "$CMD" in
|
|
f*) pacman -Ql "$@";;
|
|
sh*|inf*) pacman -Qi "$@";;
|
|
add|i*) pacman -Sy --needed "$@";;
|
|
autoc*) pacman -Sc;;
|
|
cl*) pacman -Scc;;
|
|
list-a*) pacman -Sl "$@";;
|
|
list-i*) pacman -Q "$@";;
|
|
rei*) pacman -S "$@";;
|
|
se*) pacman -Sys "$@";;
|
|
un*|rem*|rm|del*) pacman -Rcns "$@";;
|
|
up*) pacman -Syu "$@";;
|
|
*) ERROR=true;;
|
|
esac;;
|
|
esac
|
|
|
|
if $ERROR; then
|
|
echo "Unknown command: '$CMD' (run 'pkg help' for usage information)"; exit 1
|
|
fi
|