replace rankmirrors by bash clone
This removes python optdepends in pacman package This bash clone is a courtesy of Matthew Bruenig <matthewbruenig@gmail.com> Signed-off-by: Xavier Chantry <shiningxc@gmail.com>
This commit is contained in:
parent
302310c5aa
commit
35bbc96b99
3 changed files with 204 additions and 193 deletions
|
@ -16,7 +16,7 @@ EXTRA_DIST = \
|
||||||
makepkg.sh.in \
|
makepkg.sh.in \
|
||||||
pacman-optimize.sh.in \
|
pacman-optimize.sh.in \
|
||||||
pkgdelta.sh.in \
|
pkgdelta.sh.in \
|
||||||
rankmirrors.py.in \
|
rankmirrors.sh.in \
|
||||||
repo-add.sh.in
|
repo-add.sh.in
|
||||||
|
|
||||||
# Files that should be removed, but which Automake does not know.
|
# Files that should be removed, but which Automake does not know.
|
||||||
|
@ -62,7 +62,7 @@ $(OURSCRIPTS): Makefile
|
||||||
makepkg: $(srcdir)/makepkg.sh.in
|
makepkg: $(srcdir)/makepkg.sh.in
|
||||||
pacman-optimize: $(srcdir)/pacman-optimize.sh.in
|
pacman-optimize: $(srcdir)/pacman-optimize.sh.in
|
||||||
pkgdelta: $(srcdir)/pkgdelta.sh.in
|
pkgdelta: $(srcdir)/pkgdelta.sh.in
|
||||||
rankmirrors: $(srcdir)/rankmirrors.py.in
|
rankmirrors: $(srcdir)/rankmirrors.sh.in
|
||||||
repo-add: $(srcdir)/repo-add.sh.in
|
repo-add: $(srcdir)/repo-add.sh.in
|
||||||
repo-remove: $(srcdir)/repo-add.sh.in
|
repo-remove: $(srcdir)/repo-add.sh.in
|
||||||
rm -f repo-remove
|
rm -f repo-remove
|
||||||
|
|
|
@ -1,191 +0,0 @@
|
||||||
#! /usr/bin/python
|
|
||||||
#
|
|
||||||
# rankmirrors - read a list of mirrors from a file and rank them by speed
|
|
||||||
# @configure_input@
|
|
||||||
#
|
|
||||||
# Copyright (c) 2006-2009 Pacman Development Team <pacman-dev@archlinux.org>
|
|
||||||
# Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>
|
|
||||||
#
|
|
||||||
# This program is free software; you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation; either version 2 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
#
|
|
||||||
import os, sys, datetime, time, socket, urllib2
|
|
||||||
from optparse import OptionParser
|
|
||||||
from string import Template
|
|
||||||
|
|
||||||
def createOptParser():
|
|
||||||
usage = "usage: %prog [options] MIRRORFILE | URL"
|
|
||||||
version = "%prog (pacman) @PACKAGE_VERSION@\n" \
|
|
||||||
"Copyright (c) 2006-2009 Pacman Development Team <pacman-dev@archlinux.org>.\n" \
|
|
||||||
"Copyright (C) 2002-2006 Judd Vinet <jvinet@zeroflux.org>.\n\n" \
|
|
||||||
"This is free software; see the source for copying conditions.\n" \
|
|
||||||
"There is NO WARRANTY, to the extent permitted by law."
|
|
||||||
description = "Ranks pacman mirrors by their connection and opening " \
|
|
||||||
"speed. Pacman mirror files are located in /etc/pacman.d/. It " \
|
|
||||||
"can also rank one mirror if the URL is provided."
|
|
||||||
parser = OptionParser(usage = usage, version = version,
|
|
||||||
description = description)
|
|
||||||
parser.add_option("-n", type = "int", dest = "num", default = 0,
|
|
||||||
help = "number of servers to output, 0 for all")
|
|
||||||
parser.add_option("-t", "--times", action = "store_true",
|
|
||||||
dest = "times", default = False,
|
|
||||||
help = "only output mirrors and their response times")
|
|
||||||
parser.add_option("-u", "--url", action = "store_true", dest = "url",
|
|
||||||
default = False, help = "test a specific url")
|
|
||||||
parser.add_option("-v", "--verbose", action = "store_true",
|
|
||||||
dest = "verbose", default = False,
|
|
||||||
help = "be verbose in ouptut")
|
|
||||||
# The following two options should be automatic
|
|
||||||
#parser.add_option("-h", "--help", action = "help")
|
|
||||||
#parser.add_option("-V", "--version", action = "version")
|
|
||||||
return parser
|
|
||||||
|
|
||||||
def timeCmd(cmd):
|
|
||||||
before = time.time()
|
|
||||||
try:
|
|
||||||
cmd()
|
|
||||||
except KeyboardInterrupt, ki:
|
|
||||||
raise ki
|
|
||||||
except socket.timeout, ioe:
|
|
||||||
return 'timeout'
|
|
||||||
except Exception, e:
|
|
||||||
return 'unreachable'
|
|
||||||
return time.time() - before
|
|
||||||
|
|
||||||
def talkToServer(serverUrl):
|
|
||||||
opener = urllib2.build_opener()
|
|
||||||
# retrieve first 50,000 bytes only
|
|
||||||
tmp = opener.open(serverUrl).read(50000)
|
|
||||||
|
|
||||||
def getFuncToTime(serverUrl):
|
|
||||||
return lambda : talkToServer(serverUrl)
|
|
||||||
|
|
||||||
def cmpPairBySecond(p1, p2):
|
|
||||||
if p1[1] == p2[1]:
|
|
||||||
return 0
|
|
||||||
if p1[1] < p2[1]:
|
|
||||||
return -1
|
|
||||||
return 1
|
|
||||||
|
|
||||||
def printResults(servers, time, verbose, num):
|
|
||||||
items = servers.items()
|
|
||||||
items.sort(cmpPairBySecond)
|
|
||||||
itemsLen = len(items)
|
|
||||||
numToShow = num
|
|
||||||
if numToShow > itemsLen or numToShow == 0:
|
|
||||||
numToShow = itemsLen
|
|
||||||
if itemsLen > 0:
|
|
||||||
if time:
|
|
||||||
print
|
|
||||||
print ' Servers sorted by time (seconds):'
|
|
||||||
for i in items[0:numToShow]:
|
|
||||||
if i[1] == 'timeout' or i[1] == 'unreachable':
|
|
||||||
print i[0], ':', i[1]
|
|
||||||
else:
|
|
||||||
print i[0], ':', "%.2f" % i[1]
|
|
||||||
else:
|
|
||||||
for i in items[0:numToShow]:
|
|
||||||
print 'Server =', i[0]
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
parser = createOptParser()
|
|
||||||
(options, args) = parser.parse_args()
|
|
||||||
|
|
||||||
if len(args) != 1:
|
|
||||||
parser.print_help(sys.stderr)
|
|
||||||
sys.exit(0)
|
|
||||||
|
|
||||||
# allows connections to time out if they take too long
|
|
||||||
socket.setdefaulttimeout(10)
|
|
||||||
|
|
||||||
if options.url:
|
|
||||||
if options.verbose:
|
|
||||||
print 'Testing', args[0] + '...'
|
|
||||||
try:
|
|
||||||
serverToTime = timeCmd(getFuncToTime(args[0]))
|
|
||||||
except KeyboardInterrupt, ki:
|
|
||||||
sys.exit(1)
|
|
||||||
if serverToTime == 'timeout' or serverToTime == 'unreachable':
|
|
||||||
print args[0], ':', serverToTime
|
|
||||||
else:
|
|
||||||
print args[0], ':', "%.2f" % serverToTime
|
|
||||||
sys.exit(0)
|
|
||||||
|
|
||||||
if not os.path.isfile(args[0]) and args[0] != "-":
|
|
||||||
print >>sys.stderr, 'rankmirrors: file', args[0], 'does not exist.'
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
if args[0] == "-":
|
|
||||||
fl = sys.stdin
|
|
||||||
else:
|
|
||||||
fl = open(args[0], 'r')
|
|
||||||
|
|
||||||
serverToTime = {}
|
|
||||||
if options.times:
|
|
||||||
print 'Querying servers, this may take some time...'
|
|
||||||
else:
|
|
||||||
print "# Server list generated by rankmirrors on",
|
|
||||||
print datetime.date.today()
|
|
||||||
for ln in fl.readlines():
|
|
||||||
splitted = ln.split('=')
|
|
||||||
if splitted[0].strip() != 'Server':
|
|
||||||
if not options.times:
|
|
||||||
print ln,
|
|
||||||
continue
|
|
||||||
|
|
||||||
serverUrl = splitted[1].strip()
|
|
||||||
if serverUrl[-1] == '\n':
|
|
||||||
serverUrl = serverUrl[0:-1]
|
|
||||||
if options.verbose and options.times:
|
|
||||||
print serverUrl, '...',
|
|
||||||
elif options.verbose:
|
|
||||||
print '#', serverUrl, '...',
|
|
||||||
elif options.times:
|
|
||||||
print ' * ',
|
|
||||||
sys.stdout.flush()
|
|
||||||
|
|
||||||
# if the $repo var is used in the url, replace it by core
|
|
||||||
tempUrl = Template(serverUrl).safe_substitute(repo='core')
|
|
||||||
# if the $arch var is used in the url, replace it by i686
|
|
||||||
tempUrl = Template(tempUrl).safe_substitute(arch='i686')
|
|
||||||
|
|
||||||
# add @DBEXT@ to server name. the repo name is parsed
|
|
||||||
# from the mirror url; it is the third (or fourth) dir
|
|
||||||
# from the end, where the url is http://foo/bar/REPO/os/arch
|
|
||||||
try:
|
|
||||||
splitted2 = tempUrl.split('/')
|
|
||||||
if tempUrl[-1] != '/':
|
|
||||||
repoName = splitted2[-3]
|
|
||||||
dbFileName = '/' + repoName + '@DBEXT@'
|
|
||||||
else:
|
|
||||||
repoName = splitted2[-4]
|
|
||||||
dbFileName = repoName + '@DBEXT@'
|
|
||||||
except:
|
|
||||||
dbFileName = ''
|
|
||||||
|
|
||||||
try:
|
|
||||||
serverToTime[serverUrl] = timeCmd(getFuncToTime(tempUrl + dbFileName))
|
|
||||||
if options.verbose:
|
|
||||||
try:
|
|
||||||
print "%.2f" % serverToTime[serverUrl]
|
|
||||||
except:
|
|
||||||
print serverToTime[serverUrl]
|
|
||||||
except:
|
|
||||||
print
|
|
||||||
printResults(serverToTime, options.times, options.verbose,
|
|
||||||
options.num)
|
|
||||||
sys.exit(0)
|
|
||||||
|
|
||||||
printResults(serverToTime, options.times, options.verbose, options.num)
|
|
||||||
|
|
||||||
# vim: set ts=4 sw=4 et:
|
|
202
scripts/rankmirrors.sh.in
Normal file
202
scripts/rankmirrors.sh.in
Normal file
|
@ -0,0 +1,202 @@
|
||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# rankmirrors - read a list of mirrors from a file and rank them by speed
|
||||||
|
# @configure_input@
|
||||||
|
#
|
||||||
|
# Copyright (c) 2009 Matthew Bruenig <matthewbruenig@gmail.com>
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# traps interrupt key to spit out pre-interrupt info
|
||||||
|
trap finaloutput INT
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
echo "Usage: rankmirrors [options] MIRRORFILE | URL"
|
||||||
|
echo
|
||||||
|
echo "Ranks pacman mirrors by their connection and opening speed. Pacman mirror"
|
||||||
|
echo "files are located in /etc/pacman.d/. It can also rank one mirror if the URL is"
|
||||||
|
echo "provided."
|
||||||
|
echo
|
||||||
|
echo "Options:"
|
||||||
|
echo " --version show program's version number and exit"
|
||||||
|
echo " -h, --help show this help message and exit"
|
||||||
|
echo " -n NUM number of servers to output, 0 for all"
|
||||||
|
echo " -t, --times only output mirrors and their response times"
|
||||||
|
echo " -u, --url test a specific url"
|
||||||
|
echo " -v, --verbose be verbose in ouptut"
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
version() {
|
||||||
|
echo "rankmirrors (pacman) @PACKAGE_VERSION@"
|
||||||
|
echo "Copyright (c) 2009 Matthew Bruenig <matthewbruenig@gmail.com>."
|
||||||
|
echo
|
||||||
|
echo "This is free software; see the source for copying conditions."
|
||||||
|
echo "There is NO WARRANTY, to the extent permitted by law."
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
err() {
|
||||||
|
echo "$1"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# gettime fetchurl (e.g gettime http://foo.com/core/os/i686/core.db.tar.gz)
|
||||||
|
# returns the fetching time, or timeout, or unreachable
|
||||||
|
gettime() {
|
||||||
|
IFS=' ' output=( $(curl -s -m 10 -w "%{time_total} %{http_code}" "$1" -o/dev/null) )
|
||||||
|
[[ $? = 28 ]] && echo timeout && return
|
||||||
|
[[ ${output[1]} -ge 400 || ${output[1]} -eq 0 ]] && echo unreachable && return
|
||||||
|
echo "${output[0]}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# getfetchurl serverurl (e.g. getturl http://foo.com/core/os/i686)
|
||||||
|
# if $repo is in the line, then assumes core
|
||||||
|
# if $arch is in the line, then assumes $(uname -m)
|
||||||
|
# returns a fetchurl (e.g. http://foo.com/core/os/i686/core.db.tar.gz)
|
||||||
|
ARCH="$(uname -m)"
|
||||||
|
getfetchurl() {
|
||||||
|
local strippedurl="${1%/}"
|
||||||
|
|
||||||
|
local replacedurl="${strippedurl//'$repo'/core}"
|
||||||
|
replacedurl="${replacedurl//'$arch'/$ARCH}"
|
||||||
|
|
||||||
|
local tmp="${replacedurl%/*}"
|
||||||
|
tmp="${tmp%/*}"
|
||||||
|
|
||||||
|
local reponame="${tmp##*/}"
|
||||||
|
if [[ -z $reponame || $reponame = $replacedurl ]]; then
|
||||||
|
echo "fail"
|
||||||
|
else
|
||||||
|
local fetchurl="${replacedurl}/$reponame@DBEXT@"
|
||||||
|
echo "$fetchurl"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# This exists to remove the need for a separate interrupt function
|
||||||
|
finaloutput() {
|
||||||
|
IFS=$'\n' sortedarray=( $(LC_COLLATE=C printf "%s\n" "${timesarray[@]}" | sort) )
|
||||||
|
|
||||||
|
# Final output for mirrorfile
|
||||||
|
numiterator="0"
|
||||||
|
if [[ $TIMESONLY ]]; then
|
||||||
|
echo
|
||||||
|
echo " Servers sorted by time (seconds):"
|
||||||
|
for line in "${sortedarray[@]}"; do
|
||||||
|
echo "${line#* } : ${line% *}"
|
||||||
|
((numiterator++))
|
||||||
|
[[ $NUM -ne 0 && $numiterator -ge $NUM ]] && break
|
||||||
|
done
|
||||||
|
else
|
||||||
|
for line in "${sortedarray[@]}"; do
|
||||||
|
echo "Server = ${line#* }"
|
||||||
|
((numiterator++))
|
||||||
|
[[ $NUM -ne 0 && $numiterator -ge $NUM ]] && break
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Argument parsing
|
||||||
|
[[ $1 ]] || usage
|
||||||
|
while [[ $1 ]]; do
|
||||||
|
if [[ "${1:0:2}" = -- ]]; then
|
||||||
|
case "${1:2}" in
|
||||||
|
help) usage ;;
|
||||||
|
version) version ;;
|
||||||
|
times) TIMESONLY=1 ; shift ;;
|
||||||
|
verbose) VERBOSE=1 ; shift ;;
|
||||||
|
url) CHECKURL=1; [[ $2 ]] || err "Must specify url."; URL="$2"; shift 2;;
|
||||||
|
*) err "\`$1' is an invalid argument."
|
||||||
|
esac
|
||||||
|
elif [[ ${1:0:1} = - ]]; then
|
||||||
|
|
||||||
|
if [[ ! ${1:1:1} ]]; then
|
||||||
|
[[ -t 0 ]] && err "Stdin is empty."
|
||||||
|
IFS=$'\n' linearray=( $(</dev/stdin) )
|
||||||
|
STDIN=1
|
||||||
|
shift
|
||||||
|
else
|
||||||
|
snum=1
|
||||||
|
for ((i=1 ; i<${#1}; i++)); do
|
||||||
|
case ${1:$i:1} in
|
||||||
|
h) usage ;;
|
||||||
|
t) TIMESONLY=1 ;;
|
||||||
|
v) VERBOSE=1 ;;
|
||||||
|
u) CHECKURL=1; [[ $2 ]] || err "Must specify url."; URL="$2"; snum=2;;
|
||||||
|
n) [[ $2 ]] || err "Must specify number." ; NUM="$2" ; snum=2;;
|
||||||
|
*) err "\`-$1' is an invald argument." ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
shift $snum
|
||||||
|
fi
|
||||||
|
elif [[ -f "$1" ]]; then
|
||||||
|
FILE="1"
|
||||||
|
IFS=$'\n' linearray=( $(<$1) )
|
||||||
|
[[ $linearray ]] || err "File is empty."
|
||||||
|
shift
|
||||||
|
else
|
||||||
|
err "\`$1' does not exist."
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Some sanity checks
|
||||||
|
[[ $NUM ]] || NUM=0
|
||||||
|
[[ $FILE && $CHECKURL ]] && err "Cannot specify a url and mirrorfile."
|
||||||
|
[[ $FILE || $CHECKURL || $STDIN ]] || err "Must specify url, mirrorfile, or stdin."
|
||||||
|
|
||||||
|
# Single url handling
|
||||||
|
if [[ $CHECKURL ]]; then
|
||||||
|
url="$(getfetchurl "$URL")"
|
||||||
|
[[ $url = fail ]] && err "url \`$URL' is malformed."
|
||||||
|
[[ $VERBOSE ]] && echo "Testing $url..."
|
||||||
|
time=$(gettime "$url")
|
||||||
|
echo "$URL : $time"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Get url results from mirrorfile, fill up the array, and so on
|
||||||
|
if [[ $TIMESONLY ]]; then
|
||||||
|
echo "Querying servers, this may take some time..."
|
||||||
|
elif [[ $FILE ]]; then
|
||||||
|
echo "# Server list generated by rankmirrors on $(date +%Y-%m-%d)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
timesarray=()
|
||||||
|
for line in "${linearray[@]}"; do
|
||||||
|
if [[ $line =~ ^# ]]; then
|
||||||
|
[[ $TIMESONLY ]] || echo $line
|
||||||
|
elif [[ $line =~ ^Server ]]; then
|
||||||
|
|
||||||
|
# Getting values and times and such
|
||||||
|
server="${line#*= }"
|
||||||
|
url="$(getfetchurl "$server")"
|
||||||
|
[[ $url = fail ]] && err "url \`$URL' is malformed."
|
||||||
|
time=$(gettime "$url")
|
||||||
|
timesarray+=("$time $server")
|
||||||
|
|
||||||
|
# Output
|
||||||
|
if [[ $VERBOSE && $TIMESONLY ]]; then
|
||||||
|
echo "$server ... $time"
|
||||||
|
elif [[ $VERBOSE ]]; then
|
||||||
|
echo "# $server ... $time"
|
||||||
|
elif [[ $TIMESONLY ]]; then
|
||||||
|
echo -n " *"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
finaloutput
|
||||||
|
|
||||||
|
# vim: set ts=2 sw=2 noet:
|
Loading…
Add table
Reference in a new issue