245 lines
7.4 KiB
Bash
Executable File
245 lines
7.4 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
CodeToCountry() { # convert country code to country name
|
|
echo "$REFLECTOR_COUNTRIES" | grep -w "$1" | sed 's|^\(.*[a-z]\)[ ]*[A-Z][A-Z].*$|\1|'
|
|
}
|
|
CountryToCode() { # convert name to code; used for checking
|
|
echo "$REFLECTOR_COUNTRIES" | grep -w "$1" | awk '{print $(NF-1)}'
|
|
}
|
|
|
|
CCCheck() { # check validity of country code
|
|
case "$1" in
|
|
[A-Z][A-Z]) test -n "$(CodeToCountry "$1")" && return 0 ;;
|
|
esac
|
|
return 1 # fail
|
|
}
|
|
GetYourCountryCode() {
|
|
local IP code
|
|
|
|
code="$(show-location-info country)"
|
|
CCCheck "$code" && {
|
|
echo "$code" ; return
|
|
}
|
|
|
|
IP="$(dig -4 TXT +short o-o.myaddr.l.google.com @ns1.google.com | tr -d '"')" # ipv4 address
|
|
code="$(geoiplookup "$IP" | sed 's|^.*: \([A-Z][A-Z]\),.*$|\1|')"
|
|
CCCheck "$code" && {
|
|
echo "$code" ; return
|
|
}
|
|
code="$(whois "$IP" | grep ^country: | awk '{print $NF}')"
|
|
CCCheck "$code" && {
|
|
echo "$code" ; return
|
|
}
|
|
|
|
IP="$(dig -6 TXT +short o-o.myaddr.l.google.com @ns1.google.com | tr -d '"')" # ipv6 address
|
|
code="$(geoiplookup6 "$IP" | sed 's|^.*: \([A-Z][A-Z]\),.*$|\1|')"
|
|
CCCheck "$code" && {
|
|
echo "$code" ; return
|
|
}
|
|
code="$(whois "$IP" | grep ^country: | awk '{print $NF}')"
|
|
CCCheck "$code" && {
|
|
echo "$code" ; return
|
|
}
|
|
|
|
code="$(show-location-info country)"
|
|
CCCheck "$code" && {
|
|
echo "$code" ; return
|
|
}
|
|
|
|
# net services failed, use local variables, but may be wrong
|
|
code="$(locale | grep ^LC_TIME | cut -d '"' -f 2 | sed 's|^.*_\([A-Z][A-Z]\)\..*$|\1|')"
|
|
CCCheck "$code" && {
|
|
echo "$code" ; return
|
|
}
|
|
}
|
|
GetYourCountry() {
|
|
local code="$(GetYourCountryCode)"
|
|
local country="$(test -n "$code" && CodeToCountry "$code")"
|
|
echo "$country"
|
|
}
|
|
|
|
Debug() {
|
|
if [ "$dryrun" = "yes" ] ; then
|
|
echo "$@" >&2
|
|
fi
|
|
}
|
|
logterminal() {
|
|
local msg="$1"
|
|
local extra="$2"
|
|
|
|
case "$extra" in
|
|
"") echo "==> $progname: $msg" ;;
|
|
--nh) echo "$msg" ;;
|
|
esac
|
|
}
|
|
|
|
DIE() {
|
|
logterminal "$FUNCNAME: $1"
|
|
exit 1
|
|
}
|
|
|
|
UseBestMirrorsIfAvailable() {
|
|
[ -n "$this_country" ] || return
|
|
# ad hoc mirror "ranking"
|
|
declare -A BEST_MIRRORS # mirrors here will be the *first* mirrors
|
|
|
|
# Add a list of *known* best mirrors for a country:
|
|
BEST_MIRRORS[FI]='https://mirror.f4st.host/archlinux/$repo/os/$arch https://mirror.pseudoform.org/$repo/os/$arch' # FI uses these!
|
|
|
|
local best="${BEST_MIRRORS[$this_country]}"
|
|
local bb
|
|
|
|
if [ -n "$best" ] ; then
|
|
rm -f $tf.new
|
|
for bb in $best ; do
|
|
logterminal "Adding mirror '$bb'"
|
|
echo "Server = $bb" >> $tf.new
|
|
|
|
# remove $bb from the current list if it is there
|
|
grep -v "$bb" $tf > $tf.tmp
|
|
mv $tf.tmp $tf
|
|
done
|
|
cat $tf >> $tf.new
|
|
mv $tf.new $tf
|
|
fi
|
|
}
|
|
|
|
RunCmd() {
|
|
$cmd > $tf
|
|
retval=$?
|
|
[ $retval -eq 0 ] || return
|
|
|
|
UseBestMirrorsIfAvailable
|
|
|
|
if [ -x /usr/bin/rate-mirrors ] ; then
|
|
grep '^Server = ' $tf > $tf.tmp
|
|
mv $tf.tmp $tf
|
|
fi
|
|
}
|
|
|
|
Main() {
|
|
local VERSION="2.1" # started from 2.0!
|
|
local progname="$(basename "$0")"
|
|
local mf=/etc/pacman.d/mirrorlist
|
|
local bu=/tmp/mirrorlist.bu # original mirrorlist, saved by Welcome
|
|
|
|
logterminal "version $VERSION"
|
|
|
|
/usr/local/bin/connection-checker || {
|
|
logterminal "Internet connection is not available, cannot rank mirrorlist."
|
|
return
|
|
}
|
|
|
|
if [ -r $mf ] && [ -r $bu ] ; then
|
|
if (/usr/bin/diff $mf $bu >& /dev/null) ; then
|
|
# Current and original mirrorlists are the same, so carry on.
|
|
logterminal "Updating mirrorlist."
|
|
else
|
|
# Current and original mirrorlist are different, so stop.
|
|
logterminal "Mirrorlist already changed, not updating it."
|
|
logterminal "This is the current mirrorlist:"
|
|
echo "#===================================#"
|
|
cat "$mf"
|
|
echo "#===================================#"
|
|
return
|
|
fi
|
|
fi
|
|
|
|
REFLECTOR_COUNTRIES="$(reflector --list-countries --connection-timeout 20 --download-timeout 20)"
|
|
if [ -z "$REFLECTOR_COUNTRIES" ] ; then
|
|
logterminal "no result from command 'reflector --listcountries', mirrorlist not updated."
|
|
return
|
|
fi
|
|
local this_country="$(GetYourCountryCode)"
|
|
local retval
|
|
local cmd=""
|
|
local ranker="reflector" # rate-mirrors or reflector
|
|
local dryrun=no
|
|
local arg
|
|
|
|
if [ -n "$this_country" ] ; then
|
|
logterminal "detected country: $(CodeToCountry $this_country)"
|
|
else
|
|
logterminal "country code not found on Arch mirrorlist"
|
|
fi
|
|
|
|
for arg in "$@" ; do
|
|
case "$arg" in
|
|
-n | --dryrun) dryrun=yes ;; # don't save mirrorlist to /etc/pacman.d
|
|
-cc=*) this_country="${arg#*=}" ; logterminal "country changed to '$this_country'" ;;
|
|
*) DIE "parameter '$arg' is not supported" ;;
|
|
esac
|
|
done
|
|
|
|
if [ -x /usr/bin/rate-mirrors ] ; then
|
|
# new implementation (after 2021-06-27)
|
|
case "$this_country" in
|
|
FI)
|
|
# Some other European countries (e.g. DE) could use this command as well!
|
|
cmd="$ranker -phttps -l5 -cDE --sort rate --threads 5"
|
|
;;
|
|
*)
|
|
# rate-mirrors should create a reasonably good mirrorlist generally
|
|
ranker="rate-mirrors"
|
|
cmd="$ranker --allow-root arch --max-delay=3600" # don't allow too old mirrors!
|
|
;;
|
|
esac
|
|
else
|
|
# old implementation (before 2021-06-27)
|
|
cmd="$ranker -phttps --latest 10 --sort rate " # reflector and common options
|
|
case "$this_country" in
|
|
"" | IS | IE)
|
|
# no mirrors or mirror problems here, search well-updated https mirrors globally
|
|
cmd+=" --verbose"
|
|
;;
|
|
FI)
|
|
# special command for FI
|
|
cmd+=" -cde --threads 5"
|
|
cmd+=" -x orbit-os -x ratenzahlung -x satis-faction"
|
|
cmd+=" -x xtom.de -x metalgamer -x agdsn -x fsrv -x appuals -x wrz -x clientvps"
|
|
cmd+=" -x fef.moe -x gnomus"
|
|
;;
|
|
DE|DK|FR|GB|HK|NL|NZ|SE|SG|US)
|
|
# search https mirrors only in this country
|
|
cmd+=" -c $this_country --threads 5"
|
|
;;
|
|
CA|CH|CZ)
|
|
cmd+=" --threads 5"
|
|
;;
|
|
*)
|
|
# this country may lack https mirrors
|
|
cmd+=" -phttp --latest 15 --verbose"
|
|
;;
|
|
esac
|
|
fi
|
|
|
|
local tf=$(mktemp)
|
|
|
|
logterminal "command: $cmd"
|
|
logterminal "please wait..."
|
|
logterminal "" --nh
|
|
logterminal "'time' output:" --nh
|
|
time RunCmd
|
|
logterminal "" --nh
|
|
|
|
if [ $retval -eq 0 ] ; then
|
|
logterminal "Arch mirrorlist by $ranker:"
|
|
logterminal "" --nh
|
|
logterminal "$(cat $tf)" --nh
|
|
logterminal "" --nh
|
|
if [ "$dryrun" = "no" ] ; then
|
|
logterminal "writing file $mf"
|
|
sudo bash -c "cp $tf $mf && chmod 0644 $mf"
|
|
else
|
|
logterminal "you used option --dryrun, will not write file $mf"
|
|
fi
|
|
else
|
|
logterminal "$ranker returned error code $retval, mirrorlist not updated."
|
|
fi
|
|
|
|
rm -f $tf
|
|
return 0 # return $retval # 0=OK, other is FAIL
|
|
}
|
|
|
|
Main "$@"
|