config: Add KeywordsManager
authorSebastian Luther <SebastianLuther@gmx.de>
Tue, 14 Sep 2010 08:41:33 +0000 (10:41 +0200)
committerZac Medico <zmedico@gentoo.org>
Tue, 14 Sep 2010 08:51:31 +0000 (01:51 -0700)
pym/portage/package/ebuild/_config/KeywordsManager.py [new file with mode: 0644]
pym/portage/package/ebuild/config.py
pym/portage/package/ebuild/getmaskingstatus.py

diff --git a/pym/portage/package/ebuild/_config/KeywordsManager.py b/pym/portage/package/ebuild/_config/KeywordsManager.py
new file mode 100644 (file)
index 0000000..b9c2236
--- /dev/null
@@ -0,0 +1,184 @@
+# Copyright 2010 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+__all__ = (
+       'KeywordsManager',
+)
+
+from portage import os
+from portage.dep import ExtendedAtomDict
+from portage.localization import _
+from portage.package.ebuild._config.helper import ordered_by_atom_specificity
+from portage.util import grabdict_package, stack_lists, writemsg
+from portage.versions import cpv_getkey
+
+class KeywordsManager(object):
+
+       def __init__(self, profiles, abs_user_config, user_config=True, global_accept_keywords=""):
+               self._pkeywords_list = []
+               rawpkeywords = [grabdict_package(
+                       os.path.join(x, "package.keywords"), recursive=1, verify_eapi=True) \
+                       for x in profiles]
+               for pkeyworddict in rawpkeywords:
+                       if not pkeyworddict:
+                               # Omit non-existent files from the stack. This isn't
+                               # feasible for package.use (among other package.*
+                               # files such as package.use.mask) since it is stacked
+                               # in layers with make.defaults USE, and the layer
+                               # indices need to align.
+                               continue
+                       cpdict = {}
+                       for k, v in pkeyworddict.items():
+                               cpdict.setdefault(k.cp, {})[k] = v
+                       self._pkeywords_list.append(cpdict)
+               self._pkeywords_list = tuple(self._pkeywords_list)
+
+               self._p_accept_keywords = []
+               raw_p_accept_keywords = [grabdict_package(
+                       os.path.join(x, "package.accept_keywords"), recursive=1, verify_eapi=True) \
+                       for x in profiles]
+               for d in raw_p_accept_keywords:
+                       if not d:
+                               # Omit non-existent files from the stack.
+                               continue
+                       cpdict = {}
+                       for k, v in d.items():
+                               cpdict.setdefault(k.cp, {})[k] = tuple(v)
+                       self._p_accept_keywords.append(cpdict)
+               self._p_accept_keywords = tuple(self._p_accept_keywords)
+
+               self.pkeywordsdict = ExtendedAtomDict(dict)
+
+               if user_config:
+                       pkgdict = grabdict_package(
+                               os.path.join(abs_user_config, "package.keywords"),
+                               recursive=1, allow_wildcard=True, verify_eapi=False)
+
+                       for k, v in grabdict_package(
+                               os.path.join(abs_user_config, "package.accept_keywords"),
+                               recursive=1, allow_wildcard=True, verify_eapi=False).items():
+                               pkgdict.setdefault(k, []).extend(v)
+
+                       accept_keywords_defaults = global_accept_keywords.split()
+                       accept_keywords_defaults = tuple('~' + keyword for keyword in \
+                               accept_keywords_defaults if keyword[:1] not in "~-")
+                       for k, v in pkgdict.items():
+                               # default to ~arch if no specific keyword is given
+                               if not v:
+                                       v = accept_keywords_defaults
+                               self.pkeywordsdict.setdefault(k.cp, {})[k] = v
+
+       def getKeywords(self, cpv, slot, keywords):
+               cp = cpv_getkey(cpv)
+               pkg = "%s:%s" % (cpv, slot)
+               keywords = [[x for x in keywords.split() if x != "-*"]]
+               for pkeywords_dict in self._pkeywords_list:
+                       cpdict = pkeywords_dict.get(cp)
+                       if cpdict:
+                               pkg_keywords = ordered_by_atom_specificity(cpdict, pkg)
+                               if pkg_keywords:
+                                       keywords.extend(pkg_keywords)
+               return stack_lists(keywords, incremental=True)
+
+       def getMissingKeywords(self, cpv, slot, keywords, global_accept_keywords, backuped_accept_keywords):
+               """
+               Take a package and return a list of any KEYWORDS that the user may
+               may need to accept for the given package. If the KEYWORDS are empty
+               and the the ** keyword has not been accepted, the returned list will
+               contain ** alone (in order to distiguish from the case of "none
+               missing").
+
+               @param cpv: The package name (for package.keywords support)
+               @type cpv: String
+               @param slot: The 'SLOT' key from the raw package metadata
+               @type slot: String
+               @param keywords: The 'KEYWORDS' key from the raw package metadata
+               @type keywords: String
+               @param global_accept_keywords: The current value of ACCEPT_KEYWORDS
+               @type global_accept_keywords: String
+               @param backuped_accept_keywords: ACCEPT_KEYWORDS from the backup env
+               @type backuped_accept_keywords: String
+               @rtype: List
+               @return: A list of KEYWORDS that have not been accepted.
+               """
+
+               # Hack: Need to check the env directly here as otherwise stacking 
+               # doesn't work properly as negative values are lost in the config
+               # object (bug #139600)
+               egroups = backuped_accept_keywords.split()
+               mygroups = self.getKeywords(cpv, slot, keywords)
+               # Repoman may modify this attribute as necessary.
+               pgroups = global_accept_keywords.split()
+               matches = False
+               cp = cpv_getkey(cpv)
+
+               if self._p_accept_keywords:
+                       cpv_slot = "%s:%s" % (cpv, slot)
+                       accept_keywords_defaults = tuple('~' + keyword for keyword in \
+                               pgroups if keyword[:1] not in "~-")
+                       for d in self._p_accept_keywords:
+                               cpdict = d.get(cp)
+                               if cpdict:
+                                       pkg_accept_keywords = \
+                                               ordered_by_atom_specificity(cpdict, cpv_slot)
+                                       if pkg_accept_keywords:
+                                               for x in pkg_accept_keywords:
+                                                       if not x:
+                                                               x = accept_keywords_defaults
+                                                       pgroups.extend(x)
+                                               matches = True
+
+               pkgdict = self.pkeywordsdict.get(cp)
+               if pkgdict:
+                       cpv_slot = "%s:%s" % (cpv, slot)
+                       pkg_accept_keywords = \
+                               ordered_by_atom_specificity(pkgdict, cpv_slot)
+                       if pkg_accept_keywords:
+                               for x in pkg_accept_keywords:
+                                       pgroups.extend(x)
+                               matches = True
+
+               if matches or egroups:
+                       pgroups.extend(egroups)
+                       inc_pgroups = set()
+                       for x in pgroups:
+                               if x.startswith("-"):
+                                       if x == "-*":
+                                               inc_pgroups.clear()
+                                       else:
+                                               inc_pgroups.discard(x[1:])
+                               else:
+                                       inc_pgroups.add(x)
+                       pgroups = inc_pgroups
+                       del inc_pgroups
+
+               match = False
+               hasstable = False
+               hastesting = False
+               for gp in mygroups:
+                       if gp == "*" or (gp == "-*" and len(mygroups) == 1):
+                               writemsg(_("--- WARNING: Package '%(cpv)s' uses"
+                                       " '%(keyword)s' keyword.\n") % {"cpv": cpv, "keyword": gp}, noiselevel=-1)
+                               if gp == "*":
+                                       match = 1
+                                       break
+                       elif gp in pgroups:
+                               match=1
+                               break
+                       elif gp.startswith("~"):
+                               hastesting = True
+                       elif not gp.startswith("-"):
+                               hasstable = True
+               if not match and \
+                       ((hastesting and "~*" in pgroups) or \
+                       (hasstable and "*" in pgroups) or "**" in pgroups):
+                       match=1
+               if match:
+                       missing = []
+               else:
+                       if not mygroups:
+                               # If KEYWORDS is empty then we still have to return something
+                               # in order to distiguish from the case of "none missing".
+                               mygroups.append("**")
+                       missing = mygroups
+               return missing
index d920b7e2049c1e26d32f9bb3a697ebd095dbccd6..f92dd86fb0bfc11bc16359a34e25d3257d6697b6 100644 (file)
@@ -49,6 +49,7 @@ from portage.versions import catpkgsplit, catsplit, cpv_getkey
 from portage.package.ebuild._config import special_env_vars
 from portage.package.ebuild._config.env_var_validation import validate_cmd_var
 from portage.package.ebuild._config.features_set import features_set
