aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pym/_emerge/Package.py32
-rw-r--r--pym/portage/dbapi/__init__.py5
-rw-r--r--pym/portage/package/ebuild/config.py6
-rw-r--r--pym/portage/tests/dbapi/test_fakedbapi.py20
4 files changed, 63 insertions, 0 deletions
diff --git a/pym/_emerge/Package.py b/pym/_emerge/Package.py
index 2c1a116ea..cebfd8281 100644
--- a/pym/_emerge/Package.py
+++ b/pym/_emerge/Package.py
@@ -3,6 +3,7 @@
from __future__ import unicode_literals
+import functools
import sys
from itertools import chain
import warnings
@@ -82,6 +83,10 @@ class Package(Task):
if eapi_attrs.iuse_effective:
implicit_match = self.root_config.settings._iuse_effective_match
+ if self.built:
+ implicit_match = functools.partial(
+ self._built_iuse_effective_match,
+ implicit_match, frozenset(self._metadata['USE'].split()))
else:
implicit_match = self.root_config.settings._iuse_implicit_match
usealiases = self.root_config.settings._use_manager.getUseAliases(self)
@@ -109,6 +114,33 @@ class Package(Task):
type_name=self.type_name)
self._hash_value = hash(self._hash_key)
+ @staticmethod
+ def _built_iuse_effective_match(prof_effective_match, built_use, flag):
+ """
+ For built packages, it is desirable for the built USE setting to be
+ independent of the profile's current IUSE_IMPLICIT state, since the
+ profile's IUSE_IMPLICT setting may have diverged. Therefore, any
+ member of the built USE setting is considered to be a valid member of
+ IUSE_EFFECTIVE. Note that the binary package may be remote, so it's
+ only possible to rely on metadata that is available in the remote
+ Packages file, and the IUSE_IMPLICIT header in the Packages file is
+ vulnerable to mutation (see bug 640318).
+
+ This function is only used for EAPIs that support IUSE_EFFECTIVE,
+ since built USE settings for earlier EAPIs may contain a large
+ number of irrelevant flags.
+
+ @param prof_effective_match: function to match IUSE_EFFECTIVE
+ values for the current profile
+ @type prof_effective_match: callable
+ @param built_use: built USE setting
+ @type built_use: frozenset
+ @return: True if flag is a valid USE value which may
+ be specified in USE dependencies, False otherwise.
+ @rtype: bool
+ """
+ return flag in built_use or prof_effective_match(flag)
+
@property
def eapi(self):
return self._metadata["EAPI"]
diff --git a/pym/portage/dbapi/__init__.py b/pym/portage/dbapi/__init__.py
index 95053840d..2574b63df 100644
--- a/pym/portage/dbapi/__init__.py
+++ b/pym/portage/dbapi/__init__.py
@@ -5,6 +5,7 @@ from __future__ import unicode_literals
__all__ = ["dbapi"]
+import functools
import re
import portage
@@ -219,6 +220,10 @@ class dbapi(object):
eapi_attrs = _get_eapi_attrs(metadata["EAPI"])
if eapi_attrs.iuse_effective:
iuse_implicit_match = self.settings._iuse_effective_match
+ if not self._use_mutable:
+ iuse_implicit_match = functools.partial(
+ Package._built_iuse_effective_match,
+ iuse_implicit_match, frozenset(metadata["USE"].split()))
else:
iuse_implicit_match = self.settings._iuse_implicit_match
usealiases = self.settings._use_manager.getUseAliases(pkg)
diff --git a/pym/portage/package/ebuild/config.py b/pym/portage/package/ebuild/config.py
index cd2b009aa..d0225a311 100644
--- a/pym/portage/package/ebuild/config.py
+++ b/pym/portage/package/ebuild/config.py
@@ -1693,6 +1693,12 @@ class config(object):
iuse_implicit_match = self._iuse_effective_match
portage_iuse = set(self._iuse_effective)
portage_iuse.update(explicit_iuse)
+ if built_use is not None:
+ # When the binary package was built, the profile may have
+ # had different IUSE_IMPLICIT settings, so any member of
+ # the built USE setting is considered to be a member of
+ # IUSE_EFFECTIVE (see bug 640318).
+ portage_iuse.update(built_use)
self.configdict["pkg"]["IUSE_EFFECTIVE"] = \
" ".join(sorted(portage_iuse))
else:
diff --git a/pym/portage/tests/dbapi/test_fakedbapi.py b/pym/portage/tests/dbapi/test_fakedbapi.py
index e4f5dd771..19ea9cd00 100644
--- a/pym/portage/tests/dbapi/test_fakedbapi.py
+++ b/pym/portage/tests/dbapi/test_fakedbapi.py
@@ -14,6 +14,20 @@ class TestFakedbapi(TestCase):
def testFakedbapi(self):
packages = (
+ ("app-misc/foo-1", {
+ "EAPI" : "2", # does not support IUSE_EFFECTIVE
+ "IUSE" : "",
+ "repository" : "gentoo",
+ "SLOT" : "1",
+ "USE" : "missing-iuse",
+ }),
+ ("app-misc/foo-2", {
+ "EAPI" : "5", # supports IUSE_EFFECTIVE
+ "IUSE" : "",
+ "repository" : "gentoo",
+ "SLOT" : "2",
+ "USE" : "missing-iuse",
+ }),
("sys-apps/portage-2.1.10", {
"EAPI" : "2",
"IUSE" : "ipc doc",
@@ -29,6 +43,12 @@ class TestFakedbapi(TestCase):
)
match_tests = (
+ # The missing-iuse match is only intended to work for binary
+ # packages with EAPIs that support IUSE_EFFECTIVE (bug 640318).
+ ("app-misc/foo[missing-iuse]", ["app-misc/foo-2"]),
+ ("app-misc/foo[-missing-iuse]", []),
+ ("app-misc/foo", ["app-misc/foo-1", "app-misc/foo-2"]),
+
("sys-apps/portage:0[ipc]", ["sys-apps/portage-2.1.10"]),
("sys-apps/portage:0[-ipc]", []),
("sys-apps/portage:0[doc]", []),