aboutsummaryrefslogtreecommitdiff
path: root/ports-mgmt/portmk/scripts
diff options
context:
space:
mode:
authorOliver Eikemeier <eik@FreeBSD.org>2004-07-06 12:41:03 +0000
committerOliver Eikemeier <eik@FreeBSD.org>2004-07-06 12:41:03 +0000
commit193ffbdfe83678690f5ed7a289fa511b66006f83 (patch)
tree27e1d2160ad77adae34ea49e01db91210533114c /ports-mgmt/portmk/scripts
parent4e3013cd8d46bc12b506ff9bfcb16ae14bc6cad1 (diff)
downloadports-193ffbdfe83678690f5ed7a289fa511b66006f83.tar.gz
ports-193ffbdfe83678690f5ed7a289fa511b66006f83.zip
Add devel/portmk, a place where bsd.port.mk development can happen.
Notes
Notes: svn path=/head/; revision=113054
Diffstat (limited to 'ports-mgmt/portmk/scripts')
-rw-r--r--ports-mgmt/portmk/scripts/distfiles.sh1038
-rw-r--r--ports-mgmt/portmk/scripts/ranksites-fping.pl139
-rw-r--r--ports-mgmt/portmk/scripts/ranksites-geoip.pl390
3 files changed, 1567 insertions, 0 deletions
diff --git a/ports-mgmt/portmk/scripts/distfiles.sh b/ports-mgmt/portmk/scripts/distfiles.sh
new file mode 100644
index 000000000000..994d40433bba
--- /dev/null
+++ b/ports-mgmt/portmk/scripts/distfiles.sh
@@ -0,0 +1,1038 @@
+#!/bin/sh -e
+#
+# Copyright (c) 2004 Oliver Eikemeier. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# 1. Redistributions of source code must retain the above copyright notice
+# this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# 3. Neither the name of the author nor the names of its contributors may be
+# used to endorse or promote products derived from this software without
+# specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# $FreeBSD$
+#
+# MAINTAINER= eik@FreeBSD.org
+#
+# These variables are referenced and must be exported from the Makefile:
+#
+# DISABLE_SIZE
+# DISTFILES
+# DISTINFO_ALGORITHMS
+# DISTINFO_LABEL
+# DIST_SUBDIR
+# ECHO_MSG
+# FETCH_AFTER_ARGS
+# FETCH_BEFORE_ARGS
+# FETCH_CMD
+# FETCH_ENV
+# FETCH_SYMLINK_DISTFILES
+# IGNOREFILES
+# LOCALBASE
+# MASTER_SITES
+# MASTER_SITE_BACKUP
+# MASTER_SITE_OVERRIDE
+# MASTER_SORT_AWK
+# MASTER_SORT_CMD
+# MASTER_SORT_ENV
+# MK_FILE
+# NO_SIZE
+# PATCHFILES
+# PATCH_SITES
+# PERL5
+# VALID_ALGORITHMS
+#
+# These variables are user settable:
+#
+# DISABLE_SIZE
+# NO_CHECKSUM
+# FETCH_REGET
+#
+
+# utilities
+
+LOCALBASE="${LOCALBASE:-/usr/local}"
+
+AWK=/usr/bin/awk
+CAT=/bin/cat
+CUT=/usr/bin/cut
+EXPR=/bin/expr
+FETCH=/usr/bin/fetch
+GREP=/usr/bin/grep
+LS=/bin/ls
+MD5=/sbin/md5
+MKDIR='/bin/mkdir -p'
+MKTEMP=/usr/bin/mktemp
+PERL5="${PERL5:-/usr/bin/perl}"
+RM=/bin/rm
+[ -x /sbin/rmd160 ] && RMD160=/sbin/rmd160
+SED=/usr/bin/sed
+SETENV=/usr/bin/env
+[ -x /sbin/sha1 ] && SHA1=/sbin/sha1
+SORT=/usr/bin/sort
+TR=/usr/bin/tr
+WC=/usr/bin/wc
+
+if [ -x /usr/bin/openssl ]; then
+ OPENSSL=/usr/bin/openssl
+elif -x "$LOCALBASE/bin/openssl" ];then
+ OPENSSL="$LOCALBASE/bin/openssl"
+fi
+
+# global constants
+
+MK_FILE_ENDMARKER='^\.include[ ]*(<bsd\.port(\.post)?\.mk>|"\${MASTERDIR}\/Makefile")$'
+
+FETCH_REGET="${FETCH_REGET:-1}"
+
+### utility functions ###
+
+###
+# do_hash is a wrapper for md5/openssl/digest to calculate MD5/SHA1/RMD160 hashes
+###
+
+do_hash()
+{
+ local alg
+ alg="$1"
+ shift
+
+ case "$alg" in
+ [Mm][Dd]5)
+ if [ $# -eq 0 ]; then
+ $MD5
+ else
+ $MD5 -- "$@"
+ fi;;
+ [Ss][Hh][Aa]1)
+ if [ -n "$SHA1" ]; then
+ echo $SHA1
+ if [ $# -eq 0 ]; then
+ $SHA1
+ else
+ $SHA1 -- "$@"
+ fi
+ else
+ if [ $# -eq 0 ]; then
+ "${OPENSSL:-true}" sha1
+ else
+ "${OPENSSL:-true}" sha1 ./"$@" |
+ $SED -En -e 's/^[[:alnum:]]+ *\((\.\/)?(.*)\) *= *([[:xdigit:]]+)$/SHA1 (\2) = \3/p'
+ fi
+ fi;;
+ [Rr][Mm][Dd]160)
+ if [ -n "$RMD160" ]; then
+ if [ $# -eq 0 ]; then
+ $RMD160
+ else
+ $RMD160 -- "$@"
+ fi
+ else
+ if [ $# -eq 0 ]; then
+ "${OPENSSL:-true}" rmd160
+ else
+ "${OPENSSL:-true}" rmd160 ./"$@" |
+ $SED -En -e 's/^[[:alnum:]]+ *\((\.\/)?(.*)\) *= *([[:xdigit:]]+)$/RMD160 (\2) = \3/p'
+ fi
+ fi;;
+ [Ss][Ii][Zz][Ee])
+ if [ $# -eq 0 ]; then
+ $WC -c
+ else
+ while [ $# -gt 0 ]; do
+ # avoid hassle with CLICOLOR_FORCE
+ $LS -ALdfln -- "$1" | $AWK '{ print "SIZE ('"$1"') = " $5 }'
+ shift
+ done
+ fi;;
+ *)
+ return 1;;
+ esac
+}
+
+###
+# extract_sum extracts all checksums for a file in distinfo
+###
+
+extract_sum()
+{
+ local algorithms pattern
+ algorithms=`echo -n "$1" | $TR -s ' \t\n' '|'`
+ pattern=`echo "$2$3" | $SED -e 's;[/.[\(*+?{|^$];\\\\&;g'`
+ # distfiles match [a-zA-Z0-9.,_/@&%?=+-]+
+
+ [ $# -eq 3 ] || return 1
+
+ if [ -f "$MD5_FILE" ]; then
+ $SED -En -e '/^('"$algorithms"') *\('"$pattern"'\) *= */s//\1=/p' "$MD5_FILE"
+ elif $GREP -qs "^#:distinfo${DISTINFO_LABEL:+\.$DISTINFO_LABEL}$" "$MK_FILE"; then
+ $SED -En -e '
+ 1,/'"$MK_FILE_ENDMARKER"'/d
+ /^#/!q
+ /^#:distinfo'"${DISTINFO_LABEL:+.$DISTINFO_LABEL}"'$/,/^#:/ {
+ s/^#('"$algorithms"') *\('"$pattern"'\) *= */\1=/
+ t match
+ b nomatch
+ :match
+ H
+ :nomatch
+ }
+ $ {
+ g
+ p
+ }
+ ' "$MK_FILE"
+ else
+ for alg in $1; do
+ for sum in `eval echo \\$DISTINFO_$alg`; do
+ if [ "${sum%:*}" = "$3" ]; then
+ echo "$alg=${sum##*:}"
+ fi
+ done
+ done
+ fi
+}
+
+###
+# chksumfiles calculates CKSUMFILES = DISTFILES + PATCHFILES - IGNOREFILES
+###
+
+chksumfiles()
+{
+ echo "$IGNOREFILES" '<>' "$DISTFILES" "$PATCHFILES" |
+ $TR -s ' \t' '\n' | $AWK '
+ BEGIN { isignore=1 }
+ /^$/ { next }
+ /^<>$/ { isignore=0; next }
+ {
+ if (isignore !=0) {
+ ignore[$0]=1
+ } else if (!($0 in ignore)) {
+ sub(/:[^:]+$/, "")
+ print
+ }
+ }
+ '
+}
+
+### fetching distfiles ###
+
+###
+# fetch_xxx are wrappers for fetch
+###
+
+setup_fetch_cmd()
+{
+ [ -z "$fetch_cmd" ] || return 0
+
+ case "${FETCH_CMD%% *}" in
+ */curl)
+ fetch_cmd=fetch_curl;;
+ */wget)
+ fetch_cmd=fetch_wget;;
+ *)
+ fetch_cmd=fetch_fetch;;
+ esac
+}
+
+fetch_curl()
+{
+ local cksize
+
+ cksize=
+ if [ -n "$3" ]; then
+ cksize=" --max-filesize $3"
+ fi
+
+ $SETENV $FETCH_ENV $FETCH_CMD $FETCH_BEFORE_ARGS$cksize \
+ $4 -o "$2" "$1" $FETCH_AFTER_ARGS
+}
+
+fetch_fetch()
+{
+ local cksize
+
+ case "$2" in
+ */*)
+ [ -d "${file%/*}" ] || $MKDIR "${file%/*}";;
+ esac
+
+ symlink=
+ if [ -n "$FETCH_SYMLINK_DISTFILES" ]; then
+ symlink=" -l"
+ fi
+
+ cksize=
+ if [ -n "$3" -a "$OSVERSION" -ge 480000 ]; then
+ cksize=" -S $3"
+ fi
+
+ $SETENV $FETCH_ENV $FETCH_CMD $FETCH_BEFORE_ARGS$symlink$cksize \
+ $4 -o "$2" "$1" $FETCH_AFTER_ARGS
+}
+
+fetch_wget()
+{
+ case "$4" in
+ file:*)
+ fetch_fetch "$@" || return 1
+ return 0;;
+ esac
+
+ case "$2" in
+ */*)
+ [ -d "${file%/*}" ] || $MKDIR "${file%/*}";;
+ esac
+
+ $SETENV $FETCH_ENV $FETCH_CMD $FETCH_BEFORE_ARGS \
+ $4 -O "$2" "$1" $FETCH_AFTER_ARGS
+}
+
+###
+# get_master_sites returns a list of $1_SITES for groups $2
+###
+
+get_master_sites()
+{
+ [ $# -eq 2 ] || return 1
+
+ # fun with awk
+ for group in $2; do
+ eval echo "\"\${$1_SITE_SUBDIR}\"" "'<>'" "\"\${$1_SITES}\"" |
+ $TR -s ' \t' '\n' |
+ $AWK '
+ BEGIN {
+ issubdir=1
+ subdirs=0
+ }
+ /^$/ { next }
+ /^<>$/ {
+ issubdir=0
+ if (subdirs == 0)
+ subdir[subdirs++]=""
+ next
+ }
+ {
+ if ($0 ~ /\/:[^\/:]+$/) {
+ if ($0 !~ /\/:([^\/:]*,)*'"$group"'(,[^\/:]*)*$/)
+ next
+ sub(/\/:[^\/:]+$/, issubdir != 0 ? "" : "/")
+ } else if ("'"$group"'" != "DEFAULT") {
+ next
+ }
+ }
+ {
+ if (issubdir != 0)
+ subdir[subdirs++]=($0 == "." ? "" : $0 "/")
+ else
+ for (i in subdir) {
+ site=$0
+ gsub(/%SUBDIR%\//, subdir[i], site)
+ print site
+ }
+ }
+ ';
+ done |
+ $AWK '{ if ($0 in done) next; done[$0]=1 } { print }'
+}
+
+###
+# get_master_sites_sorted returns a sorted list of $1_SITES for groups $2
+###
+
+get_master_sites_sorted()
+{
+ get_master_sites "$@" |
+ if [ -n "$MASTER_SORT_CMD" ]; then
+ $SETENV $MASTER_SORT_ENV $MASTER_SORT_CMD | $TR -s '\n' ' '
+ elif [ -z "$KEEP_MASTER_SITE_ORDER" ]; then
+ $AWK 'BEGIN { srand() } { print rand() "\t" $0 }' |
+ $SORT -n | $CUT -f 2 | $TR -s '\n' ' ' |
+ $AWK "$MASTER_SORT_AWK"
+ else
+ $TR -s '\n' ' ' |
+ $AWK "$MASTER_SORT_AWK"
+ fi
+}
+
+###
+# fetch_file tries to fetch one file from {MASTER,PATCH}_SITES
+###
+
+fetch_file()
+{
+ [ $# -eq 5 ] || return 1
+
+ fetch_reget="${FETCH_REGET}"
+ SORTED_MASTER_SITES_TMP=`get_master_sites_sorted "$1" "$2"`
+ for site in $_MASTER_SITE_OVERRIDE \
+ $SORTED_MASTER_SITES_TMP $_MASTER_SITE_BACKUP; do
+ $ECHO_MSG ">> Attempting to fetch from $site${4:+ (${4#*=} bytes)}."
+ case "$site" in
+ *%FILE%*)
+ # this expression uses ctrl-A as delimiters
+ url=`echo "$site" | $SED -E -e 's/$; s%FILE%'"$file"'g'`;;
+ *)
+ url="$site$file";;
+ esac
+ if $fetch_cmd "$url" "$3" "$4"; then
+ [ -f "$file" ] || continue
+ [ -z "$5" ] && return 0
+ for cksum2 in $5; do
+ case "${cksum2#*=}" in
+ IGNORE)
+ return 0;;
+ *)
+ CKSUM=`do_hash "${cksum2%%=*}" < "$file"`
+ if [ "${cksum2#*=}" = "$CKSUM" ]; then
+ $ECHO_MSG ">> Checksum OK (${cksum2%%=*}) for $file."
+ return 0
+ fi;;
+ esac
+ done
+ $ECHO_MSG ">> Checksum mismatch for $_file."
+ if [ "$fetch_reget" -gt 0 ]; then
+ $ECHO_MSG "===> Refetch for $fetch_reget more times."
+ $RM -f "$file"
+ fetch_reget=$(($fetch_reget-1))
+ else
+ $ECHO_MSG ">> To get this file from more mirrors," \
+ "type \"make FETCH_REGET=99 [other args]\"."
+ $ECHO_MSG "===> Giving up on fetching $_file."
+ return 1
+ fi
+ fi
+ done
+ $ECHO_MSG ">> Couldn't fetch it - please try to retrieve this"
+ $ECHO_MSG ">> file manually into $_DISTDIR and try again."
+ return 1
+}
+
+###
+# do_fetch tries to fetch DISTFILES and PATCHFILES
+###
+
+do_fetch()
+{
+ local _DISTDIR
+ local DIR
+ local file
+ local select
+
+ setup_fetch_cmd
+
+ _DISTDIR="$DISTDIR${DIST_SUBDIR:+/$DIST_SUBDIR}"
+ DIR="${DIST_SUBDIR:+$DIST_SUBDIR/}"
+
+ for fileset in MASTER PATCH; do
+ case "$fileset" in
+ MASTER)
+ files="$DISTFILES";;
+ PATCH)
+ files="$PATCHFILES";;
+ *)
+ return 1;;
+ esac
+ for _file in $files; do
+
+ file=`echo "$_file" | $SED -E -e 's/:[^:]+$//'`
+ select=`echo "$_file" | $SED -En -e 'y/,/ /; s/.*:([^:]+)$/\1/p'`
+ [ -n "$select" ] || select="DEFAULT"
+
+ if [ -z "$NO_CHECKSUM" ]; then
+ CKSUM2=`extract_sum "$VALID_ALGORITHMS" "$DIR" "$file"`
+ if [ -z "$CKSUM2" ]; then
+ $ECHO_MSG ">> No checksum entry for $DIR$file."
+ $ECHO_MSG ">> Make sure the Makefile and distinfo file ($MD5_FILE) are"
+ $ECHO_MSG ">> up to date. If you are absolutely sure you want to override"
+ $ECHO_MSG ">> this check, type \"make NO_CHECKSUM=yes [other args]\"."
+ return 1
+ fi
+ chkfile=true
+ for ignore in $IGNOREFILES; do
+ if [ "$file" = "$ignore" ]; then
+ chkfile=false
+ fi
+ done
+ else
+ CKSUM2=
+ chkfile=false
+ fi
+
+ if [ -f "$_DISTDIR/$file" ]; then
+ fileexists=true
+ else
+ fileexists=false
+ if [ -L $file ]; then
+ $ECHO_MSG ">> $_DISTDIR/$file is a broken symlink."
+ $ECHO_MSG ">> Perhaps a filesystem (most likely a CD) isn't mounted?"
+ $ECHO_MSG ">> Please correct this problem and try again."
+ return 1
+ fi
+ fi
+
+ fetchfile=true
+ if $fileexists; then
+ if [ -n "$CKSUM2" ]; then
+ for cksum2 in $CKSUM2; do
+ case "${cksum2#*=}" in
+ IGNORE)
+ if $chkfile; then
+ $ECHO_MSG ">> Checksum for $file is set to IGNORE in distinfo file"
+ $ECHO_MSG " even though the file is not in the "'$'"{IGNOREFILES} list."
+ return 1
+ fi
+ fetchfile=false
+ break;;
+ *)
+ if ! $chkfile; then
+ $ECHO_MSG ">> Checksum for $file is not set to IGNORE in distinfo file"
+ $ECHO_MSG " even though the file is in the "'$'"{IGNOREFILES} list."
+ return 1
+ fi
+ CKSUM=`do_hash "${cksum2%%=*}" < "$_DISTDIR/$file"`
+ if [ "${cksum2#*=}" = "$CKSUM" ]; then
+ $ECHO_MSG ">> Checksum OK (${cksum2%%=*}) for $file."
+ fetchfile=false
+ break
+ fi;;
+ esac
+ done
+ if $fetchfile; then
+ $ECHO_MSG ">> Checksum mismatch for $file."
+ fi
+ else
+ fetchfile=false
+ fi
+ else
+ if [ -n "$CKSUM2" ]; then
+ for cksum2 in $CKSUM2; do
+ case "${cksum2#*=}" in
+ IGNORE)
+ if $chkfile; then
+ $ECHO_MSG ">> Checksum for $file is set to IGNORE in distinfo file"
+ $ECHO_MSG " even though the file is not in the "'$'"{IGNOREFILES} list."
+ return 1
+ fi
+ break;;
+ *)
+ if ! $chkfile; then
+ $ECHO_MSG ">> Checksum for $file is not set to IGNORE in distinfo file"
+ $ECHO_MSG " even though the file is in the "'$'"{IGNOREFILES} list."
+ return 1
+ fi;;
+ esac
+ done
+ fi
+ $ECHO_MSG ">> $file doesn't seem to exist in $_DISTDIR."
+ fi
+
+ if $fetchfile; then
+ if ! { [ -d "$_DISTDIR" ] || $MKDIR "$_DISTDIR"; }; then
+ $ECHO_MSG ">> Cannot create $_DISTDIR."
+ return 1
+ fi
+ if [ ! -w "$_DISTDIR" ]; then
+ $ECHO_MSG ">> $_DISTDIR is not writable by you; cannot fetch."
+ return 1
+ fi
+ if [ -z "$NO_CHECKSUM" -a -z "$DISABLE_SIZE" ]; then
+ CKSIZE=`extract_sum 'SIZE' "$DIR" "$file"`
+ else
+ CKSIZE=
+ fi
+ cd "$_DISTDIR"
+ if ! fetch_file "$fileset" "$select" "$file" "${CKSIZE#*=}" "$CKSUM2"; then
+ return 1
+ fi
+ fi
+ done
+ done
+}
+
+### missing size ###
+
+###
+# print_missing_size prints a list of all files that are not in DISTDIR
+###
+
+print_missing_size()
+{
+ local _DISTDIR
+ local DIR
+ local file
+ local select
+
+ CKSUMFILES="${CKSUMFILES:-`chksumfiles`}"
+
+ DIR="${DIST_SUBDIR:+$DIST_SUBDIR/}"
+
+ for _file in $CKSUMFILES; do
+ file="$DIR$_file"
+ [ -f "$DISTDIR/$file" ] && continue
+ CKSIZE=`extract_sum 'SIZE' "$DIR" "$_file"`
+ if [ -n "${CKSIZE#*=}" ]; then
+ echo "${CKSIZE#*=} $file"
+ else
+ echo "0 $file"
+ fi
+ done
+
+ for _file in $IGNOREFILES; do
+ file="$DIR$_file"
+ [ -f "$DISTDIR/$file" ] && continue
+ echo "0 $file"
+ done
+}
+
+### fetch all ##
+
+###
+# do_fetch_all tries to fetch all files from *every* site
+###
+
+do_fetch_all()
+{
+ local DIR
+ local file
+ local select
+
+ setup_fetch_cmd
+
+ _FAILED_SITES=
+ DIR="${DIST_SUBDIR:+$DIST_SUBDIR/}"
+
+ for fileset in MASTER PATCH; do
+ case "$fileset" in
+ MASTER)
+ files="$DISTFILES";;
+ PATCH)
+ files="$PATCHFILES";;
+ *)
+ return 1;;
+ esac
+
+ for _file in $files; do
+ file=`echo "$_file" | $SED -E -e 's/:[^:]+$//'`
+ select=`echo "$_file" | $SED -En -e 'y/,/ /; s/.*:([^:]+)$/\1/p'`
+ [ -n "$select" ] || select="DEFAULT"
+
+ CKSUM2=`extract_sum "$VALID_ALGORITHMS" "$DIR" "$file"`
+ if [ -z "$CKSUM2" ]; then
+ $ECHO_MSG ">> No checksum recorded for $DIR$file."
+ return 1
+ fi
+ CKSIZE=`extract_sum 'SIZE' "$DIR" "$file"`
+
+ $ECHO_MSG ">> Verifying availability of file $file."
+ MASTER_SITES_TMP=`get_master_sites "$fileset" "$select"`
+ for site in $MASTER_SITES_TMP; do
+ $ECHO_MSG ">> Attempting to fetch from $site${CKSIZE:+ (${CKSIZE#*=} bytes)}."
+ case "$site" in
+ *%FILE%*)
+ # this expression uses ctrl-A as delimiters
+ url=`echo "$site" | $SED -E -e 's/$; s%FILE%'"$file"'g'`;;
+ *)
+ url="$site$file";;
+ esac
+ if [ -z "$NO_CHECKSUM" ]; then
+ for cksum2 in $CKSUM2; do
+ _FETCH_RESULT=`{ if ! $fetch_cmd "$url" "-" "${CKSIZE#*=}"; then \
+ echo "FAILED: $$?" >&3; fi | do_hash "${cksum2%%=*}"; } 3>&1`;
+ case "$_FETCH_RESULT" in
+ FAILED:*)
+ $ECHO_MSG ">> Fetch from $site failed."
+ _FAILED_SITES="${_FAILED_SITES:+$_FAILED_SITES }$url";;
+ *)
+ case "${cksum2#*=}" in
+ IGNORE)
+ $ECHO_MSG ">> Checksum IGNORED for $file.";;
+ "$_FETCH_RESULT")
+ $ECHO_MSG ">> Checksum OK (${cksum2%%=*}) for $file.";;
+ *)
+ $ECHO_MSG ">> Checksum mismatch (${cksum2%%=*}) for $file."
+ _FAILED_SITES="${_FAILED_SITES:+$_FAILED_SITES }$url";;
+ esac;;
+ esac
+ break
+ done
+ else
+ if _FETCH_RESULT=`$SETENV $FETCH_ENV $FETCH -s "$url"`; then
+ if [ -z "$DISABLE_SIZE" -a -n "${CKSIZE#*=}" ]; then
+ if [ "${CKSIZE#*=}" = "$_FETCH_RESULT" ]; then
+ $ECHO_MSG ">> Size OK (${CKSIZE#*=}) for $file."
+ else
+ $ECHO_MSG ">> Size mismatch ($_FETCH_RESULT) for $file."
+ _FAILED_SITES="${_FAILED_SITES:+$_FAILED_SITES }$url"
+ fi
+ else
+ $ECHO_MSG ">> Found $file."
+ fi
+ else
+ echo ">> Fetch from $site failed."
+ _FAILED_SITES="${_FAILED_SITES:+$_FAILED_SITES }$url"
+ fi
+ fi
+ done
+ done
+ done
+ if [ -z "$_FAILED_SITES" ]; then
+ echo ">> All files are fetchable."
+ else
+ echo ">> The following files did not fetch correctly:"
+ echo "$_FAILED_SITES" | ${TR} ' ' '\n' | ${SED} -e 's/^/ - /'
+ fi
+}
+
+###
+# do_fetch_list generates a list of files to fetch
+###
+
+do_fetch_list()
+{
+ local _DISTDIR
+ local DIR
+ local file
+ local select
+
+ _DISTDIR="$DISTDIR${DIST_SUBDIR:+/$DIST_SUBDIR}"
+ DIR="${DIST_SUBDIR:+$DIST_SUBDIR/}"
+
+ for fileset in MASTER PATCH; do
+ case "$fileset" in
+ MASTER)
+ files="$DISTFILES";;
+ PATCH)
+ files="$PATCHFILES";;
+ *)
+ return 1;;
+ esac
+
+ for _file in $files; do
+
+ file=`echo "$_file" | $SED -E -e 's/:[^:]+$//'`
+ select=`echo "$_file" | $SED -En -e 'y/,/ /; s/.*:([^:]+)$/\1/p'`
+ [ -n "$select" ] || select="DEFAULT"
+
+ if [ ! -f "$_DISTDIR/$file" ]; then
+ SORTED_MASTER_SITES_TMP=`get_master_sites_sorted "$fileset" "$select"`
+ for site in $_MASTER_SITE_OVERRIDE \
+ $SORTED_MASTER_SITES_TMP $_MASTER_SITE_BACKUP; do
+ case "$site" in
+ *%FILE%*)
+ # this expression uses ctrl-A as delimiters
+ url=`echo "$site" | $SED -E -e 's/$; s%FILE%'"$file"'g'`;;
+ *)
+ url="$site$file";;
+ esac
+ if [ -n "$FETCH_ENV" ]; then
+ echo -n "$SETENV $FETCH_ENV "
+ fi
+ echo -n "$FETCH_CMD $FETCH_BEFORE_ARGS" \
+ "-o '$file' '$url' $FETCH_AFTER_ARGS || "
+ done
+ echo "echo '$file not fetched'"
+ fi
+ done
+
+ done
+}
+
+### distinfo ###
+
+###
+# make_tmpsum generates a temporary distinfo file
+###
+
+make_tmpsum()
+{
+ local NO_CHECKSUM DISABLE_SIZE
+
+ NO_CHECKSUM=true
+ DISABLE_SIZE=true
+
+ do_fetch || return 1
+
+ CKSUMFILES="${CKSUMFILES:-`chksumfiles`}"
+
+ if ! TMPMD5_FILE=`$MKTEMP -q "$MD5_FILE.XXXXXX"`; then
+ echo ">> makesum: Can't create temporary checksum file"
+ return 1
+ fi
+
+ cd "$DISTDIR"
+ DIR="${DIST_SUBDIR:+$DIST_SUBDIR/}"
+
+ MY_ALGS="$DISTINFO_ALGORITHMS";
+ [ -z "$NO_SIZE" ] && MY_ALGS="$MY_ALGS SIZE"
+
+ # faster, but not the same sort order as the `classic' distinfo
+ #for alg in $MY_ALGS; do
+ # do_hash "$alg" `echo "$CKSUMFILES" | $SED -e "s^$DIR"` >> "$TMPMD5_FILE"
+ #done
+
+ for _file in $CKSUMFILES; do
+ file="$DIR$_file"
+ if [ -r "$file" ]; then
+ for alg in $MY_ALGS; do
+ do_hash "$alg" "$file" >> "$TMPMD5_FILE"
+ done
+ else
+ $ECHO_MSG ">> $file is not in $DISTDIR"
+ $RM "$TMPMD5_FILE"
+ return 1
+ fi
+ done
+ for _file in $IGNOREFILES; do
+ file="$DIR$_file"
+ echo "MD5 ($file) = IGNORE" >> "$TMPMD5_FILE"
+ done
+}
+
+###
+# replace_distinfo adds or replaces a distinfo entry in MK_FILE
+###
+
+replace_distinfo()
+{
+ [ $# -eq 1 -a -f "$1" ] || return 1
+
+ if ! TMPMK_FILE=`$MKTEMP -q "$MK_FILE.XXXXXX"`; then
+ $ECHO_MSG ">> makesum: Can't create temporary Makefile"
+ return 1
+ fi
+ if ! $AWK -v MD5_FILE="$1" '
+ BEGIN { seen=0; ignore=0; first=1 }
+ /'"$MK_FILE_ENDMARKER"'/ { seen=NR }
+ NR == 1, seen != 0 { print; next }
+ !/^#/ { exit 1 }
+ /^#:/ { ignore=0 }
+ /^#:distinfo'"${DISTINFO_LABEL:+\.$DISTINFO_LABEL}"'$/ {
+ if (first)
+ while ((getline md5_line < MD5_FILE) > 0) {
+ if (first) {
+ print "#:distinfo'"${DISTINFO_LABEL:+\.$DISTINFO_LABEL}"'"
+ first=0
+ }
+ print "#" md5_line
+ }
+ ignore=1
+ }
+ ignore == 0 { print }
+ END {
+ if (seen == 0)
+ exit 1
+ if (first)
+ while ((getline md5_line < MD5_FILE) > 0) {
+ if (first) {
+ print "#:distinfo'"${DISTINFO_LABEL:+\.$DISTINFO_LABEL}"'"
+ first=0
+ }
+ print "#" md5_line
+ }
+ }
+ ' "$MK_FILE" > "$TMPMK_FILE"; then
+ $ECHO_MSG ">> Parse error: $MK_FILE, end of file not found"
+ $RM "$TMPMK_FILE"
+ return 1
+ fi
+ $CAT "$TMPMK_FILE" > "$MK_FILE"
+ $RM "$TMPMK_FILE"
+}
+
+###
+# replace_distinfo2 adds or replaces a distinfo entry in MK_FILE
+###
+
+replace_distinfo2()
+{
+ [ $# -eq 1 -a -f "$1" ] || return 1
+
+ if [ ! -x "$PERL5" ]; then
+ $ECHO_MSG ">> makesum: perl 5 required, please install lang/perl"
+ return 1
+ fi
+
+ #XXX TODO: honor status of $ECHO_MSG in `die'
+ if ! $PERL5 -w -e '
+ use strict;
+ srand();
+ my $marker="##-MARKER_".rand()."-##";
+ my $valid_algs=join "|", "SIZE", split " ", $ARGV[3];
+ my $distsubdir=$ARGV[1] ? "$ARGV[1]/" : "";
+ my $distlabel=$ARGV[2] ? "$ARGV[2]_" : "";
+ my %distinfo;
+
+ open DISTINFO, "<$ARGV[0]"
+ or die ">> migratesum2: error reading $ARGV[0]\n";
+ while(<DISTINFO>) {
+ push @{$distinfo{$1}{$2}}, $3
+ if /^(\w+) *\($distsubdir(.*)\) *= *([\da-f]+)$/o
+ }
+ close DISTINFO;
+ my $makefile;
+ open MAKEFILE, "<$ARGV[4]"
+ or die ">> migratesum2: error reading $ARGV[4]\n";
+ {
+ local $/;
+ $makefile = <MAKEFILE>;
+ }
+ close MAKEFILE;
+ my $newinfo;
+ foreach my $key (split " ", $ARGV[3]) {
+ next
+ if !$distinfo{$key};
+ my @chksum = ();
+ foreach my $file (sort keys %{$distinfo{$key}}) {
+ push @chksum, map "$file:$_", @{$distinfo{$key}{$file}};
+ }
+ $newinfo .= "DISTINFO_$distlabel$key+=\t";
+ $newinfo .= join " \\\n\t\t", "", @chksum;
+ $newinfo .= "\n";
+ }
+ $makefile =~ s/^DISTINFO_$distlabel(?:$valid_algs)[+:!?]?=.*(?:\\\n.*)*[^\\\n]\n/$marker\n/mg ||
+ $makefile =~ s/^(COMMENT[+:!?]?=.*(?:\\\n.*)*[^\\\n])\n+/$1\n\n$marker\n\n/m ||
+ die ">> migratesum2: error parsing $ARGV[4]\n";
+
+ $makefile =~ s/^$marker\n/$newinfo/m;
+ $makefile =~ s/^$marker\n//mg;
+
+ open MAKEFILE, ">$ARGV[5]"
+ or die ">> migratesum2: error writing $ARGV[4]\n";
+ print MAKEFILE $makefile;
+ close MAKEFILE;
+ ' "$1" "$DIST_SUBDIR" "$DISTINFO_LABEL" "$VALID_ALGORITHMS SIZE" "$MK_FILE" "$MK_FILE"; then
+ return 1
+ fi
+}
+
+
+###
+# do_makesum (re-)calculates distinfo
+###
+
+do_makesum()
+{
+ local algorithms
+ algorithms=`echo -n "$VALID_ALGORITHMS SIZE" | $TR -s ' \t\n' '|'`
+
+ make_tmpsum || return 1
+
+ if [ -f "$MD5_FILE" ]; then
+ $CAT "$TMPMD5_FILE" > "$MD5_FILE"
+ elif $GREP -qs "^#:distinfo${DISTINFO_LABEL:+\.$DISTINFO_LABEL}$" "$MK_FILE"; then
+ replace_distinfo "$TMPMD5_FILE"
+ elif $GREP -Eqs "^DISTINFO${DISTINFO_LABEL:+_$DISTINFO_LABEL}_($algorithms)[+:!?]?=" "$MK_FILE"; then
+ replace_distinfo2 "$TMPMD5_FILE"
+ elif [ -s "$TMPMD5_FILE" ]; then
+ $CAT "$TMPMD5_FILE" > "$MD5_FILE"
+ fi
+
+ $RM "$TMPMD5_FILE"
+}
+
+###
+# do_migratemakesum integrates distinfo into the port's Makefile
+###
+
+do_migratesum()
+{
+ if [ ! -f "$MD5_FILE" ]; then
+ $ECHO_MSG ">> migratesum: no $MD5_FILE"
+ return 1
+ fi
+
+ if replace_distinfo "$MD5_FILE"; then
+ $RM "$MD5_FILE"
+ echo ">> Done."
+ else
+ return 1
+ fi
+}
+
+###
+# do_migratemakesum2 integrates distinfo into the port's Makefile
+###
+
+do_migratesum2()
+{
+ if [ ! -f "$MD5_FILE" ]; then
+ $ECHO_MSG ">> migratesum2: no $MD5_FILE"
+ return 1
+ fi
+
+ if replace_distinfo2 "$MD5_FILE"; then
+ $RM "$MD5_FILE"
+ echo ">> Done."
+ else
+ return 1
+ fi
+}
+
+###
+# main
+###
+
+opt_fetch_list=false
+opt_makesum=false
+opt_migratesum=false
+opt_migratesum2=false
+opt_fetch=false
+opt_fetch_all=false
+opt_missing_size=false
+
+while getopts "LmMNfFS" opt; do
+ case "$opt" in
+ L) opt_fetch_list=true;;
+ m) opt_makesum=true;;
+ M) opt_migratesum=true;;
+ N) opt_migratesum2=true;;
+ f) opt_fetch=true;;
+ F) opt_fetch_all=true;;
+ S) opt_missing_size=true;;
+ ?) echo "Usage: $0 -LmMfFS"; exit 1;;
+ esac
+done
+
+shift $(($OPTIND-1))
+
+$opt_fetch_list &&
+ { do_fetch_list || exit 1; }
+
+$opt_fetch &&
+ { do_fetch || exit 1; }
+
+$opt_makesum &&
+ { do_makesum || exit 1; }
+
+$opt_migratesum &&
+ { do_migratesum || exit 1; }
+
+$opt_migratesum2 &&
+ { do_migratesum2 || exit 1; }
+
+$opt_fetch_all &&
+ { do_fetch_all || exit 1; }
+
+$opt_missing_size &&
+ { print_missing_size || exit 1; }
+
+exit 0
diff --git a/ports-mgmt/portmk/scripts/ranksites-fping.pl b/ports-mgmt/portmk/scripts/ranksites-fping.pl
new file mode 100644
index 000000000000..db399548b22c
--- /dev/null
+++ b/ports-mgmt/portmk/scripts/ranksites-fping.pl
@@ -0,0 +1,139 @@
+#!/usr/bin/perl -w
+#
+# Copyright (c) 2004 Oliver Eikemeier. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# 1. Redistributions of source code must retain the above copyright notice
+# this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# 3. Neither the name of the author nor the names of its contributors may be
+# used to endorse or promote products derived from this software without
+# specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# $FreeBSD$
+#
+# MAINTAINER= eik@FreeBSD.org
+#
+
+require 5.005;
+use strict;
+
+my $dbdir = $ENV{RANKDIR} ? $ENV{RANKDIR} : '/var/db/distrank';
+
+my $fping = $ENV{FPING} ? $ENV{FPING} : '/usr/local/sbin/fping';
+
+-x $fping
+ or die "fping required\n";
+
+-d $dbdir || mkdir $dbdir, 0777
+ or die "Can't create $dbdir\n";
+
+my $rankfile = "$dbdir/ranks-fping";
+
+my $now = time;
+
+my %distance;
+
+if (-r $rankfile) {
+ open RANKS, "<$rankfile";
+ while (<RANKS>) {
+ chomp;
+ my ($host, $d, $e) = split;
+ $distance{$host} = [$d, $e]
+ if defined $e && $e >= $now;
+ }
+ close RANKS;
+}
+
+my %mastersites;
+my %newdistance;
+
+my $distgood = 0;
+my $distdefault = 5000;
+my $distbad = 10000;
+
+my $expgood = $now + 14 * 86400;
+my $expdefault = $now + 7 * 86400;
+
+my $hostcount = 0;
+
+while (<>) {
+ chomp;
+ next
+ if exists $mastersites{$_};
+ if (m'^(?:ftp|https?)://(?:[^/]*@)?([^/:]+\.[^/:]+)(?::\d+)?(?:/|$)'i) {
+ my $host = lc $1;
+ $mastersites{$_} = $host;
+ if (!defined $distance{$host}) {
+ $distance{$host} = [$distdefault, $expdefault];
+ $newdistance{$host} = undef
+ }
+ $hostcount++;
+ } elsif (m'^file:'i) {
+ $mastersites{$_} = 'FILE';
+ } else {
+ $mastersites{$_} = 'UNKNOWN';
+ }
+}
+
+if (%newdistance && $hostcount > 1) {
+ if (!open FPING, '-|') {
+ if (!open FPINGIN, '|-') {
+ open STDERR, '>&STDOUT';
+ exec $fping, '-q', '-C', '3';
+ die
+ }
+ foreach (keys %newdistance) {
+ print FPINGIN $_, "\n";
+ }
+ close FPINGIN;
+ exit;
+ }
+
+ while(<FPING>) {
+ /([^\s:]+)\s*:\s*([\s\d.-]*)/ or next;
+ my $sum = 0.0;
+ my $num = 0;
+ foreach my $val (split ' ', $2) {
+ $val ne '-' || next;
+ $sum += $val;
+ $num++;
+ }
+ if ($num > 0) {
+ $distance{$1} = [$sum/$num, $expgood];
+ }
+ }
+ close FPING;
+
+ open RANKS, ">$rankfile";
+ while (my ($host, $val) = each %distance) {
+ printf RANKS "%s\t%.2f\t%d\n", $host, $val->[0], $val->[1]
+ if defined $val;
+ }
+ close RANKS;
+}
+
+$distance{FILE} = [$distgood, 0];
+$distance{UNKNOWN} = [$distbad, 0];
+
+foreach (sort {$distance{$mastersites{$a}}->[0] <=> $distance{$mastersites{$b}}->[0]} keys %mastersites) {
+ print $_, "\n";
+}
diff --git a/ports-mgmt/portmk/scripts/ranksites-geoip.pl b/ports-mgmt/portmk/scripts/ranksites-geoip.pl
new file mode 100644
index 000000000000..4631ff6038a3
--- /dev/null
+++ b/ports-mgmt/portmk/scripts/ranksites-geoip.pl
@@ -0,0 +1,390 @@
+#!/usr/bin/perl -w
+#
+# Copyright (c) 2004 Oliver Eikemeier. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# 1. Redistributions of source code must retain the above copyright notice
+# this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# 3. Neither the name of the author nor the names of its contributors may be
+# used to endorse or promote products derived from this software without
+# specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# $FreeBSD$
+#
+# MAINTAINER= eik@FreeBSD.org
+#
+
+require 5.005;
+use strict;
+use Geo::IP;
+use constant PI => 3.14159265358979323846;
+
+my $home = $ENV{CC_HOME} ? lc $ENV{CC_HOME} : 'eu';
+
+my $dbdir = $ENV{RANKDIR} ? $ENV{RANKDIR} : '/var/db/distrank';
+
+-d $dbdir || mkdir $dbdir, 0777 or die "Can't create $dbdir\n";
+
+my $rankfile = "$dbdir/ranks-geoip";
+
+my $now = time;
+
+my %distance;
+
+if (-r $rankfile) {
+ open RANKS, "<$rankfile";
+ while (<RANKS>) {
+ chomp;
+ my ($host, $d, $e) = split;
+ $distance{$host} = [$d, $e]
+ if defined $e && $e >= $now;
+ }
+ close RANKS;
+}
+
+my %mastersites;
+my %newdistance;
+
+my $distgood = -1;
+my $distdefault = PI/2;
+my $distbad = 2;
+
+my $expgood = $now + 14 * 86400;
+my $expdefault = $now + 7 * 86400;
+
+my $hostcount = 0;
+
+while (<>) {
+ chomp;
+ next
+ if exists $mastersites{$_};
+ if (m'^(?:ftp|https?)://(?:[^/]*@)?([^/:]+\.[^/:]+)(?::\d+)?(?:/|$)'i) {
+ my $host = lc $1;
+ $mastersites{$_} = $host;
+ if (!defined $distance{$host}) {
+ $distance{$host} = [$distdefault, $expdefault];
+ $newdistance{$host} = undef
+ }
+ $hostcount++;
+ } elsif (m'^file:'i) {
+ $mastersites{$_} = 'FILE';
+ } else {
+ $mastersites{$_} = 'UNKNOWN';
+ }
+}
+
+# calculate_distance and the associated table is from Geo::Mirror, and therefore
+# Copyright (c) 2002, T.J. Mather, tjmather@tjmather.com, New York, NY, USA
+
+my (%lat, %lon);
+
+sub getlatlon {
+ my ($cc) = @_;
+ my ($lat_cc, $lon_cc) = ($lat{$cc}, $lon{$cc});
+
+ # Convert all the degrees to radians
+ $lat_cc *= PI/180
+ if defined $lat_cc;
+ $lon_cc *= PI/180
+ if defined $lon_cc;
+ return ($lat_cc, $lon_cc);
+}
+
+if (%newdistance && $hostcount > 1) {
+ while (<main::DATA>) {
+ my ($country, $lat, $lon) = split(':');
+
+ $lat{$country} = $lat;
+ $lon{$country} = $lon;
+ }
+ close main::DATA;
+
+ my $gi = Geo::IP->new(GEOIP_MEMORY_CACHE);
+
+ my ($lat_home, $lon_home) = getlatlon($home);
+
+ foreach (keys %newdistance) {
+ my $dist;
+ my $cc = lc $gi->country_code_by_name($_);
+ my ($lat_cc, $lon_cc) = getlatlon($cc)
+ if defined $cc;
+
+ # Find the deltas
+ my $delta_lat = $lat_cc - $lat_home;
+ my $delta_lon = $lon_cc - $lon_home;
+
+ # Find the Great Circle distance
+ my $temp = sin($delta_lat/2.0)**2 + cos($lat_home) * cos($lat_cc) * sin($delta_lon/2.0)**2;
+ $dist = atan2(sqrt($temp),sqrt(1-$temp));
+
+ $distance{$_} = [$dist, $expgood]
+ if defined $dist;
+ }
+
+ open RANKS, ">$rankfile";
+ while (my ($host, $val) = each %distance) {
+ printf RANKS "%s\t%.4f\t%d\n", $host, $val->[0], $val->[1]
+ if defined $val;
+ }
+ close RANKS;
+}
+
+$distance{FILE} = [$distgood, 0];
+$distance{UNKNOWN} = [$distbad, 0];
+
+foreach (sort {$distance{$mastersites{$a}}->[0] <=> $distance{$mastersites{$b}}->[0]} keys %mastersites) {
+ print $_, "\n";
+}
+
+__END__
+af:33:65
+al:41:20
+dz:28:3
+as:-14:-170
+ad:42:1
+ao:-12:18
+ai:18:-63
+aq:-90:0
+ag:17:-61
+ar:-34:-64
+am:40:45
+aw:12:-69
+au:-27:133
+at:47:13
+az:40:47
+bs:24:-76
+bh:26:50
+bd:24:90
+bb:13:-59
+by:53:28
+be:50:4
+bz:17:-88
+bj:9:2
+bm:32:-64
+bt:27:90
+bo:-17:-65
+ba:44:18
+bw:-22:24
+bv:-54:3
+br:-10:-55
+io:-6:71
+vg:18:-64
+bg:43:25
+bf:13:-2
+bi:-3:30
+kh:13:105
+cm:6:12
+ca:60:-95
+cv:16:-24
+ky:19:-80
+cf:7:21
+td:15:19
+cl:-30:-71
+cn:35:105
+cx:-10:105
+cc:-12:96
+co:4:-72
+km:-12:44
+cd:0:25
+cg:-1:15
+ck:-21:-159
+cr:10:-84
+ci:8:-5
+hr:45:15
+cu:21:-80
+cy:35:33
+cz:49:15
+dk:56:10
+dj:11:43
+dm:15:-61
+do:19:-70
+ec:-2:-77
+eg:27:30
+sv:13:-88
+gq:2:10
+er:15:39
+ee:59:26
+et:8:38
+fk:-51:-59
+fo:62:-7
+fj:-18:175
+fi:64:26
+fr:46:2
+gf:4:-53
+pf:-15:-140
+ga:-1:11
+gm:13:-16
+ge:42:43
+de:51:9
+eu:48:10
+gh:8:-2
+gi:36:-5
+gr:39:22
+gl:72:-40
+gd:12:-61
+gp:16:-61
+gu:13:144
+gt:15:-90
+gn:11:-10
+gw:12:-15
+gy:5:-59
+ht:19:-72
+hm:-53:72
+va:41:12
+hn:15:-86
+hk:22:114
+hu:47:20
+is:65:-18
+in:20:77
+id:-5:120
+ir:32:53
+iq:33:44
+ie:53:-8
+il:31:34
+it:42:12
+jm:18:-77
+sj:71:-8
+jp:36:138
+jo:31:36
+ke:1:38
+ki:1:173
+kp:40:127
+kr:37:127
+kw:29:45
+kg:41:75
+lv:57:25
+lb:33:35
+ls:-29:28
+lr:6:-9
+ly:25:17
+li:47:9
+lt:56:24
+lu:49:6
+mo:22:113
+mk:41:22
+mg:-20:47
+mw:-13:34
+my:2:112
+mv:3:73
+ml:17:-4
+mt:35:14
+mh:9:168
+mq:14:-61
+mr:20:-12
+mu:-20:57
+yt:-12:45
+mx:23:-102
+fm:6:158
+mc:43:7
+mn:46:105
+ms:16:-62
+ma:32:-5
+mz:-18:35
+na:-22:17
+nr:-0:166
+np:28:84
+nl:52:5
+an:12:-68
+nc:-21:165
+nz:-41:174
+ni:13:-85
+ne:16:8
+ng:10:8
+nu:-19:-169
+nf:-29:167
+mp:15:145
+no:62:10
+om:21:57
+pk:30:70
+pw:7:134
+pa:9:-80
+pg:-6:147
+py:-23:-58
+pe:-10:-76
+ph:13:122
+pn:-25:-130
+pl:52:20
+pt:39:-8
+pr:18:-66
+qa:25:51
+re:-21:55
+ro:46:25
+ru:60:100
+rw:-2:30
+sh:-15:-5
+kn:17:-62
+lc:13:-60
+pm:46:-56
+vc:13:-61
+ws:-13:-172
+sm:43:12
+st:1:7
+sa:25:45
+sn:14:-14
+sc:-4:55
+sl:8:-11
+sg:1:103
+sk:48:19
+si:46:15
+sb:-8:159
+so:10:49
+za:-29:24
+gs:-54:-37
+es:40:-4
+lk:7:81
+sd:15:30
+sr:4:-56
+sj:78:20
+sz:-26:31
+se:62:15
+ch:47:8
+sy:35:38
+tj:39:71
+tz:-6:35
+th:15:100
+tg:8:1
+tk:-9:-172
+to:-20:-175
+tt:11:-61
+tn:34:9
+tr:39:35
+tm:40:60
+tc:21:-71
+tv:-8:178
+ug:1:32
+ua:49:32
+ae:24:54
+gb:54:-2
+us:38:-97
+uy:-33:-56
+uz:41:64
+vu:-16:167
+ve:8:-66
+vn:16:106
+vi:18:-64
+wf:-13:-176
+eh:24:-13
+ye:15:48
+yu:44:21
+zm:-15:30
+zw:-20:30
+tw:23:121