From 07faf261cd67b545d61d521685306ffdd79f8887 Mon Sep 17 00:00:00 2001 From: Antonio Ospite Date: Mon, 12 Nov 2018 13:51:30 +0100 Subject: [PATCH 1/1] Initial import --- README.rst | 76 +++++++++++++++++++++++++++ deb-download-from-pool.sh | 128 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 204 insertions(+) create mode 100644 README.rst create mode 100755 deb-download-from-pool.sh diff --git a/README.rst b/README.rst new file mode 100644 index 0000000..ca42672 --- /dev/null +++ b/README.rst @@ -0,0 +1,76 @@ +`deb-download-from-pool.sh` is a script to download a group of related deb +packages built from the same "src" package directly from the "pool" directory +of a Debian mirror. + +It could be used to downgrade a group of packages when the latest version +introduces a regression, and previous versions are not available anymore for +the current distribution. + + +Examples +======== + +Get version from testing +------------------------ + +Sometimes a package gets updated in Debian unstable but it introduces +regressions, so reverting to the version in testing can be useful:: + + $ lsb_release --description + Description: Debian GNU/Linux unstable (sid) + $ rmadison -a $(dpkg-architecture -qDEB_BUILD_ARCH) libllvm7 + libllvm7 | 1:7-6 | testing | amd64 + libllvm7 | 1:7.0.1~+rc2-2 | unstable | amd64 + +However just specifying the version to `apt-get` is not enough if the old +version is not available anymore for unstable:: + + $ sudo apt-get install libllvm7=1:7-6 + Reading package lists... Done + Building dependency tree + Reading state information... Done + E: Version '1:7-6' for 'libllvm7' was not found + +The official mechanism to get packages from different suites is to use pinning_. + +.. _pinning: https://wiki.debian.org/AptPreferences#Pinning-1 + +Without pinning_ getting packages from different suites does not work:: + + $ sudo apt-get install -t testing libllvm7=1:7-6 + Reading package lists... Done + E: The value 'testing' is invalid for APT::Default-Release as such a release is not available in the sources + +With `deb-download-from-pool.sh` it is possible to get packages from *testing* +even if they are not directly available from *unstable* anymore:: + + $ ./deb-download-from-pool.sh libllvm7 7-6 + + +Get ancient version from snapshot.debian.org +-------------------------------------------- + +Debian provides snapshots of mirrors at http://snapshot.debian.org/ and using +these it is possible to download ancient package versions. + +Specifying a snapshot mirrors makes it possible to download very old packages:: + + MIRROR=http://snapshot.debian.org/archive/debian/20180904T211902Z/ \ + DEBUG_MIRROR=http://snapshot.debian.org/archive/debian-debug/20180904T210823Z/ \ + ./deb-download-from-pool.sh dash 0.5.8-2.10 + + +Known Bugs +========== + +If no version is passed the script will list available versions on the mirror, +but it will do so regardless of what binaries are actually available for the +current architecture of the host running the script. + +So it may list versions which could not be downloaded for the host. + +A more reliable way to list version could be something like the following:: + + rmadison -a $(dpkg-architecture -qDEB_BUILD_ARCH) package_name + +However this would not work with arbitrary mirrors, or snapshots. diff --git a/deb-download-from-pool.sh b/deb-download-from-pool.sh new file mode 100755 index 0000000..991b4b3 --- /dev/null +++ b/deb-download-from-pool.sh @@ -0,0 +1,128 @@ +#!/bin/sh +# +# deb-download-from-pool.sh - download specific packages from the pool +# +# Copyright (C) 2018 Antonio Ospite +# +# 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 . + +set -e + +MIRROR="${MIRROR:-https://deb.debian.org/debian}" +DEBUG_MIRROR="${DEBUG_MIRROR:-http://debug.mirrors.debian.org/debian-debug}" + +usage() { + PROG_NAME=$(basename "$0") + cat < [] + +Helper script to download specific packages from the pool directory of +a Debian mirror. + + +Options: + --all download all related packages even if currently + uninstalled + -h, --help display this usage message and exit + + +Notes: + +Some settings can be changed via environment variables: + SOURCE_PACKAGE + POOL_DIRECTORY + MIRROR + DEBUG_MIRROR +EOF +} + +download() { + dpkg --validate-pkgname -- "$1" || { usage 1>&2; exit 1; } + + PACKAGE="$1" + + if [ "x$SOURCE_PACKAGE" = "x" ]; + then + SOURCE_PACKAGE=$(apt-cache show "$PACKAGE" | grep Source | head -1 | cut -d ' ' -f 2) + if [ "x$SOURCE_PACKAGE" = "x" ]; + then + SOURCE_PACKAGE="$PACKAGE" + fi + fi + + if [ "x$POOL_DIRECTORY" = "x" ]; + then + POOL_DIRECTORY=$(apt-cache showsrc "$SOURCE_PACKAGE" | grep Directory | head -1 | cut -d ' ' -f 2) + fi + + POOL_URL="${MIRROR}/${POOL_DIRECTORY}" + + if [ "x$2" = "x" ]; + then + echo "Available versions, pass one of these as the second argument:" + wget -q "$POOL_URL" -O - | grep "${SOURCE_PACKAGE}_.*\\.dsc" | sed -e 's/^.*.*_\(.*\)\.dsc<\/a>.*$/\1/g' + exit $? + fi + + dpkg --validate-version -- "$2" || { usage 1>&2; exit 1; } + + VERSION="$2" + + ARCH=$(dpkg-architecture -qDEB_BUILD_ARCH) + PACKAGES=$(wget -q "$POOL_URL" -O - | \ + grep -e "${VERSION}[^_]*_${ARCH}" \ + -e "${VERSION}[^_]*_all" | \ + sed -e 's/^.* href="\([^"]*\)".*$/\1/g') + + for p in $PACKAGES; + do + PNAME=$(echo "$p" | cut -d '_' -f 1); + STATUS=$(grep-status -X \( -F Architecture "$ARCH" --or -F Architecture all \) --and -X -F Package "$PNAME" -n -s Status || true) + if [ "$STATUS" = "install ok installed" ] || [ "$DOWNLOAD_ALL" = "true" ]; + then + wget -nv "${POOL_URL}/${p}" + fi + done +} + + +[ $# -eq 0 ] && { usage 1>&2 && exit 1; } + +while [ $# -gt 0 ]; +do + case "$1" in + --) + shift + break + ;; + -h|--help) + usage + exit 0 + ;; + --all) + DOWNLOAD_ALL="true" + shift + ;; + -*) + echo "Error: Unknown option '${1}'" 1>&2 + shift + ;; + *) + break + ;; + esac +done + +download "$@" +MIRROR=$DEBUG_MIRROR download "$@" -- 2.1.4