Merged from trunk 11225:11238
authorFabian Groffen <grobian@gentoo.org>
Mon, 28 Jul 2008 17:48:47 +0000 (17:48 -0000)
committerFabian Groffen <grobian@gentoo.org>
Mon, 28 Jul 2008 17:48:47 +0000 (17:48 -0000)
   | 11226   | Fix the new glep56 code to handle missing metadata.xml.      |
   | zmedico | Thanks to jmbsvicetto for reporting.                         |

   | 11227   | Fix incorrect logging.exception() arguments. The exception   |
   | zmedico | instance is not supposed to be passed into this function.    |

   | 11228   | Bug #233137 - Implement Atom.split().                        |
   | zmedico |                                                              |

   | 11229   | * Add support in dep_getusedeps() and isvalidatom() for      |
   | zmedico | comma separated USE deps that only have one set of square    |
   |         | brackets. * Add test cases for the new comma separated USE   |
   |         | deps syntax.                                                 |

   | 11230   | Create a SlotDict constructor which can take an optional     |
   | zmedico | positional arg that is passed to the update() method         |
   |         | (similar to the dict constructor), and also pass keyword     |
   |         | arguments into the update() method if any are given. This    |
   |         | makes it possible to use the constructor similarly to the    |
   |         | way that the _emerge.SlotObject constructor is used.         |

   | 11231   | Implement new conditional USE dep syntax: Conditional        |
   | zmedico | evaluation behavior: parent state conditional result x x? x  |
   |         | -x x? x -x? -x -x? -x x x= x -x x= -x x x!= -x -x x!= x      |
   |         | Conditional syntax examples: compact form equivalent         |
   |         | expanded form foo[bar?] foo bar? ( foo[bar] ) foo[-bar?] foo |
   |         | !bar? ( foo[-bar] ) foo[bar=] foo bar? ( foo[bar] ) !bar? (  |
   |         | foo[-bar] ) foo[bar!=] foo bar? ( foo[-bar] ) !bar? (        |
   |         | foo[bar] )                                                   |

   | 11232   | Disable the multi-bracket USE deps syntax, so only the comma |
   | zmedico | separated syntax is now valid.                               |

   | 11234   | Fix arg count when constructing a TypeError in the SlotDict  |
   | zmedico | constructor.                                                 |

   | 11235   | Create a table to document conditional USE dependency        |
   | zmedico | syntax.                                                      |

   | 11236   | Add note about support for EAPI="2_pre0".                    |
   | zmedico |                                                              |

   | 11238   | Remove pointless generator expression.                       |
   | zmedico |                                                              |

svn path=/main/branches/prefix/; revision=11239

NEWS
bin/repoman
doc/package/ebuild.docbook
doc/package/ebuild/eapi/2.docbook [new file with mode: 0644]
doc/portage.docbook
pym/portage/cache/mappings.py
pym/portage/dep.py
pym/portage/tests/dep/test_dep_getusedeps.py
pym/portage/tests/dep/test_isvalidatom.py

diff --git a/NEWS b/NEWS
index 4c565a514fa4473c6f1a40810cdffbbba956f460..fe6fb10ae5bea8df10c05c54bbc846e66478b704 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -3,6 +3,11 @@ News (mainly features/major bug fixes)
 portage-2.2
 -------------
 
+* Add support for a new EAPI="2_pre0" value that can be used in ebuilds when
+  testing new features such as USE dependencies. This is an experimental EAPI
+  that will not be supported after the final EAPI 2 is defined. For more
+  information about experimental EAPI features, refer to the "Ebuild" chapter
+  of the html documentation that is installed with portage.
 * Add PORTAGE_IONICE_COMMAND setting for make.conf which is called to adjust
   IO priority on portage and it's subprocesses.
 * Add link level dependency awareness to emerge --depclean and --prune actions
