You're right btw that it's a dpkg bug, but it's a bit more subtle. The cleanup that dpkg performs after installation is meant to preserve the hold state for non-installed packages. This is handled by the pkg_is_informative function, which classifies everything with "pkg->want != PKG_WANT_UNKNOWN" as informative, so would actually preserve hold for non-installed packages. However, pkg_parse_verify contains logic to fix up state left by older dpkg versions, without taking into account that this also includes valid state by current dpkg versions:
/* XXX: Mark not-installed leftover packages for automatic removal on
* next database dump. This code can be removed after dpkg 1.16.x, when
* there's guarantee that no leftover is found on the status file on
* major distributions. */
if (!(ps->flags & pdb_recordavailable) &&
pkg->status == PKG_STAT_NOTINSTALLED &&
pkg->eflag == PKG_EFLAG_OK &&
(pkg->want == PKG_WANT_PURGE ||
pkg->want == PKG_WANT_DEINSTALL ||
pkg->want == PKG_WANT_HOLD)) {
pkg_set_want(pkg, PKG_WANT_UNKNOWN);
}
We are now at dpkg 1.20.x, well after 1.16.x. If this block of code is removed (or at least the pkg->want == PKG_WANT_HOLD condition), direct installation by dpkg works as expected, and presumably installation using apt will work as expected as well.
You're right btw that it's a dpkg bug, but it's a bit more subtle. The cleanup that dpkg performs after installation is meant to preserve the hold state for non-installed packages. This is handled by the pkg_is_informative function, which classifies everything with "pkg->want != PKG_WANT_UNKNOWN" as informative, so would actually preserve hold for non-installed packages. However, pkg_parse_verify contains logic to fix up state left by older dpkg versions, without taking into account that this also includes valid state by current dpkg versions:
/* XXX: Mark not-installed leftover packages for automatic removal on able) && NOTINSTALLED && set_want( pkg, PKG_WANT_UNKNOWN);
* next database dump. This code can be removed after dpkg 1.16.x, when
* there's guarantee that no leftover is found on the status file on
* major distributions. */
if (!(ps->flags & pdb_recordavail
pkg->status == PKG_STAT_
pkg->eflag == PKG_EFLAG_OK &&
(pkg->want == PKG_WANT_PURGE ||
pkg->want == PKG_WANT_DEINSTALL ||
pkg->want == PKG_WANT_HOLD)) {
pkg_
}
We are now at dpkg 1.20.x, well after 1.16.x. If this block of code is removed (or at least the pkg->want == PKG_WANT_HOLD condition), direct installation by dpkg works as expected, and presumably installation using apt will work as expected as well.