+from portage.package.ebuild._config.KeywordsManager import KeywordsManager
 from portage.package.ebuild._config.LicenseManager import LicenseManager
 from portage.package.ebuild._config.UseManager import UseManager
 from portage.package.ebuild._config.LocationsManager import LocationsManager
@@ -236,8 +237,7 @@ class config(object):
                        self._setcpv_args_hash = clone._setcpv_args_hash
 
                        # immutable attributes (internal policy ensures lack of mutation)
-                       self._pkeywords_list = clone._pkeywords_list
-                       self._p_accept_keywords = clone._p_accept_keywords
+                       self._keywords_manager = clone._keywords_manager
                        self._use_manager = clone._use_manager
                        self._mask_manager = clone._mask_manager
 
@@ -261,7 +261,6 @@ class config(object):
                        self.lookuplist.reverse()
                        self._use_expand_dict = copy.deepcopy(clone._use_expand_dict)
                        self.backupenv  = self.configdict["backupenv"]
-                       self.pkeywordsdict = copy.deepcopy(clone.pkeywordsdict)
                        self.prevmaskdict = copy.deepcopy(clone.prevmaskdict)
                        self.pprovideddict = copy.deepcopy(clone.pprovideddict)
                        self.features = features_set(self)
@@ -356,38 +355,6 @@ class config(object):
                                        x = Atom(x.lstrip('*'))
                                self.prevmaskdict.setdefault(x.cp, []).append(x)
 