index a164b4c3f5dd950d1443511ea8fbeebe174ebde2..d0d58795580f7fb90131e04f809e198058a87e85 100755 (executable)
@@ -570,7 +570,7 @@ try:
        utilities.parse_use_local_desc(f, luselist)
        f.close()
 except (IOError, OSError, ParseError), e:
-       logging.exception("Couldn't read from use.local.desc", e)
+       logging.exception("Couldn't read from use.local.desc")
        sys.exit(1)
 
 if portdir_overlay != portdir:
@@ -581,7 +581,7 @@ if portdir_overlay != portdir:
                        utilities.parse_use_local_desc(f, luselist)
                        f.close()
                except (IOError, OSError, ParseError), e:
-                       logging.exception("Couldn't read from '%s'" % filename, e)
+                       logging.exception("Couldn't read from '%s'" % (filename,))
                        sys.exit(1)
        del filename
 
@@ -596,7 +596,7 @@ try:
                for l in range(0, len(vardescs)):
                        uselist.append(var.lower() + "_" + vardescs[l].split()[0])
 except (IOError, OSError, ParseError), e:
-       logging.exception("Couldn't read USE flags from use.desc", e)
+       logging.exception("Couldn't read USE flags from use.desc")
        sys.exit(1)
 
 # retrieve a list of current licenses in portage
@@ -1059,6 +1059,8 @@ for x in scanlist:
                fails["changelog.missing"].append(x+"/ChangeLog")
        
        #metadata.xml file check
+       muselist = []
+
        if "metadata.xml" not in checkdirlist:
                stats["metadata.missing"]+=1
                fails["metadata.missing"].append(x+"/metadata.xml")
@@ -1078,15 +1080,14 @@ for x in scanlist:
                                stats["metadata.bad"]+=1
                                fails["metadata.bad"].append(x+"/metadata.xml")
 
-       #load USE flags from metadata.xml
-       muselist=[]
-       try:
-               f = open(os.path.join(checkdir, "metadata.xml"))
-               utilities.parse_metadata_use(f, muselist)
-               f.close()
-       except (IOError, OSError, ParseError), e:
-               logging.exception("Couldn't read from metadata.xml", e)
-               sys.exit(1)
+               #load USE flags from metadata.xml
+               try:
+                       f = open(os.path.join(checkdir, "metadata.xml"))
+                       utilities.parse_metadata_use(f, muselist)
+                       f.close()
+               except (EnvironmentError, ParseError), e:
+                       logging.exception("Couldn't read from metadata.xml")
+                       sys.exit(1)
 
        allmasked = True
 
index 4bdb8129d92bb8cc08456f5ecbb951960194b144..fa4f75609f13fb6850b55c221fc097cd446d8eeb 100644 (file)
@@ -2,4 +2,5 @@
 <title>Ebuild</title>
 &package_ebuild_phases;
 &package_ebuild_helper_functions;
+&package_ebuild_eapi_2;
 </chapter>
