diff options
Diffstat (limited to 'scripts')
-rw-r--r-- | scripts/Makefile.am | 4 | ||||
-rw-r--r-- | scripts/makepkg.sh.in | 282 | ||||
-rw-r--r-- | scripts/rankmirrors.py.in | 189 | ||||
-rw-r--r-- | scripts/rankmirrors.sh.in | 202 | ||||
-rw-r--r-- | scripts/repo-add.sh.in | 21 |
5 files changed, 368 insertions, 330 deletions
diff --git a/scripts/Makefile.am b/scripts/Makefile.am index 5d656534..330acb98 100644 --- a/scripts/Makefile.am +++ b/scripts/Makefile.am @@ -16,7 +16,7 @@ EXTRA_DIST = \ makepkg.sh.in \ pacman-optimize.sh.in \ pkgdelta.sh.in \ - rankmirrors.py.in \ + rankmirrors.sh.in \ repo-add.sh.in # Files that should be removed, but which Automake does not know. @@ -62,7 +62,7 @@ $(OURSCRIPTS): Makefile makepkg: $(srcdir)/makepkg.sh.in pacman-optimize: $(srcdir)/pacman-optimize.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-remove: $(srcdir)/repo-add.sh.in rm -f repo-remove diff --git a/scripts/makepkg.sh.in b/scripts/makepkg.sh.in index 3662228c..0ce5353f 100644 --- a/scripts/makepkg.sh.in +++ b/scripts/makepkg.sh.in @@ -27,7 +27,7 @@ # makepkg uses quite a few external programs during its execution. You # need to have at least the following installed for makepkg to function: -# awk, bsdtar (libarchive), bzip2, coreutils, fakeroot, find (findutils), +# bsdtar (libarchive), bzip2, coreutils, fakeroot, find (findutils), # getopt (util-linux), gettext, grep, gzip, openssl, sed # gettext initialization @@ -46,8 +46,9 @@ pkgdir="$startdir/pkg" packaging_options=('strip' 'docs' 'libtool' 'emptydirs' 'zipman' 'purge') other_options=('ccache' 'distcc' 'makeflags' 'force') -splitpkg_overrides=('pkgdesc' 'license' 'groups' 'depends' 'optdepends' 'provides' \ - 'conflicts' 'replaces' 'backup' 'options' 'install') +splitpkg_overrides=('pkgver' 'pkgrel' 'pkgdesc' 'arch' 'license' 'groups' \ + 'depends' 'optdepends' 'provides' 'conflicts' 'replaces' \ + 'backup' 'options' 'install' 'changelog') readonly -a packaging_options other_options splitpkg_overrides # Options @@ -175,6 +176,7 @@ clean_up() { ## # Signal Traps ## +set -E trap 'clean_up' 0 trap 'trap_exit "$(gettext "TERM signal caught. Exiting...")"' TERM HUP QUIT trap 'trap_exit "$(gettext "Aborted by user! Exiting...")"' INT @@ -187,15 +189,15 @@ trap 'trap_exit "$(gettext "An unknown error has occurred. Exiting...")"' ERR # extract the filename from a source entry get_filename() { # if a filename is specified, use it - local filename=$(echo $1 | sed 's|::.*||') + local filename="${1%%::*}" # if it is just an URL, we only keep the last component - echo "$filename" | sed 's|^.*://.*/||g' + echo "${filename##*/}" } # extract the URL from a source entry get_url() { # strip an eventual filename - echo $1 | sed 's|.*::||' + echo "${1#*::}" } ## @@ -245,11 +247,11 @@ check_buildenv() { # ? - not found ## in_opt_array() { - local needle=$(echo $1 | tr '[:upper:]' '[:lower:]'); shift + local needle="${1,,}"; shift local opt for opt in "$@"; do - opt=$(echo $opt | tr '[:upper:]' '[:lower:]') + opt="${opt,,}" if [ "$opt" = "$needle" ]; then echo 'y' # Enabled return @@ -281,14 +283,14 @@ in_array() { get_downloadclient() { # $1 = URL with valid protocol prefix local url=$1 - local proto=$(echo "$url" | sed 's|://.*||') + local proto="${url%%://*}" # loop through DOWNLOAD_AGENTS variable looking for protocol local i for i in "${DLAGENTS[@]}"; do - local handler=$(echo $i | sed 's|::.*||') + local handler="${i%%::*}" if [ "$proto" = "$handler" ]; then - agent=$(echo $i | sed 's|^.*::||') + agent="${i##*::}" break fi done @@ -301,7 +303,7 @@ get_downloadclient() { fi # ensure specified program is installed - local program="$(echo $agent | awk '{print $1 }')" + local program="${agent%% *}" if [ ! -x "$program" ]; then local baseprog=$(basename $program) error "$(gettext "The download program %s is not installed.")" "$baseprog" @@ -320,7 +322,7 @@ download_file() { # destination file local file=$3 # temporary download file, default to last component of the URL - local dlfile=$(echo "$url" | sed 's|^.*://.*/||g') + local dlfile="${url##*/}" # replace %o by the temporary dlfile if it exists if echo "$dlcmd" | grep -q "%o" ; then @@ -355,7 +357,7 @@ check_deps() { fi } -handledeps() { +handle_deps() { local R_DEPS_SATISFIED=0 local R_DEPS_MISSING=1 @@ -403,7 +405,7 @@ resolve_deps() { return $R_DEPS_SATISFIED fi - if handledeps $deplist; then + if handle_deps $deplist; then pkgdeps="$pkgdeps $deplist" # check deps again to make sure they were resolved deplist="$(check_deps $*)" @@ -430,7 +432,7 @@ remove_deps() { local dep depstrip deplist deplist="" for dep in $pkgdeps; do - depstrip=$(echo $dep | sed -e 's|=.*$||' -e 's|>.*$||' -e 's|<.*$||') + depstrip="${dep%%[<=>]*}" deplist="$deplist $depstrip" done @@ -512,7 +514,7 @@ generate_checksums() { local integ for integ in ${INTEGRITY_CHECK[@]}; do - integ="$(echo $integ | tr '[:upper:]' '[:lower:]')" + integ="${integ,,}" case "$integ" in md5|sha1|sha256|sha384|sha512) : ;; *) @@ -545,7 +547,8 @@ generate_checksums() { fi fi - local sum="$(openssl dgst -${integ} "$file" | awk '{print $NF}')" + local sum="$(openssl dgst -${integ} "$file")" + sum=${sum##* } [ $ct -gt 0 ] && echo -n "$indent" echo -n "'$sum'" ct=$(($ct+1)) @@ -590,8 +593,9 @@ check_checksums() { fi if [ $found -gt 0 ] ; then - local expectedsum="$(echo ${integrity_sums[$idx]} | tr '[A-F]' '[a-f]')" - local realsum="$(openssl dgst -${integ} "$file" | awk '{print $NF}')" + local expectedsum="${integrity_sums[$idx],,}" + local realsum="$(openssl dgst -${integ} "$file")" + realsum="${realsum##* }" if [ "$expectedsum" = "$realsum" ]; then echo "$(gettext "Passed")" >&2 else @@ -693,72 +697,23 @@ extract_sources() { fi } -run_build() { - # use distcc if it is requested (check buildenv and PKGBUILD opts) - if [ "$(check_buildenv distcc)" = "y" -a "$(check_option distcc)" != "n" ]; then - [ -d /usr/lib/distcc/bin ] && export PATH="/usr/lib/distcc/bin:$PATH" - export DISTCC_HOSTS - elif [ "$(check_option distcc)" = "n" ]; then - # if it is not wanted, clear the makeflags too - MAKEFLAGS="" - fi - - # use ccache if it is requested (check buildenv and PKGBUILD opts) - if [ "$(check_buildenv ccache)" = "y" -a "$(check_option ccache)" != "n" ]; then - [ -d /usr/lib/ccache/bin ] && export PATH="/usr/lib/ccache/bin:$PATH" - fi - - # clear user-specified makeflags if requested - if [ "$(check_option makeflags)" = "n" ]; then - MAKEFLAGS="" - fi - - msg "$(gettext "Starting build()...")" - cd "$srcdir" - - # ensure all necessary build variables are exported - export CFLAGS CXXFLAGS MAKEFLAGS LDFLAGS CHOST - # save our shell options so build() can't override what we need - local shellopts=$(shopt -p) - - local ret=0 - if [ "$LOGGING" -eq 1 ]; then - BUILDLOG="${startdir}/${pkgbase}-${pkgver}-${pkgrel}-${CARCH}-build.log" - if [ -f "$BUILDLOG" ]; then - local i=1 - while true; do - if [ -f "$BUILDLOG.$i" ]; then - i=$(($i +1)) - else - break - fi - done - mv "$BUILDLOG" "$BUILDLOG.$i" - fi - - build 2>&1 | tee "$BUILDLOG"; ret=${PIPESTATUS[0]} - else - build 2>&1 || ret=$? +error_function() { + if [ -p "$logpipe" ]; then + rm "$logpipe" fi - # reset our shell options - eval "$shellopts" - - if [ $ret -gt 0 ]; then - error "$(gettext "Build Failed.")" + # first exit all subshells, then print the error + if [ $BASH_SUBSHELL -eq 0 ]; then plain "$(gettext "Aborting...")" remove_deps - exit 2 # $E_BUILD_FAILED fi + exit 2 # $E_BUILD_FAILED } -run_package() { +run_function() { if [ -z "$1" ]; then - pkgfunc="package" - nameofpkg="$pkgname" - else - pkgfunc="package_$1" - nameofpkg="$1" + return 1 fi + pkgfunc="$1" # clear user-specified makeflags if requested if [ "$(check_option makeflags)" = "n" ]; then @@ -770,10 +725,12 @@ run_package() { # ensure all necessary build variables are exported export CFLAGS CXXFLAGS LDFLAGS MAKEFLAGS CHOST + # save our shell options so pkgfunc() can't override what we need + local shellopts=$(shopt -p) local ret=0 if [ "$LOGGING" -eq 1 ]; then - BUILDLOG="${startdir}/${nameofpkg}-${pkgver}-${pkgrel}-${CARCH}-package.log" + BUILDLOG="${startdir}/${pkgname}-${pkgver}-${pkgrel}-${CARCH}-$pkgfunc.log" if [ -f "$BUILDLOG" ]; then local i=1 while true; do @@ -792,20 +749,49 @@ run_package() { exec 3>&1 tee "$BUILDLOG" < "$logpipe" & exec 1>"$logpipe" 2>"$logpipe" - $pkgfunc 2>&1 || ret=$? + restoretrap=$(trap -p ERR) + trap 'error_function' ERR + $pkgfunc 2>&1 + eval $restoretrap sync exec 1>&3 2>&3 3>&- rm "$logpipe" else - $pkgfunc 2>&1 || ret=$? + restoretrap=$(trap -p ERR) + trap 'error_function' ERR + $pkgfunc 2>&1 + eval $restoretrap fi + # reset our shell options + eval "$shellopts" +} - if [ $ret -gt 0 ]; then - error "$(gettext "Packaging Failed.")" - plain "$(gettext "Aborting...")" - remove_deps - exit 2 # $E_BUILD_FAILED +run_build() { + # use distcc if it is requested (check buildenv and PKGBUILD opts) + if [ "$(check_buildenv distcc)" = "y" -a "$(check_option distcc)" != "n" ]; then + [ -d /usr/lib/distcc/bin ] && export PATH="/usr/lib/distcc/bin:$PATH" + export DISTCC_HOSTS + elif [ "$(check_option distcc)" = "n" ]; then + # if it is not wanted, clear the makeflags too + MAKEFLAGS="" fi + + # use ccache if it is requested (check buildenv and PKGBUILD opts) + if [ "$(check_buildenv ccache)" = "y" -a "$(check_option ccache)" != "n" ]; then + [ -d /usr/lib/ccache/bin ] && export PATH="/usr/lib/ccache/bin:$PATH" + fi + + run_function "build" +} + +run_package() { + if [ -z "$1" ]; then + pkgfunc="package" + else + pkgfunc="package_$1" + fi + + run_function "$pkgfunc" } tidy_install() { @@ -899,7 +885,8 @@ write_pkginfo() { else local packager="Unknown Packager" fi - local size=$(du -sk | awk '{print $1 * 1024}') + local size="$(du -sk)" + size="$(( ${size%%[^0-9]*} * 1024 ))" msg2 "$(gettext "Generating .PKGINFO file...")" echo "# Generated by makepkg $myver" >.PKGINFO @@ -915,9 +902,7 @@ write_pkginfo() { echo "builddate = $builddate" >>.PKGINFO echo "packager = $packager" >>.PKGINFO echo "size = $size" >>.PKGINFO - if [ -n "$CARCH" ]; then - echo "arch = $CARCH" >>.PKGINFO - fi + echo "arch = $PKGARCH" >>.PKGINFO if [ "$(check_option force)" = "y" ]; then echo "force = true" >> .PKGINFO fi @@ -966,6 +951,18 @@ write_pkginfo() { fi } +check_package() { + cd "$pkgdir" + + # check existence of backup files + local file + for file in "${backup[@]}"; do + if [ ! -f "$file" ]; then + warning "$(gettext "Invalid backup entry : %s")" "$file" + fi + done +} + create_package() { if [ ! -d "$pkgdir" ]; then error "$(gettext "Missing pkg/ directory.")" @@ -973,6 +970,8 @@ create_package() { exit 1 # $E_MISSING_PKGDIR fi + check_package + cd "$pkgdir" msg "$(gettext "Creating package...")" @@ -982,6 +981,12 @@ create_package() { nameofpkg="$1" fi + if [ "$arch" = "any" ]; then + PKGARCH="any" + else + PKGARCH=$CARCH + fi + write_pkginfo $nameofpkg local comp_files=".PKGINFO" @@ -994,9 +999,9 @@ create_package() { fi # do we have a changelog? - if [ -f "$startdir/ChangeLog" ]; then + if [ -n "$changelog" ]; then msg2 "$(gettext "Adding package changelog...")" - cp "$startdir/ChangeLog" .CHANGELOG + cp "$startdir/$changelog" .CHANGELOG comp_files="$comp_files .CHANGELOG" fi @@ -1010,7 +1015,7 @@ create_package() { *) warning "$(gettext "'%s' is not a valid archive extension.")" \ "$PKGEXT" ; EXT=$PKGEXT ;; esac - local pkg_file="$PKGDEST/${nameofpkg}-${pkgver}-${pkgrel}-${CARCH}${EXT}" + local pkg_file="$PKGDEST/${nameofpkg}-${pkgver}-${pkgrel}-${PKGARCH}${EXT}" local ret=0 @@ -1058,13 +1063,17 @@ create_srcpackage() { msg2 "$(gettext "Adding install script...")" ln -s "${startdir}/$install" "${srclinks}/${pkgbase}/" else - error "$(gettext "Install script %s not found.")" "$install" + error "$(gettext "Install scriptlet (%s) does not exist.")" "$install" fi fi - if [ -f ChangeLog ]; then - msg2 "$(gettext "Adding %s...")" "ChangeLog" - ln -s "${startdir}/ChangeLog" "${srclinks}/${pkgbase}" + if [ -n "$changelog" ]; then + if [ -f "$changelog" ]; then + msg2 "$(gettext "Adding package changelog...")" + ln -s "${startdir}/$changelog" "${srclinks}/${pkgbase}/" + else + error "$(gettext "Changelog file (%s) does not exist.")" "$changelog" + fi fi local netfile @@ -1112,7 +1121,11 @@ install_package() { local pkglist for pkg in ${pkgname[@]}; do - pkglist="${pkglist} $PKGDEST/${pkg}-${pkgver}-${pkgrel}-${CARCH}${PKGEXT}" + if [ -f $PKGDEST/${pkg}-${pkgver}-${pkgrel}-${CARCH}${PKGEXT} ]; then + pkglist="${pkglist} $PKGDEST/${pkg}-${pkgver}-${pkgrel}-${CARCH}${PKGEXT}" + else + pkglist="${pkglist} $PKGDEST/${pkg}-${pkgver}-${pkgrel}-any${PKGEXT}" + fi done local ret=0 @@ -1155,15 +1168,14 @@ check_sanity() { return 1 fi - if [ "$arch" = 'any' ]; then - CARCH='any' - fi - if ! in_array $CARCH ${arch[@]}; then - if [ "$IGNOREARCH" -eq 0 ]; then - error "$(gettext "%s is not available for the '%s' architecture.")" "$pkgbase" "$CARCH" - plain "$(gettext "Note that many packages may need a line added to their %s")" "$BUILDSCRIPT" - plain "$(gettext "such as arch=('%s').")" "$CARCH" - return 1 + if [ "$arch" != 'any' ]; then + if ! in_array $CARCH ${arch[@]}; then + if [ "$IGNOREARCH" -eq 0 ]; then + error "$(gettext "%s is not available for the '%s' architecture.")" "$pkgbase" "$CARCH" + plain "$(gettext "Note that many packages may need a line added to their %s")" "$BUILDSCRIPT" + plain "$(gettext "such as arch=('%s').")" "$CARCH" + return 1 + fi fi fi @@ -1175,11 +1187,32 @@ check_sanity() { fi done + local file + for file in "${backup[@]}"; do + if [ "${file:0:1}" = "/" ]; then + error "$(gettext "Invalid backup entry : %s")" "$file" + return 1 + fi + done + + local optdepend + for optdepend in "${optdepends[@]}"; do + pkg=${optdepend%%:*} + if [[ ! $pkg =~ ^[[:alnum:]\>\<\=\.\+\_\-]*$ ]]; then + error "$(gettext "Invalid syntax for optdepend : '%s'")" "$optdepend" + fi + done + if [ "$install" -a ! -f "$install" ]; then error "$(gettext "Install scriptlet (%s) does not exist.")" "$install" return 1 fi + if [ -n "$changelog" -a ! -f "$changelog" ]; then + error "$(gettext "Changelog file (%s) does not exist.")" "$changelog" + return 1 + fi + local valid_options=1 local opt known kopt for opt in ${options[@]}; do @@ -1414,31 +1447,30 @@ usage() { printf "$(gettext " -A, --ignorearch Ignore incomplete arch field in %s")\n" "$BUILDSCRIPT" echo "$(gettext " -c, --clean Clean up work files after build")" echo "$(gettext " -C, --cleancache Clean up source files from the cache")" - printf "$(gettext " --config <config> Use an alternate config file (instead of '%s')")\n" "$confdir/makepkg.conf" echo "$(gettext " -d, --nodeps Skip all dependency checks")" echo "$(gettext " -e, --noextract Do not extract source files (use existing src/ dir)")" echo "$(gettext " -f, --force Overwrite existing package")" echo "$(gettext " -g, --geninteg Generate integrity checks for source files")" - echo "$(gettext " --skipinteg Do not fail when integrity checks are missing")" echo "$(gettext " -h, --help This help")" echo "$(gettext " -i, --install Install package after successful build")" echo "$(gettext " -L, --log Log package build process")" echo "$(gettext " -m, --nocolor Disable colorized output messages")" echo "$(gettext " -o, --nobuild Download and extract files only")" - printf "$(gettext " -p <buildscript> Use an alternate build script (instead of '%s')")\n" "$BUILDSCRIPT" + printf "$(gettext " -p <file> Use an alternate build script (instead of '%s')")\n" "$BUILDSCRIPT" echo "$(gettext " -r, --rmdeps Remove installed dependencies after a successful build")" - # fix flyspray feature request #2978 echo "$(gettext " -R, --repackage Repackage contents of the package without rebuilding")" echo "$(gettext " -s, --syncdeps Install missing dependencies with pacman")" - echo "$(gettext " --allsource Generate a source-only tarball including downloaded sources")" - echo "$(gettext " --asroot Allow makepkg to run as root user")" - echo "$(gettext " --holdver Prevent automatic version bumping for development PKGBUILDs")" - echo "$(gettext " --source Generate a source-only tarball without downloaded sources")" + echo "$(gettext " --allsource Generate a source-only tarball including downloaded sources")" + echo "$(gettext " --asroot Allow makepkg to run as root user")" + printf "$(gettext " --config <file> Use an alternate config file (instead of '%s')")\n" "$confdir/makepkg.conf" + echo "$(gettext " --holdver Prevent automatic version bumping for development PKGBUILDs")" + echo "$(gettext " --skipinteg Do not fail when integrity checks are missing")" + echo "$(gettext " --source Generate a source-only tarball without downloaded sources")" echo echo "$(gettext "These options can be passed to pacman:")" echo - echo "$(gettext " --noconfirm Do not ask for confirmation when resolving dependencies")" - echo "$(gettext " --noprogressbar Do not show a progress bar when downloading files")" + echo "$(gettext " --noconfirm Do not ask for confirmation when resolving dependencies")" + echo "$(gettext " --noprogressbar Do not show a progress bar when downloading files")" echo printf "$(gettext "If -p is not specified, makepkg will look for '%s'")\n" "$BUILDSCRIPT" echo @@ -1567,7 +1599,7 @@ if [ "$CLEANCACHE" -eq 1 ]; then echo -n "$(gettext " Are you sure you wish to do this? ")" echo -n "$(gettext "[Y/n]")" read answer - answer=$(echo $answer | tr '[:lower:]' '[:upper:]') + answer="${answer^^}" if [ "$answer" = "$(gettext "YES")" -o "$answer" = "$(gettext "Y")" ]; then rm "$SRCDEST"/* if [ $? -ne 0 ]; then @@ -1634,7 +1666,7 @@ if [ "$ASROOT" -eq 0 \ fi unset pkgname pkgbase pkgver pkgrel pkgdesc url license groups provides -unset md5sums replaces depends conflicts backup source install build +unset md5sums replaces depends conflicts backup source install changelog build unset makedepends optdepends options noextract BUILDFILE=${BUILDFILE:-$BUILDSCRIPT} @@ -1689,8 +1721,9 @@ fi pkgbase=${pkgbase:-${pkgname[0]}} if [ "$SPLITPKG" -eq 0 ]; then - if [ -f "$PKGDEST/${pkgname}-${pkgver}-${pkgrel}-${CARCH}${PKGEXT}" \ - -a "$FORCE" -eq 0 -a "$SOURCEONLY" -eq 0 -a "$NOBUILD" -eq 0 ]; then + if [ \( -f "$PKGDEST/${pkgname}-${pkgver}-${pkgrel}-${CARCH}${PKGEXT}" \ + -f "$PKGDEST/${pkgname}-${pkgver}-${pkgrel}-any${PKGEXT}" \) \ + -a "$FORCE" -eq 0 -a "$SOURCEONLY" -eq 0 -a "$NOBUILD" -eq 0 ]; then if [ "$INSTALL" -eq 1 ]; then warning "$(gettext "A package has already been built, installing existing package...")" install_package @@ -1704,7 +1737,8 @@ else allpkgbuilt=1 somepkgbuilt=0 for pkg in ${pkgname[@]}; do - if [ -f "$PKGDEST/${pkg}-${pkgver}-${pkgrel}-${CARCH}${PKGEXT}" ]; then + if [ \( -f "$PKGDEST/${pkg}-${pkgver}-${pkgrel}-${CARCH}${PKGEXT}" \ + -f "$PKGDEST/${pkg}-${pkgver}-${pkgrel}-any${PKGEXT}" \) ]; then somepkgbuilt=1 else allpkgbuilt=0 @@ -1759,7 +1793,7 @@ if [ "$INFAKEROOT" -eq 1 ]; then exit 0 # $E_OK fi -msg "$(gettext "Making package: %s")" "$pkgbase $pkgver-$pkgrel $CARCH ($(date))" +msg "$(gettext "Making package: %s")" "$pkgbase $pkgver-$pkgrel ($(date))" # if we are creating a source-only package, go no further if [ "$SOURCEONLY" -ne 0 ]; then @@ -1883,7 +1917,7 @@ else fi fi -msg "$(gettext "Finished making: %s")" "$pkgbase $pkgver-$pkgrel $CARCH ($(date))" +msg "$(gettext "Finished making: %s")" "$pkgbase $pkgver-$pkgrel ($(date))" install_package diff --git a/scripts/rankmirrors.py.in b/scripts/rankmirrors.py.in deleted file mode 100644 index 4b253b67..00000000 --- a/scripts/rankmirrors.py.in +++ /dev/null @@ -1,189 +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') - - # 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: diff --git a/scripts/rankmirrors.sh.in b/scripts/rankmirrors.sh.in new file mode 100644 index 00000000..015b39a7 --- /dev/null +++ b/scripts/rankmirrors.sh.in @@ -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: diff --git a/scripts/repo-add.sh.in b/scripts/repo-add.sh.in index c8380c4e..3f00441a 100644 --- a/scripts/repo-add.sh.in +++ b/scripts/repo-add.sh.in @@ -136,7 +136,8 @@ db_write_delta() echo -e "%DELTAS%" >>$deltas fi # get md5sum and compressed size of package - md5sum="$(openssl dgst -md5 "$deltafile" | awk '{print $NF}')" + md5sum="$(openssl dgst -md5 "$deltafile")" + md5sum="${md5sum##* }" csize=$(@SIZECMD@ "$deltafile") oldfile=$(xdelta3 printhdr $deltafile | grep "XDELTA filename (source)" | sed 's/.*: *//') @@ -213,7 +214,8 @@ db_write_entry() IFS=$OLDIFS # get md5sum and compressed size of package - md5sum="$(openssl dgst -md5 "$pkgfile" | awk '{print $NF}')" + md5sum="$(openssl dgst -md5 "$pkgfile")" + md5sum="${md5sum##* }" csize=$(@SIZECMD@ "$pkgfile") # ensure $pkgname and $pkgver variables were found @@ -357,7 +359,7 @@ add() fi pkgfile=$1 - if ! bsdtar -tqf "$pkgfile" .PKGINFO 2>&1 >/dev/null; then + if ! bsdtar -tqf "$pkgfile" .PKGINFO >/dev/null 2>&1; then error "$(gettext "'%s' is not a package file, skipping")" "$pkgfile" return 1 fi @@ -423,12 +425,6 @@ case "$1" in -V|--version) version; exit 0;; esac -# check for correct number of args -if [ $# -lt 2 ]; then - usage - exit 1 -fi - # figure out what program we are cmd="$(basename $0)" if [ "$cmd" != "repo-add" -a "$cmd" != "repo-remove" ]; then @@ -450,12 +446,6 @@ success=0 for arg in "$@"; do case "$arg" in -q|--quiet) QUIET=1;; - - -f|--force) - warning "$(gettext "the -f and --force options are no longer recognized")" - msg2 "$(gettext "use options=(force) in the PKGBUILD instead")" - ;; - *) if [ -z "$REPO_DB_FILE" ]; then REPO_DB_FILE="$arg" @@ -499,6 +489,7 @@ if [ $success -eq 1 ]; then [ -f "$tmpdir/$filename" ] && mv "$tmpdir/$filename" "$REPO_DB_FILE" else msg "$(gettext "No packages modified, nothing to do.")" + exit 1 fi exit 0 |