-                       self._pkeywords_list = []
-                       rawpkeywords = [grabdict_package(
-                               os.path.join(x, "package.keywords"), recursive=1, verify_eapi=True) \
-                               for x in self.profiles]
-                       for pkeyworddict in rawpkeywords:
-                               if not pkeyworddict:
-                                       # Omit non-existent files from the stack. This isn't
-                                       # feasible for package.use (among other package.*
-                                       # files such as package.use.mask) since it is stacked
-                                       # in layers with make.defaults USE, and the layer
-                                       # indices need to align.
-                                       continue
-                               cpdict = {}
-                               for k, v in pkeyworddict.items():
-                                       cpdict.setdefault(k.cp, {})[k] = v
-                               self._pkeywords_list.append(cpdict)
-                       self._pkeywords_list = tuple(self._pkeywords_list)
-
-                       self._p_accept_keywords = []
-                       raw_p_accept_keywords = [grabdict_package(
-                               os.path.join(x, "package.accept_keywords"), recursive=1, verify_eapi=True) \
-                               for x in self.profiles]
-                       for d in raw_p_accept_keywords:
-                               if not d:
-                                       # Omit non-existent files from the stack.
-                                       continue
-                               cpdict = {}
-                               for k, v in d.items():
-                                       cpdict.setdefault(k.cp, {})[k] = tuple(v)
-                               self._p_accept_keywords.append(cpdict)
-                       self._p_accept_keywords = tuple(self._p_accept_keywords)
-
                        # The expand_map is used for variable substitution
                        # in getconfig() calls, and the getconfig() calls
                        # update expand_map with the value of each variable