diff --git a/doc/package/ebuild/eapi/2.docbook b/doc/package/ebuild/eapi/2.docbook
new file mode 100644 (file)
index 0000000..594ecea
--- /dev/null
@@ -0,0 +1,39 @@
+<sect1 id='package-ebuild-eapi-2'>
+       <title>EAPI 2_pre0</title>
+       <sect2 id='package-ebuild-eapi-2-use-deps'>
+       <title>USE Dependencies</title>
+       <sect3 id='package-ebuild-eapi-2-use-deps-conditional'>
+       <title>Conditional USE Dependencies</title>
+       <table><title>Syntax Examples</title>
+       <tgroup cols='2' align='left' >
+       <colspec colname='compact'/>
+       <colspec colname='expanded'/>
+       <thead>
+       <row>
+       <entry>Compact Form</entry>
+       <entry>Equivalent Expanded Form</entry>
+       </row>
+       </thead>
+       <tbody>
+       <row>
+       <entry>foo[bar?]</entry>
+       <entry>foo  bar? (  foo[bar] )</entry>
+       </row>
+       <row>
+       <entry>foo[-bar?]</entry>
+       <entry>foo !bar? ( foo[-bar] )</entry>
+       </row>
+       <row>
+       <entry>foo[bar=]</entry>
+       <entry>foo  bar? (  foo[bar] ) !bar? ( foo[-bar] )</entry>
+       </row>
+       <row>
+       <entry>foo[bar!=]</entry>
+       <entry>foo  bar? ( foo[-bar] ) !bar? (  foo[bar] )</entry>
+       </row>
+       </tbody>
+       </tgroup>
+       </table>
+       </sect3>
+       </sect2>
+</sect1>
index 8c29303e66c0d5898dfd4f99a5a7b8d8c602ece6..c038079a25d0639228203241d83a1d7503b8bb0d 100644 (file)
@@ -15,6 +15,7 @@
        <!ENTITY package_ebuild SYSTEM "package/ebuild.docbook">
        <!ENTITY package_ebuild_phases SYSTEM "package/ebuild/phases.docbook">
        <!ENTITY package_ebuild_helper_functions SYSTEM "package/ebuild/helper_functions.docbook">
+       <!ENTITY package_ebuild_eapi_2 SYSTEM "package/ebuild/eapi/2.docbook">
        <!ENTITY qa SYSTEM "qa.docbook">
        <!ENTITY config SYSTEM "config.docbook">
        <!ENTITY config_bashrc SYSTEM "config/bashrc.docbook">
index d0ca487f07dca8376512b8178c984bd6bff728c4..96e9e553b9a12e0089dd832ea543d01163a7e1a0 100644 (file)
@@ -142,6 +142,19 @@ def slot_dict_class(keys, prefix="_val_"):
                        __slots__ = ("__weakref__",) + \
                                tuple(prefix + k for k in allowed_keys)
 
+                       def __init__(self, *args, **kwargs):
+
+                               if len(args) > 1:
+                                       raise TypeError(
+                                               "expected at most 1 positional argument, got " + \
+                                               repr(len(args)))
+
+                               if args:
+                                       self.update(args[0])
+
+                               if kwargs:
+                                       self.update(kwargs)
+
                        def __iter__(self):
                                for k, v in self.iteritems():
                                        yield k
index c2f506d4bd321181cfaa6a20fe5d63d48b4221d6..49f6bc045a4ec39667ac74760a186720abd71126 100644 (file)
@@ -24,6 +24,7 @@ from itertools import chain
 import portage.exception
 from portage.exception import InvalidData, InvalidAtom
 from portage.versions import catpkgsplit, catsplit, pkgcmp, pkgsplit, ververify
+import portage.cache.mappings
 
 def cpvequal(cpv1, cpv2):
        """
@@ -343,54 +344,101 @@ class _use_dep(object):
        __slots__ = ("__weakref__", "conditional", "conditional_disabled",
                "conditional_enabled", "disabled", "enabled", "tokens", "required")
 
+       _conditionals_class = portage.cache.mappings.slot_dict_class(
+               ("disabled", "enabled", "equal", "not_equal"), prefix="")
+
        def __init__(self, use):
                enabled_flags = []
                disabled_flags = []
-               conditional_enabled = []
-               conditional_disabled = []
+               conditional = self._conditionals_class()
+               for k in conditional.allowed_keys:
+                       conditional[k] = []
+
                for x in use:
-                       if "-" == x[:1]:
-                               if "?" == x[-1:]:
-                                       conditional_disabled.append(x[1:-1])
+                       last_char = x[-1:]
+                       if "?" == last_char:
+                               if "-" == x[:1]:
+                                       conditional.disabled.append(x[1:-1])
                                else:
-                                       disabled_flags.append(x[1:])
+                                       conditional.enabled.append(x[:-1])
+                       elif "=" == last_char:
+                               if "-" == x[:1]:
+                                       raise InvalidAtom("Invalid use dep: '%s'" % (x,))
+                               if "!" == x[-2:-1]:
+                                       conditional.not_equal.append(x[:-2])
+                               else:
+                                       conditional.equal.append(x[:-1])
                        else:
-                               if "?" == x[-1:]:
-                                       conditional_enabled.append(x[:-1])
+                               if "-" == x[:1]:
+                                       disabled_flags.append(x[1:])
                                else:
                                        enabled_flags.append(x)
+
                self.tokens = use
                if not isinstance(self.tokens, tuple):
                        self.tokens = tuple(self.tokens)
+
+               self.required = frozenset(chain(
+                       enabled_flags,
+                       disabled_flags,
+                       *conditional.values()
+               ))
+
                self.enabled = frozenset(enabled_flags)
                self.disabled = frozenset(disabled_flags)
-               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))
+               self.conditional = None
+
+               for v in conditional.itervalues():
+                       if v:
+                               for k, v in conditional.iteritems():
+                                       conditional[k] = frozenset(v)
+                               self.conditional = conditional
+                               break
 
        def __str__(self):
-               return "".join("[%s]" % x for x in self.tokens)
+               return "[%s]" % (",".join(self.tokens),)
 
        def evaluate_conditionals(self, use):
                """
