Ubuntu 16.04: virtual package

This article will describe about virtual package of deb package.

1 What is virtual package

There are packages which provides awk feature like awk-original, mawk and gawk. There have different licences, implements and detail of features. And user can choise one from these.

The package depending awk feature will cause a problem. If the package depends gawk while a user choice mawk, gawk will conflict mawk.

Using virtual package which names awk resolves this conflict problem. The package which depends awk feature will depend virtual package which names awk. And awk-original, mawk and gawk will provide awk feature.

2 Check virtual package

The apt show with virtual package will output "not a real package".

$ apt show awk | grep "not a real package"
State: not a real package (virtual)

3 Get provide package

The apt install with virtual package will output "Package xxx is a virtual package provided by:" and list of provide package. The -s option is useful for checking provide package.

$ apt install awk -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

4 Convert virtual package to provide package

The following script will convert virtual package to provide package.

#!/bin/sh

if [ $# -ne 1 ]; then
  prog=`basename ${0}`
  echo "usage: ${prog} <virtual 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 $?
}

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

  state=0
  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}
}

check_virtual_package $1
if [ $? -eq 0 ]; then
  print_provide_package $1
else
  echo $1
fi