@@ -532,7 +499,6 @@ class config(object):
                        self["PORTAGE_SANDBOX_COMPAT_LEVEL"] = _SANDBOX_COMPAT_LEVEL
                        self.backup_changes("PORTAGE_SANDBOX_COMPAT_LEVEL")
 
-                       self.pkeywordsdict = portage.dep.ExtendedAtomDict(dict)
                        self._ppropertiesdict = portage.dep.ExtendedAtomDict(dict)
                        self._penvdict = portage.dep.ExtendedAtomDict(dict)
 
@@ -554,6 +520,10 @@ class config(object):
 
                        locations_manager.set_port_dirs(self["PORTDIR"], self["PORTDIR_OVERLAY"])
 
+                       #Read package.keywords and package.accept_keywords.
+                       self._keywords_manager = KeywordsManager(self.profiles, abs_user_config, \
+                               local_config, global_accept_keywords=self.configdict["defaults"].get("ACCEPT_KEYWORDS", ""))
+
                        #Read all USE related files from profiles and optionally from user config.
                        self._use_manager = UseManager(self.profiles, abs_user_config, user_config=local_config)
                        #Initialize all USE related variables we track ourselves.
@@ -577,26 +547,6 @@ class config(object):
                        self._virtuals_manager = VirtualsManager(self.profiles)
 
                        if local_config:
-                               # package.accept_keywords and package.keywords
-                               pkgdict = grabdict_package(
-                                       os.path.join(abs_user_config, "package.keywords"),
-                                       recursive=1, allow_wildcard=True, verify_eapi=False)
-
-                               for k, v in grabdict_package(
-                                       os.path.join(abs_user_config, "package.accept_keywords"),
-                                       recursive=1, allow_wildcard=True, verify_eapi=False).items():
-                                       pkgdict.setdefault(k, []).extend(v)
-
-                               accept_keywords_defaults = \
-                                       self.configdict["defaults"].get("ACCEPT_KEYWORDS", "").split()
-                               accept_keywords_defaults = tuple('~' + keyword for keyword in \
-                                       accept_keywords_defaults if keyword[:1] not in "~-")
-                               for k, v in pkgdict.items():
-                                       # default to ~arch if no specific keyword is given
-                                       if not v:
-                                               v = accept_keywords_defaults
-                                       self.pkeywordsdict.setdefault(k.cp, {})[k] = v
-
                                #package.properties
                                propdict = grabdict_package(os.path.join(
                                        abs_user_config, "package.properties"), recursive=1, allow_wildcard=True, verify_eapi=False)
@@ -1489,17 +1439,7 @@ class config(object):
                return None
 
        def _getKeywords(self, cpv, metadata):