-               Create a new instance with conditionals evaluated as follows:
+               Create a new instance with conditionals evaluated.
+
+               Conditional evaluation behavior:
+
+                       parent state   conditional   result
+
+                        x              x?            x
+                       -x              x?
+                        x             -x?
+                       -x             -x?           -x
+
+                        x              x=            x
+                       -x              x=           -x
+                        x             x!=           -x
+                       -x             x!=            x
+
+               Conditional syntax examples:
+
+                       compact form         equivalent expanded form
+
+                        foo[bar?]           foo  bar? (  foo[bar] )
+                       foo[-bar?]           foo !bar? ( foo[-bar] )
+                        foo[bar=]           foo  bar? (  foo[bar] ) !bar? ( foo[-bar] )
+                        foo[bar!=]          foo  bar? ( foo[-bar] ) !bar? (  foo[bar] )
 
-               parent state   conditional   result
-                x              x?            x
-               -x              x?           -x
-                x             -x?           -x
-               -x             -x?            x
                """
                tokens = []
+
+               conditional = self.conditional
                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))
+               tokens.extend(x for x in conditional.enabled if x in use)
+               tokens.extend("-" + x for x in conditional.disabled if x not in use)
+
+               tokens.extend(x for x in conditional.equal if x in use)
+               tokens.extend("-" + x for x in conditional.equal if x not in use)
+               tokens.extend("-" + x for x in conditional.not_equal if x in use)
+               tokens.extend(x for x in conditional.not_equal if x not in use)
+
                return _use_dep(tokens)
 
 class _AtomCache(type):
@@ -416,7 +464,8 @@ class Atom(object):
        _atoms = weakref.WeakValueDictionary()
 
        _str_methods = ("endswith", "find", "index", "lstrip", "replace",
-               "startswith", "strip", "rindex", "rfind", "rstrip", "__getitem__",
+               "startswith", "split", "strip",
+               "rindex", "rfind", "rstrip", "__getitem__",
                "__eq__", "__hash__", "__len__", "__ne__", "__repr__", "__str__")
 
        __slots__ = ("__weakref__", "blocker", "cp", "cpv", "operator",
@@ -587,16 +636,38 @@ def dep_getusedeps( depend ):
        use_list = []
        open_bracket = depend.find('[')
        # -1 = failure (think c++ string::npos)
+       comma_separated = False
+       bracket_count = 0
        while( open_bracket != -1 ):
+               bracket_count += 1
+               if bracket_count > 1:
+                       raise InvalidAtom("USE Dependency with more " + \
+                               "than one set of brackets: %s" % (depend,))
                close_bracket = depend.find(']', open_bracket )
                if close_bracket == -1:
                        raise InvalidAtom("USE Dependency with no closing bracket: %s" % depend )
                use = depend[open_bracket + 1: close_bracket]
                # foo[1:1] may return '' instead of None, we don't want '' in the result
-               if len(use):
-                       use_list.append(use)
+               if not use:
+                       raise InvalidAtom("USE Dependency with " + \
+                               "no use flag ([]): %s" % depend )
+               if not comma_separated:
+                       comma_separated = "," in use
+
+               if comma_separated and bracket_count > 1:
+                       raise InvalidAtom("USE Dependency contains a mixture of " + \
+                               "comma and bracket separators: %s" % depend )
+
+               if comma_separated:
+                       for x in use.split(","):
+                               if x:
+                                       use_list.append(x)
+                               else:
+                                       raise InvalidAtom("USE Dependency with no use " + \
+                                               "flag next to comma: %s" % depend )
                else:
-                       raise InvalidAtom("USE Dependency with no use flag ([]): %s" % depend )
+                       use_list.append(use)
+
                # Find next use flag
                open_bracket = depend.find( '[', open_bracket+1 )
        return tuple(use_list)
@@ -633,6 +704,14 @@ def isvalidatom(atom, allow_blockers=False):
                return 0
        if allow_blockers and atom.startswith("!"):
                atom = atom[1:]
+
+       try:
+               use = dep_getusedeps(atom)
+               if use:
+                       use = _use_dep(use)
+       except InvalidAtom:
+               return 0
+
        cpv = dep_getcpv(atom)
        cpv_catsplit = catsplit(cpv)
        mycpv_cps = None
index 71b0fe290100809a39bf24138fc9d5db3948ae12..99a17b80de765cd54198e85f247b48c4de9a8269 100644 (file)
@@ -25,8 +25,7 @@ class DepGetUseDeps(TestCase):
                                                if slot:
                                                        cpv += ":" + slot
                                                if isinstance(use, tuple):
-                                                       for u in use:
-                                                               cpv = cpv + "[" + u + "]"
+                                                       cpv += "[%s]" % (",".join(use),)
                                                        self.assertEqual( dep_getusedeps(
                                                                cpv ), use )
                                                else:
index dfcf178988517d9e9afa5872938f94a273ad503f..f7cc3b844e8533751372a328c3fd7a1f1c39813a 100644 (file)
@@ -25,7 +25,17 @@ class IsValidAtom(TestCase):
                          ( "sys-apps/portage:foo", True ),
                          ( "sys-apps/portage-2.1:foo", False ),
                          ( "sys-apps/portage-2.1:", False ),
-                         ( "=sys-apps/portage-2.2*:foo[bar][-baz][doc?][-build?]", True ),
+                         ( "=sys-apps/portage-2.2*:foo[bar?,-baz?,doc!=,build=]", True ),
+                         ( "=sys-apps/portage-2.2*:foo[build=]", True ),
+                         ( "=sys-apps/portage-2.2*:foo[doc!=]", True ),
+                         ( "=sys-apps/portage-2.2*:foo[-doc!=]", False ),
+                         ( "=sys-apps/portage-2.2*:foo[-doc=]", False ),
+                         ( "=sys-apps/portage-2.2*:foo[bar][-baz][doc?][-build?]", False ),
+                         ( "=sys-apps/portage-2.2*:foo[bar,-baz,doc?,-build?]", True ),
+                         ( "=sys-apps/portage-2.2*:foo[bar,-baz,doc?,-build?,]", False ),
+                         ( "=sys-apps/portage-2.2*:foo[,bar,-baz,doc?,-build?]", False ),
+                         ( "=sys-apps/portage-2.2*:foo[bar,-baz][doc?,-build?]", False ),
+                         ( "=sys-apps/portage-2.2*:foo[bar][doc,build]", False ),
                          ( ">~cate-gory/foo-1.0", False ),
                          ( ">~category/foo-1.0", False ),
                          ( "<~category/foo-1.0", False ),