apt: fix virtual package install version detection (#76781)

* apt: fix virtual package install version detection

Change 4a62c4e3e4 introduced version
matching in installation.

The problem stems from

 if version_installable or version:
     pkg_list.append("'%s=%s'" % (name, version_installable or version))

When the package is a virtual-package, package_status() is returning
the "version_installable" of the package *satisfying* the
virtual-package; but then this is trying to install the
virtual-package with this version pin.

For example, "yaml-mode" is a virtual package satisifed by
"elpa-yaml-mode" (currently 0.0.14-1) and trying to install it fails
with

 $ usr/bin/apt-get -y ... install 'yaml-mode=0.0.14-1'
 ... failed: E: Version '0.0.14-1' for 'yaml-mode' was not found ...

In the case of a virtual-package with nothing installed to satisfy it,
we should just return blank values to allow apt-get to do it's thing.

The tests are updated to install and remove this package.

Fixes: #76779
pull/77916/head
Ian Wienand 4 years ago committed by GitHub
parent 6fbc8bd2bc
commit e4c0bbf885
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,2 @@
bugfixes:
- apt module now correctly handles virtual packages.

@ -510,17 +510,20 @@ def package_status(m, pkgname, version_cmp, version, default_release, cache, sta
try: try:
provided_packages = cache.get_providing_packages(pkgname) provided_packages = cache.get_providing_packages(pkgname)
if provided_packages: if provided_packages:
is_installed = False # When this is a virtual package satisfied by only
version_installable = None # one installed package, return the status of the target
version_ok = False # package to avoid requesting re-install
# when virtual package providing only one package, look up status of target package
if cache.is_virtual_package(pkgname) and len(provided_packages) == 1: if cache.is_virtual_package(pkgname) and len(provided_packages) == 1:
package = provided_packages[0] package = provided_packages[0]
installed, version_ok, version_installable, has_files = \ installed, installed_version, version_installable, has_files = \
package_status(m, package.name, version_cmp, version, default_release, cache, state='install') package_status(m, package.name, version_cmp, version, default_release, cache, state='install')
if installed: if installed:
is_installed = True return installed, installed_version, version_installable, has_files
return is_installed, version_ok, version_installable, False
# Otherwise return nothing so apt will sort out
# what package to satisfy this with
return False, False, None, False
m.fail_json(msg="No package matching '%s' is available" % pkgname) m.fail_json(msg="No package matching '%s' is available" % pkgname)
except AttributeError: except AttributeError:
# python-apt version too old to detect virtual packages # python-apt version too old to detect virtual packages

@ -507,3 +507,25 @@
that: that:
- "allow_change_held_packages_no_update is not changed" - "allow_change_held_packages_no_update is not changed"
- "allow_change_held_packages_hello_version.stdout == allow_change_held_packages_hello_version_again.stdout" - "allow_change_held_packages_hello_version.stdout == allow_change_held_packages_hello_version_again.stdout"
# Virtual package
- name: Install a virtual package
apt:
package:
- emacs-nox
- yaml-mode # <- the virtual package
state: latest
register: install_virtual_package_result
- name: Check the virtual package install result
assert:
that:
- install_virtual_package_result is changed
- name: Clean up virtual-package install
apt:
package:
- emacs-nox
- elpa-yaml-mode
state: absent
purge: yes

Loading…
Cancel
Save