-               cp = cpv_getkey(cpv)
-               pkg = "%s:%s" % (cpv, metadata["SLOT"])
-               keywords = [[x for x in metadata.get("KEYWORDS", "").split() \
-                       if x != "-*"]]
-               for pkeywords_dict in self._pkeywords_list:
-                       cpdict = pkeywords_dict.get(cp)
-                       if cpdict:
-                               pkg_keywords = ordered_by_atom_specificity(cpdict, pkg)
-                               if pkg_keywords:
-                                       keywords.extend(pkg_keywords)
-               return stack_lists(keywords, incremental=True)
+               return self._keywords_manager.getKeywords(cpv, metadata["SLOT"], metadata.get("KEYWORDS", ""))
 
        def _getMissingKeywords(self, cpv, metadata):
                """
@@ -1520,84 +1460,11 @@ class config(object):
                # Hack: Need to check the env directly here as otherwise stacking 
                # doesn't work properly as negative values are lost in the config
                # object (bug #139600)
-               egroups = self.configdict["backupenv"].get(
-                       "ACCEPT_KEYWORDS", "").split()
-               mygroups = self._getKeywords(cpv, metadata)
-               # Repoman may modify this attribute as necessary.
-               pgroups = self["ACCEPT_KEYWORDS"].split()
-               matches = False
-               cp = cpv_getkey(cpv)
+               backuped_accept_keywords = self.configdict["backupenv"].get("ACCEPT_KEYWORDS", "")
+               global_accept_keywords = self["ACCEPT_KEYWORDS"]
 
-               if self._p_accept_keywords:
-                       cpv_slot = "%s:%s" % (cpv, metadata["SLOT"])
-                       accept_keywords_defaults = tuple('~' + keyword for keyword in \
-                               pgroups if keyword[:1] not in "~-")
-                       for d in self._p_accept_keywords:
-                               cpdict = d.get(cp)
-                               if cpdict:
-                                       pkg_accept_keywords = \
-                                               ordered_by_atom_specificity(cpdict, cpv_slot)
-                                       if pkg_accept_keywords:
-                                               for x in pkg_accept_keywords:
-                                                       if not x:
-                                                               x = accept_keywords_defaults
-                                                       pgroups.extend(x)
-                                               matches = True
-
-               pkgdict = self.pkeywordsdict.get(cp)
-               if pkgdict:
-                       cpv_slot = "%s:%s" % (cpv, metadata["SLOT"])
-                       pkg_accept_keywords = \
-                               ordered_by_atom_specificity(pkgdict, cpv_slot)
-                       if pkg_accept_keywords:
-                               for x in pkg_accept_keywords:
-                                       pgroups.extend(x)
-                               matches = True
-
-               if matches or egroups:
-                       pgroups.extend(egroups)
-                       inc_pgroups = set()
-                       for x in pgroups:
-                               if x.startswith("-"):
-                                       if x == "-*":
-                                               inc_pgroups.clear()
-                                       else:
-                                               inc_pgroups.discard(x[1:])
-                               else:
-                                       inc_pgroups.add(x)
-                       pgroups = inc_pgroups
-                       del inc_pgroups
-
-               match = False
-               hasstable = False
-               hastesting = False
-               for gp in mygroups:
-                       if gp == "*" or (gp == "-*" and len(mygroups) == 1):
-                               writemsg(_("--- WARNING: Package '%(cpv)s' uses"
-                                       " '%(keyword)s' keyword.\n") % {"cpv": cpv, "keyword": gp}, noiselevel=-1)
-                               if gp == "*":
-                                       match = 1
-                                       break
-                       elif gp in pgroups:
-                               match=1
-                               break
-                       elif gp.startswith("~"):
-                               hastesting = True
-                       elif not gp.startswith("-"):
-                               hasstable = True
-               if not match and \
-                       ((hastesting and "~*" in pgroups) or \
-                       (hasstable and "*" in pgroups) or "**" in pgroups):
-                       match=1
-               if match:
-                       missing = []
-               else:
-                       if not mygroups:
-                               # If KEYWORDS is empty then we still have to return something
-                               # in order to distiguish from the case of "none missing".
-                               mygroups.append("**")
-                       missing = mygroups
-               return missing
+               return self._keywords_manager.getMissingKeywords(cpv, metadata["SLOT"], \
+                       metadata.get("KEYWORDS", ""), global_accept_keywords, backuped_accept_keywords)
 
        def _getMissingLicenses(self, cpv, metadata):
                """
index a09aa33ddf5c7c35ea4a18fbac3e541739de9f58..434b4b2eba6e8c77b63aaa932491240e8e5809cd 100644 (file)
@@ -100,7 +100,7 @@ def _getmaskingstatus(mycpv, settings, portdb):
                myarch = pgroups[0].lstrip("~")
 
        cp = cpv_getkey(mycpv)
-       pkgdict = settings.pkeywordsdict.get(cp)
+       pkgdict = settings._keywords_manager.pkeywordsdict.get(cp)
        matches = False
        if pkgdict:
                cpv_slot_list = ["%s:%s" % (mycpv, metadata["SLOT"])]