#!/bin/bash
#
# This script is for automating the download of a built Koji package
# without having to type in each package, instead we take the build
# url, compute the package list, apply the name and arch filter, and
# download only the files you want. We could do this with `koji
# download-build` but it refuses to download just one package and
# wants to download the entire build.
#
# Input: $1: URL of build or task in Koji.
# -a: List of arches.
# -p: List of packages.
# Output: Specific srpms and rpms built for the given task/build.
#
set -e
# Enable for debugging:
# set -x
koji_taskurl=http://koji.fedoraproject.org/koji
koji_buildurl=http://koji.fedoraproject.org/koji
koji_packages=https://kojipkgs.fedoraproject.org
buildline="buildArch"
# Remove '-q' to get more detail for debugging.
#wgetopts="--no-check-certificate -q"
wgetopts="--no-check-certificate --retry-connrefused --continue"
if [ $# -lt 1 ]; then
echo "$0: <Build or task URL in Koji> [-p <Package list>] [-a <Arches list>]"
exit 1
fi
url="$1"
shift
# Read options
opts=`getopt -o p:a: --long packages:arches: -n $0 -- "$@"`
eval set -- "$opts"
# Extract options and their arguments.
arg_packages=""
arg_arches=""
packages=""
arches=""
while true ; do
case "$1" in
-p|--packages)
arg_packages=$2; shift 2 ;;
-a|--arches)
arg_arches=$2; shift 2 ;;
--) shift ; break ;;
*) echo "Internal error!" ; exit 1 ;;
esac
done
if [ "$arg_packages" ]; then
packages=`echo $arg_packages | sed -e 's/,/-[[:digit:]] /g' -e 's/$/-[[:digit:]]/g'`
fi
if [ "$arg_arches" ]; then
arches=`echo $arg_arches | sed -e 's/,/\. \./g' -e 's/^/\./g' -e 's/$/\./g'`
fi
tempfiles=()
cleanup() {
rm -f "${tempfiles[@]}"
}
trap cleanup 0
error () {
local parent_lineno="$1"
local message="$2"
local code="${3:-1}"
if [[ -n "$message" ]]; then
echo "Error on line ${parent_lineno}: ${message} (${code})"
else
echo "Error on line ${parent_lineno} (${code})"
fi
exit "${code}"
}
trap 'error ${LINENO}' ERR
# Setup some temp files.
buildinfo=$(mktemp)
chmod u+rw $buildinfo
tempfiles+=("$buildinfo")
archinfo=$(mktemp)
chmod u+rw $archinfo
tempfiles+=("$archinfo")
pageinfo=$(mktemp)
chmod u+rw $pageinfo
tempfiles+=("$pageinfo")
rpminfo=$(mktemp)
chmod u+rw $rpminfo
tempfiles+=("$rpminfo")
# Fetch the build information.
echo "Downloading build information..."
if true; then
echo "Detected Koji..."
buildurl=$koji_buildurl
taskurl=$koji_taskurl
packageurl=$koji_packages
fi
# All rpm downloads go through fetch_rpm and we throttle
# it slighlty to avoid getting kicked by the server.
function fetch_rpm {
local wgetopts url ret
wgetopts="$1"
url="$2"
ret=1
while [ $ret -ne 0 ]; do
ret=$(wget $wgetopts $url | echo $?)
sleep 1
done
}
# Download the globally selected arches and packages
# from RPMINFO.
function fetch_rpms {
local rpminfo
local line arch package
rpminfo="$1"
# Downloading specific packages for a given arch?
# - The most restrictive query.
if [ "$arches" ] && [ "$packages" ]; then
while read line
do
for arch in $arches; do
for package in $packages; do
if echo $line | grep -q -F $arch && echo $line | grep -q $package; then
echo "Downloading $line"
fetch_rpm "$wgetopts" "$line"
fi
done
done
done < $rpminfo
fi
# Downloading a specific package only?
# - Will download that package for all arches.
if [ -z "$arches" ] && [ "$packages" ]; then
while read line
do
for package in $packages; do
if echo $line | grep -q $package; then
echo "Downloading $line"
fetch_rpm "$wgetopts" "$line"
fi
done
done < $rpminfo
fi
# Downloading all packages for a given arch?
if [ "$arches" ] && [ -z "$packages" ]; then
while read line
do
for arch in $arches; do
if echo $line | grep -q -F $arch; then
echo "Downloading $line"
fetch_rpm "$wgetopts" "$line"
fi
done
done < $rpminfo
fi
# Downloading all rpms for all arches?
if [ -z "$arches" ] && [ -z "$packages" ]; then
while read line
do
echo "Downloading $line"
fetch_rpm "$wgetopts" "$line"
done < $rpminfo
fi
}
# Next we need to determine if the URL is for a TASK or a BUILD.
# A TASK has sub-builds that we need to walk.
# A BUILD has an architecture list we need to walk.
wget $wgetopts --output-document=$buildinfo $url
grep "$buildline" $buildinfo | sed -e 's,^.*href=",,g' -e 's,".*$,,g' > $archinfo
count=$(cat $archinfo | wc -l)
if [ $count -lt 1 ]; then
# It's a BUILD.
# Get the full list of all RPMs.
grep "$packageurl" $buildinfo | grep '\.rpm' | sed -e 's,^.*href=",,g' -e 's,".*$,,g' > $rpminfo
rpmcount=$(wc -l $rpminfo | sed -e 's, .*$,,g')
if [ $rpmcount -eq 0 ]; then
echo "No RPMs detected!"
exit 1
fi
fetch_rpms "$rpminfo"
else
# It's a TASK.
# For each sub-arch build:
count=0
while read line
do
# Download the descendent build info page...
echo "Downloading target $count information..."
truncate -s 0 $pageinfo
wget $wgetopts --output-document=$pageinfo $taskurl/$line
grep "$packageurl" $pageinfo | grep ".*rpm" | sed -e 's,^.*href=",,g' -e 's,".*$,,g' > $rpminfo
# Then download the rpms.
fetch_rpms "$rpminfo"
count=$((count+1))
done < $archinfo
fi
# Cleanup, leaving the downloaded rpms.
echo "Done."
exit 0