Ubuntu 16.04: 依存パッケージを含めたdebパッケージをダウンロードする

依存パッケージを含めてdebパッケージをダウンロードする方法について記載します。

1 apt-rdepends

apt-rdependsは指定したパッケージから辿れるすべての依存パッケージを表示するツールです。

apt-rdependsをaptでインストールします。

$ sudo apt install -y apt-rdepends

binutilsの出力は以下のとおりです。" XXX:"の行を省いたものがbinutilsから辿れるすべての依存パッケージとなります。

$ apt-rdepends binutils 2> /dev/null
binutils
  Depends: libc6 (>= 2.14)
  Depends: zlib1g (>= 1:1.2.0)
libc6
  Depends: libgcc1
libgcc1
  Depends: gcc-6-base (= 6.0.1-0ubuntu1)
  Depends: libc6 (>= 2.14)
gcc-6-base
zlib1g
  Depends: libc6 (>= 2.14)

2 apt-rdependsにはvirtual packageが含まれる

virtual packageは選択可能な依存パッケージを抽象化するパッケージです。awkというvirtual packageの場合、awk-original, mawk, gawkがawk機能をprovideしており、そのいずれかがインストールされていれば依存を満たすことができます。

apt-rdependsを用いると依存パッケージとしてvirtual packageが表示される場合があります。virtual packageをダウンロードしようとするとエラーとなります。

$ apt download awk
E: Can't select candidate version from package awk as it has no candidate

そこでvirtual packageをprovideするパッケージを割り出す必要があります。apt installを実行することでprovideするパッケージの一覧を取得できます。

$ apt install -s awk
NOTE: This is only a simulation!
      apt-get needs root privileges for real execution.
      Keep also in mind that locking is deactivated,
      so don't depend on the relevance to the real current situation!
Reading package lists... Done
Building dependency tree
Reading state information... Done
Package awk is a virtual package provided by:
  original-awk:i386 2012-12-20-5
  original-awk 2012-12-20-5
  mawk:i386 1.3.3-17ubuntu2
  gawk:i386 1:4.1.3+dfsg-0.1
  mawk 1.3.3-17ubuntu2
  gawk 1:4.1.3+dfsg-0.1
You should explicitly select one to install.

E: Package 'awk' has no installation candidate

3 依存パッケージを含めたdebパッケージをダウンロードする

以下の手順でダウンロードします。

  • apt-rdependsで指定したパッケージの依存パッケージの一覧を取得する
  • 依存パッケージの一覧のうちvirtual packageはprovideするすべてのパッケージに置き換える
  • 取得したパッケージと依存パッケージの一覧のdebパッケージを取得する
#!/bin/sh

if [ $# -ne 1 ]; then
  prog=`basename ${0}`
  echo "usage: ${prog} <package>"
  exit 1
fi

TMP=`mktemp -t a.sh.XXXXXX`
trap "rm $TMP* 2>/dev/null" 0

check_virtual_package()
{
  apt show $1 2> /dev/null | grep "not a real package" > /dev/null
  return $?
}

get_provide_package()
{
  apt install -s $1 > ${TMP} 2> /dev/null

  local state=0
  local pkgs=""
  while read line; do
    if [ "${line}x" = "Package $1 is a virtual package provided by:x" ]; then
      state=1
    elif [ ${state} -eq 1 -a -n "${line}" ]; then
      pkg=`echo ${line} | awk '{ print $1 }'`
      echo ${pkg} | grep -v ':i386' > /dev/null && pkgs="${pkg} ${pkgs}"
    fi
  done < ${TMP}

  echo "${pkgs}"
}

get_depend_package()
{
  local pkgs=""
  local pkg=""

  for pkg in `apt-rdepends $1 2> /dev/null | grep -v "^  "`; do
    check_virtual_package ${pkg}
    if [ $? -eq 0 ]; then
      pkg=`get_provide_package ${pkg}`
    fi
    pkgs="${pkgs} ${pkg}"
  done

  echo "${pkgs}"
}

download_deb_package()
{
  local pkgs=""
  pkgs=`get_depend_package $1`
  apt download ${pkgs}
}

download_deb_package $1