Add support for conditionals inside USE dependencies. This is useful
authorZac Medico <zmedico@gentoo.org>
Sun, 25 May 2008 01:44:03 +0000 (01:44 -0000)
committerZac Medico <zmedico@gentoo.org>
Sun, 25 May 2008 01:44:03 +0000 (01:44 -0000)
for cases in which the package satisfying a dependency should have
identical or opposite flag state relative to the parent package.

Conditionals are evaluated as follows:

   parent state   conditional   result
     x              [x?]          [x]
    -x              [x?]         [-x]
     x             [-x?]         [-x]
    -x             [-x?]          [x]

svn path=/main/trunk/; revision=10396

pym/portage/__init__.py
pym/portage/dep.py

index dfe7ddeb09beba1cdc1a8e611a09900d2904ba9d..80c24ff310b8b65431336f6c75d48fcf53d129ca 100644 (file)
@@ -5403,6 +5403,7 @@ def _expand_new_virtuals(mysplit, edebug, mydbapi, mysettings, myroot="/",
        if kwargs["use_binaries"]:
                portdb = trees[myroot]["bintree"].dbapi
        myvirtuals = mysettings.getvirtuals()
+       myuse = kwargs["myuse"]
        for x in mysplit:
                if x == "||":
                        newsplit.append(x)
@@ -5411,10 +5412,23 @@ def _expand_new_virtuals(mysplit, edebug, mydbapi, mysettings, myroot="/",
                        newsplit.append(_expand_new_virtuals(x, edebug, mydbapi,
                                mysettings, myroot=myroot, trees=trees, **kwargs))
                        continue
-               if portage.dep._dep_check_strict and \
-                       not isvalidatom(x, allow_blockers=True):
-                       raise portage.exception.ParseError(
-                               "invalid atom: '%s'" % x)
+
+               if not isinstance(x, portage.dep.Atom):
+                       try:
+                               x = portage.dep.Atom(x)
+                       except portage.exception.InvalidAtom:
+                               if portage.dep._dep_check_strict:
+                                       raise portage.exception.ParseError(
+                                               "invalid atom: '%s'" % x)
+
+               if isinstance(x, portage.dep.Atom) and x.use:
+                       if x.use.conditional:
+                               evaluated_atom = portage.dep.remove_slot(x)
+                               if x.slot:
+                                       evaluated_atom += ":%s" % x.slot
+                               evaluated_atom += str(x.use.evaluate_conditionals(myuse))
+                               x = portage.dep.Atom(evaluated_atom)
+
                mykey = dep_getkey(x)
                if not mykey.startswith("virtual/"):
                        newsplit.append(x)
index 3e642b51750b282eef18531a50092efd50a3ade7..6881b17346ad98cc4e7ed9b3073336c53992d4f8 100644 (file)
@@ -19,6 +19,7 @@
 #
 
 import re, sys, types
+from itertools import chain
 import portage.exception
 from portage.exception import InvalidData, InvalidAtom
 from portage.versions import catpkgsplit, catsplit, pkgcmp, pkgsplit, ververify
@@ -340,15 +341,52 @@ class _use_dep(object):
        def __init__(self, use):
                enabled_flags = []
                disabled_flags = []
+               conditional_enabled = []
+               conditional_disabled = []
                for x in use:
                        if "-" == x[:1]:
-                               disabled_flags.append(x[1:])
+                               if "?" == x[-1:]:
+                                       conditional_disabled.append(x[1:-1])
+                               else:
+                                       disabled_flags.append(x[1:])
                        else:
-                               enabled_flags.append(x)
+                               if "?" == x[-1:]:
+                                       conditional_enabled.append(x[:-1])
+                               else:
+                                       enabled_flags.append(x)
                self.tokens = use
+               if not isinstance(self.tokens, tuple):
+                       self.tokens = tuple(self.tokens)
                self.enabled = frozenset(enabled_flags)
                self.disabled = frozenset(disabled_flags)
-               self.required = self.enabled.union(self.disabled)
+               self.conditional_enabled = frozenset(conditional_enabled)
+               self.conditional_disabled = frozenset(conditional_disabled)
+               self.conditional = self.conditional_enabled.union(
+                       self.conditional_disabled)
+               self.required = frozenset(chain(self.enabled, self.disabled,
+                       self.conditional_enabled, self.conditional_disabled))
+
+       def __str__(self):
+               return "".join("[%s]" % x for x in self.tokens)
+
+       def evaluate_conditionals(self, use):
+               """
+               Create a new instance with conditionals evaluated as follows:
+
+               parent state   conditional   result
+                x              x?            x
+               -x              x?           -x
+                x             -x?           -x
+               -x             -x?            x
+               """
+               tokens = []
+               tokens.extend(self.enabled)
+               tokens.extend("-" + x for x in self.disabled)
+               tokens.extend(self.conditional_enabled.intersection(use))
+               tokens.extend("-" + x for x in self.conditional_enabled.difference(use))
+               tokens.extend("-" + x for x in self.conditional_disabled.intersection(use))
+               tokens.extend(self.conditional_disabled.difference(use))
+               return _use_dep(tokens)
 
 class Atom(str):
 
@@ -519,7 +557,7 @@ def dep_getusedeps( depend ):
                open_bracket = depend.find( '[', open_bracket+1 )
        return tuple(use_list)
 
-_invalid_atom_chars_regexp = re.compile("[()|?@]")
+_invalid_atom_chars_regexp = re.compile("[()|@]")
 
 def isvalidatom(atom, allow_blockers=False):
        """