Initial import master
authorAntonio Ospite <ao2@ao2.it>
Mon, 12 Nov 2018 12:51:30 +0000 (13:51 +0100)
committerAntonio Ospite <ao2@ao2.it>
Mon, 12 Nov 2018 14:17:20 +0000 (15:17 +0100)
README.rst [new file with mode: 0644]
deb-download-from-pool.sh [new file with mode: 0755]

diff --git a/README.rst b/README.rst
new file mode 100644 (file)
index 0000000..ca42672
--- /dev/null
@@ -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 (executable)
index 0000000..991b4b3
--- /dev/null
@@ -0,0 +1,128 @@
+#!/bin/sh
+#
+# deb-download-from-pool.sh - download specific packages from the pool
+#
+# Copyright (C) 2018  Antonio Ospite <ao2@ao2.it>
+#
+# 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/>.
+
+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 <<EOF
+usage: $PROG_NAME [--all|-h|--help] <package> [<version>]
+
+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/^.*<a .*>.*_\(.*\)\.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 "$@"