config: Split out LicenseManager and helper
authorSebastian Luther <SebastianLuther@gmx.de>
Tue, 24 Aug 2010 08:21:07 +0000 (10:21 +0200)
committerZac Medico <zmedico@gentoo.org>
Tue, 24 Aug 2010 13:13:39 +0000 (06:13 -0700)
pym/portage/package/ebuild/_config/LicenseManager.py [new file with mode: 0644]
pym/portage/package/ebuild/_config/__init__.py [new file with mode: 0644]
pym/portage/package/ebuild/_config/helper.py [new file with mode: 0644]
pym/portage/package/ebuild/config.py

diff --git a/pym/portage/package/ebuild/_config/LicenseManager.py b/pym/portage/package/ebuild/_config/LicenseManager.py
new file mode 100644 (file)
index 0000000..fa030f1
--- /dev/null
@@ -0,0 +1,231 @@
+# Copyright 2010 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+__all__ = (
+       'LicenseManager',
+)
+
+import copy
+
+from portage import os
+from portage.dep import ExtendedAtomDict, use_reduce
+from portage.util import grabdict, grabdict_package, writemsg
+from portage.versions import cpv_getkey
+
+from portage.package.ebuild._config.helper import ordered_by_atom_specificity
+
+
+class LicenseManager(object):
+
+       def __init__(self, clone=None):
+               if clone:
+                       self._accept_license_str = copy.deepcopy(clone._accept_license_str)
+                       self._accept_license = copy.deepcopy(clone._accept_license)
+                       self._plicensedict = copy.deepcopy(clone._plicensedict)
+                       self._license_groups = copy.deepcopy(clone._license_groups)
+                       self._undef_lic_groups = copy.deepcopy(clone._undef_lic_groups)
+               else:
+                       self._accept_license_str = None
+                       self._accept_license = None
+                       self._license_groups = {}
+                       self._plicensedict = ExtendedAtomDict(dict)
+                       self._undef_lic_groups = set()
+
+       def read_config_files(self, abs_user_config):
+               licdict = grabdict_package(os.path.join(
+                       abs_user_config, "package.license"), recursive=1, allow_wildcard=True)
+               for k, v in licdict.items():
+                       self._plicensedict.setdefault(k.cp, {})[k] = \
+                               self.expandLicenseTokens(v)
+
+       def parse_license_groups(self, locations):
+               for loc in locations:
+                       for k, v in grabdict(
+                               os.path.join(loc, "license_groups")).items():
+                               self._license_groups.setdefault(k, []).extend(v)
+
+       def extract_global_changes(self, old=""):
+               ret = old
+               atom_license_map = self._plicensedict.get("*/*")
+               if atom_license_map is not None:
+                       v = atom_license_map.pop("*/*", None)
+                       if v is not None:
+                               ret = " ".join(v)
+                               if old:
+                                       ret = old + " " + ret
+                               if not atom_license_map:
+                                       #No tokens left in atom_license_map, remove it.
+                                       del self._plicensedict["*/*"]
+               return ret
+       
+       def expandLicenseTokens(self, tokens):
+               """ Take a token from ACCEPT_LICENSE or package.license and expand it
+               if it's a group token (indicated by @) or just return it if it's not a
+               group.  If a group is negated then negate all group elements."""
+               expanded_tokens = []
+               for x in tokens:
+                       expanded_tokens.extend(self._expandLicenseToken(x, None))
+               return expanded_tokens
+
+       def _expandLicenseToken(self, token, traversed_groups):
+               negate = False
+               rValue = []
+               if token.startswith("-"):
+                       negate = True
+                       license_name = token[1:]
+               else:
+                       license_name = token
+               if not license_name.startswith("@"):
+                       rValue.append(token)
+                       return rValue
+               group_name = license_name[1:]
+               if traversed_groups is None:
+                       traversed_groups = set()
+               license_group = self._license_groups.get(group_name)
+               if group_name in traversed_groups:
+                       writemsg(_("Circular license group reference"
+                               " detected in '%s'\n") % group_name, noiselevel=-1)
+                       rValue.append("@"+group_name)
+               elif license_group:
+                       traversed_groups.add(group_name)
+                       for l in license_group:
+                               if l.startswith("-"):
+                                       writemsg(_("Skipping invalid element %s"
+                                               " in license group '%s'\n") % (l, group_name),
+                                               noiselevel=-1)
+                               else:
+                                       rValue.extend(self._expandLicenseToken(l, traversed_groups))
+               else:
+                       if self._license_groups and \
+                               group_name not in self._undef_lic_groups:
+                               self._undef_lic_groups.add(group_name)
+                               writemsg(_("Undefined license group '%s'\n") % group_name,
+                                       noiselevel=-1)
+                       rValue.append("@"+group_name)
+               if negate:
+                       rValue = ["-" + token for token in rValue]
+               return rValue
+
+       def _getPkgAcceptLicense(self, cpv, slot):
+               """
+               Get an ACCEPT_LICENSE list, accounting for package.license.
+               """
+               accept_license = self._accept_license
+               cp = cpv_getkey(cpv)
+               cpdict = self._plicensedict.get(cp)
+               if cpdict:
+                       cpv_slot = "%s:%s" % (cpv, slot)
+                       plicence_list = ordered_by_atom_specificity(cpdict, cpv_slot)
+                       if plicence_list:
+                               accept_license = list(self._accept_license)
+                               for x in plicence_list:
+                                       accept_license.extend(x)
+               return accept_license
+
+       def get_prunned_accept_license(self, cpv, use, lic, slot):
+               """
+               Generate a pruned version of ACCEPT_LICENSE, by intersection with
+               LICENSE. This is required since otherwise ACCEPT_LICENSE might be
+               too big (bigger than ARG_MAX), causing execve() calls to fail with
+               E2BIG errors as in bug #262647.
+               """
+               try:
+                       licenses = set(use_reduce(lic, uselist=use, flat=True))
+               except InvalidDependString:
+                       licenses = set()
+               licenses.discard('||')
+
+               accept_license = self._getPkgAcceptLicense(cpv, slot)
+
+               if accept_license:
+                       acceptable_licenses = set()
+                       for x in accept_license:
+                               if x == '*':
+                                       acceptable_licenses.update(licenses)
+                               elif x == '-*':
+                                       acceptable_licenses.clear()
+                               elif x[:1] == '-':
+                                       acceptable_licenses.discard(x[1:])
+                               elif x in licenses:
+                                       acceptable_licenses.add(x)
+
+                       licenses = acceptable_licenses
+               return ' '.join(sorted(licenses))
+
+       def getMissingLicenses(self, cpv, use, lic, slot):
+               """
+               Take a LICENSE string and return a list any licenses that the user may
+               may need to accept for the given package.  The returned list will not
+               contain any licenses that have already been accepted.  This method
+               can throw an InvalidDependString exception.
+
+               @param cpv: The package name (for package.license support)
+               @type cpv: String
+               @param use: "USE" from the cpv's metadata
+               @type use: String
+               @param lic: "LICENSE" from the cpv's metadata
+               @type lic: String
+               @param slot: "SLOT" from the cpv's metadata
+               @type slot: String
+               @rtype: List
+               @return: A list of licenses that have not been accepted.
+               """
+
+               licenses = set(use_reduce(lic, matchall=1, flat=True))
+               licenses.discard('||')
+
+               acceptable_licenses = set()
+               for x in self._getPkgAcceptLicense(cpv, slot):
+                       if x == '*':
+                               acceptable_licenses.update(licenses)
+                       elif x == '-*':
+                               acceptable_licenses.clear()
+                       elif x[:1] == '-':
+                               acceptable_licenses.discard(x[1:])
+                       else:
+                               acceptable_licenses.add(x)
+
+               license_str = lic
+               if "?" in license_str:
+                       use = use.split()
+               else:
+                       use = []
+
+               license_struct = use_reduce(license_str, uselist=use, opconvert=True)
+               return self._getMaskedLicenses(license_struct, acceptable_licenses)
+
+       def _getMaskedLicenses(self, license_struct, acceptable_licenses):
+               if not license_struct:
+                       return []
+               if license_struct[0] == "||":
+                       ret = []
+                       for element in license_struct[1:]:
+                               if isinstance(element, list):
+                                       if element:
+                                               tmp = self._getMaskedLicenses(element, acceptable_licenses)
+                                               if not tmp:
+                                                       return []
+                                               ret.extend(tmp)
+                               else:
+                                       if element in acceptable_licenses:
+                                               return []
+                                       ret.append(element)
+                       # Return all masked licenses, since we don't know which combination
+                       # (if any) the user will decide to unmask.
+                       return ret
+
+               ret = []
+               for element in license_struct:
+                       if isinstance(element, list):
+                               if element:
+                                       ret.extend(self._getMaskedLicenses(element,
+                                               acceptable_licenses))
+                       else:
+                               if element not in acceptable_licenses:
+                                       ret.append(element)
+               return ret
+
+       def set_accept_license_str(self, accept_license_str):
+               if accept_license_str != self._accept_license_str:
+                       self._accept_license_str = accept_license_str
+                       self._accept_license = tuple(self.expandLicenseTokens(accept_license_str.split()))
diff --git a/pym/portage/package/ebuild/_config/__init__.py b/pym/portage/package/ebuild/_config/__init__.py
new file mode 100644 (file)
index 0000000..21a391a
--- /dev/null
@@ -0,0 +1,2 @@
+# Copyright 2010 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
diff --git a/pym/portage/package/ebuild/_config/helper.py b/pym/portage/package/ebuild/_config/helper.py
new file mode 100644 (file)
index 0000000..00e2dfa
--- /dev/null
@@ -0,0 +1,42 @@
+# Copyright 2010 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+__all__ = (
+       'ordered_by_atom_specificity',
+)
+
+from portage.dep import best_match_to_list
+
+def ordered_by_atom_specificity(cpdict, pkg):
+       """
+       Return a list of matched values from the given cpdict,
+       in ascending order by atom specificity. The rationale
+       for this order is that package.* config files are
+       typically written in ChangeLog like fashion, so it's
+       most friendly if the order that the atoms are written
+       does not matter. Therefore, settings from more specific
+       atoms override those of less specific atoms. Without
+       this behavior, settings from relatively unspecific atoms
+       would (somewhat confusingly) override the settings of
+       more specific atoms, requiring people to make adjustments
+       to the order that atoms are listed in the config file in
+       order to achieve desired results (and thus corrupting
+       the ChangeLog like ordering of the file).
+       """
+
+       results = []
+       keys = list(cpdict)
+
+       while keys:
+               bestmatch = best_match_to_list(pkg, keys)
+               if bestmatch:
+                       keys.remove(bestmatch)
+                       results.append(cpdict[bestmatch])
+               else:
+                       break
+
+       if results:
+               # reverse, so the most specific atoms come last
+               results.reverse()
+
+       return results
index d49b23552f09a0acedc0b61ec7832b1fe34c80d7..31516665918de8896e10603b26bb51b1c4eb1d08 100644 (file)
@@ -31,7 +31,7 @@ from portage.const import CACHE_PATH, CUSTOM_PROFILE_PATH, \
 from portage.dbapi import dbapi
 from portage.dbapi.porttree import portdbapi
 from portage.dbapi.vartree import vartree
-from portage.dep import Atom, best_match_to_list, \
+from portage.dep import Atom, \
        isvalidatom, match_from_list, \
        remove_slot, use_reduce
 from portage.eapi import eapi_exports_AA, eapi_supports_prefix, eapi_exports_replace_vars
@@ -47,6 +47,9 @@ from portage.util import ensure_dirs, getconfig, grabdict, \
        writemsg, writemsg_level
 from portage.versions import catpkgsplit, catsplit, cpv_getkey
 
+from portage.package.ebuild._config.LicenseManager import LicenseManager
+from portage.package.ebuild._config.helper import ordered_by_atom_specificity
+
 if sys.hexversion >= 0x3000000:
        basestring = str
 
@@ -95,40 +98,6 @@ def best_from_dict(key, top_dict, key_order, EmptyOnError=1, FullCopy=1, AllowEm
        else:
                raise KeyError("Key not found in list; '%s'" % key)
 
-def _ordered_by_atom_specificity(cpdict, pkg):
-       """
-       Return a list of matched values from the given cpdict,
-       in ascending order by atom specificity. The rationale
-       for this order is that package.* config files are
-       typically written in ChangeLog like fashion, so it's
-       most friendly if the order that the atoms are written
-       does not matter. Therefore, settings from more specific
-       atoms override those of less specific atoms. Without
-       this behavior, settings from relatively unspecific atoms
-       would (somewhat confusingly) override the settings of
-       more specific atoms, requiring people to make adjustments
-       to the order that atoms are listed in the config file in
-       order to achieve desired results (and thus corrupting
-       the ChangeLog like ordering of the file).
-       """
-
-       results = []
-       keys = list(cpdict)
-
-       while keys:
-               bestmatch = best_match_to_list(pkg, keys)
-               if bestmatch:
-                       keys.remove(bestmatch)
-                       results.append(cpdict[bestmatch])
-               else:
-                       break
-
-       if results:
-               # reverse, so the most specific atoms come last
-               results.reverse()
-
-       return results
-
 class _features_set(object):
        """
        Provides relevant set operations needed for access and modification of
@@ -190,7 +159,6 @@ class _features_set(object):
                        self._features.remove(k)
                        self._sync_env_var()
 
-
 def _lazy_iuse_regex(iuse_implicit):
        """
        The PORTAGE_IUSE value is lazily evaluated since re.escape() is slow
@@ -402,7 +370,6 @@ class config(object):
 
        _environ_filter = frozenset(_environ_filter)
 
-       _undef_lic_groups = set()
        _default_globals = (
                ('ACCEPT_LICENSE',           '* -@EULA'),
                ('ACCEPT_PROPERTIES',        '*'),
@@ -460,9 +427,7 @@ class config(object):
                self.modifiedkeys = []
                self.uvlist = []
                self._accept_chost_re = None
-               self._accept_license = None
-               self._accept_license_str = None
-               self._license_groups = {}
+               self._license_manager = LicenseManager()
                self._accept_properties = None
                self._features_overrides = []
 
@@ -553,9 +518,7 @@ class config(object):
                        self.features._features = copy.deepcopy(clone.features._features)
                        self._features_overrides = copy.deepcopy(clone._features_overrides)
 
-                       self._accept_license = copy.deepcopy(clone._accept_license)
-                       self._plicensedict = copy.deepcopy(clone._plicensedict)
-                       self._license_groups = copy.deepcopy(clone._license_groups)
+                       self._license_manager = LicenseManager(clone._license_manager)
                        self._accept_properties = copy.deepcopy(clone._accept_properties)
                        self._ppropertiesdict = copy.deepcopy(clone._ppropertiesdict)
                        self._penvdict = copy.deepcopy(clone._penvdict)
@@ -968,7 +931,6 @@ class config(object):
 
                        self.pusedict = portage.dep.ExtendedAtomDict(dict)
                        self.pkeywordsdict = portage.dep.ExtendedAtomDict(dict)
-                       self._plicensedict = portage.dep.ExtendedAtomDict(dict)
                        self._ppropertiesdict = portage.dep.ExtendedAtomDict(dict)
                        self._penvdict = portage.dep.ExtendedAtomDict(dict)
                        self.punmaskdict = portage.dep.ExtendedAtomDict(list)
@@ -1053,17 +1015,10 @@ class config(object):
                                        self.pkeywordsdict.setdefault(k.cp, {})[k] = v
 
                                #package.license
-                               licdict = grabdict_package(os.path.join(
-                                       abs_user_config, "package.license"), recursive=1, allow_wildcard=True)
-                               v = licdict.pop("*/*", None)
-                               if v is not None:
-                                       if "ACCEPT_LICENSE" in self.configdict["conf"]:
-                                               self.configdict["conf"]["ACCEPT_LICENSE"] += " " + " ".join(v)
-                                       else:
-                                               self.configdict["conf"]["ACCEPT_LICENSE"] = " ".join(v)
-                               for k, v in licdict.items():
-                                       self._plicensedict.setdefault(k.cp, {})[k] = \
-                                               self.expandLicenseTokens(v)
+                               self._license_manager.read_config_files(abs_user_config)
+                               self.configdict["conf"]["ACCEPT_LICENSE"] = \
+                                       self._license_manager.extract_global_changes(\
+                                               self.configdict["conf"].get("ACCEPT_LICENSE", ""))
 
                                #package.properties
                                propdict = grabdict_package(os.path.join(
@@ -1196,11 +1151,7 @@ class config(object):
                                        self.pprovideddict[mycatpkg]=[x]
 
                        # parse licensegroups
-                       license_groups = self._license_groups
-                       for x in locations:
-                               for k, v in grabdict(
-                                       os.path.join(x, "license_groups")).items():
-                                       license_groups.setdefault(k, []).extend(v)
+                       self._license_manager.parse_license_groups(locations)
 
                        # reasonable defaults; this is important as without USE_ORDER,
                        # USE will always be "" (nothing set)!
@@ -1305,49 +1256,7 @@ class config(object):
                """ Take a token from ACCEPT_LICENSE or package.license and expand it
                if it's a group token (indicated by @) or just return it if it's not a
                group.  If a group is negated then negate all group elements."""
-               expanded_tokens = []
-               for x in tokens:
-                       expanded_tokens.extend(self._expandLicenseToken(x, None))
-               return expanded_tokens
-
-       def _expandLicenseToken(self, token, traversed_groups):
-               negate = False
-               rValue = []
-               if token.startswith("-"):
-                       negate = True
-                       license_name = token[1:]
-               else:
-                       license_name = token
-               if not license_name.startswith("@"):
-                       rValue.append(token)
-                       return rValue
-               group_name = license_name[1:]
-               if traversed_groups is None:
-                       traversed_groups = set()
-               license_group = self._license_groups.get(group_name)
-               if group_name in traversed_groups:
-                       writemsg(_("Circular license group reference"
-                               " detected in '%s'\n") % group_name, noiselevel=-1)
-                       rValue.append("@"+group_name)
-               elif license_group:
-                       traversed_groups.add(group_name)
-                       for l in license_group:
-                               if l.startswith("-"):
-                                       writemsg(_("Skipping invalid element %s"
-                                               " in license group '%s'\n") % (l, group_name),
-                                               noiselevel=-1)
-                               else:
-                                       rValue.extend(self._expandLicenseToken(l, traversed_groups))
-               else:
-                       if self._license_groups and \
-                               group_name not in self._undef_lic_groups:
-                               self._undef_lic_groups.add(group_name)
-                               writemsg(_("Undefined license group '%s'\n") % group_name,
-                                       noiselevel=-1)
-                       rValue.append("@"+group_name)
-               if negate:
-                       rValue = ["-" + token for token in rValue]
-               return rValue
+               return self._license_manager.expandLicenseTokens(tokens)
 
        def validate(self):
                """Validate miscellaneous settings and display warnings if necessary.
@@ -1498,41 +1407,12 @@ class config(object):
                        use = self.built_use
                        if use is None:
                                use = frozenset(settings['PORTAGE_USE'].split())
-                       values['ACCEPT_LICENSE'] = self._accept_license(use, settings)
+
+                       values['ACCEPT_LICENSE'] = settings._license_manager.get_prunned_accept_license( \
+                               settings.mycpv, use, settings['LICENSE'], settings['SLOT'])
                        values['PORTAGE_RESTRICT'] = self._restrict(use, settings)
                        return values
 
-               def _accept_license(self, use, settings):
-                       """
-                       Generate a pruned version of ACCEPT_LICENSE, by intersection with
-                       LICENSE. This is required since otherwise ACCEPT_LICENSE might be
-                       too big (bigger than ARG_MAX), causing execve() calls to fail with
-                       E2BIG errors as in bug #262647.
-                       """
-                       try:
-                               licenses = set(use_reduce(settings['LICENSE'], uselist=use, flat=True))
-                       except InvalidDependString:
-                               licenses = set()
-                       licenses.discard('||')
-
-                       accept_license = settings._getPkgAcceptLicense(
-                               settings.mycpv, {'SLOT' : settings['SLOT']})
-
-                       if accept_license:
-                               acceptable_licenses = set()
-                               for x in accept_license:
-                                       if x == '*':
-                                               acceptable_licenses.update(licenses)
-                                       elif x == '-*':
-                                               acceptable_licenses.clear()
-                                       elif x[:1] == '-':
-                                               acceptable_licenses.discard(x[1:])
-                                       elif x in licenses:
-                                               acceptable_licenses.add(x)
-
-                               licenses = acceptable_licenses
-                       return ' '.join(sorted(licenses))
-
                def _restrict(self, use, settings):
                        try:
                                restrict = set(use_reduce(settings['RESTRICT'], uselist=use, flat=True))
@@ -1712,7 +1592,7 @@ class config(object):
                                defaults.append(self.make_defaults_use[i])
                        cpdict = pkgprofileuse_dict.get(cp)
                        if cpdict:
-                               pkg_defaults = _ordered_by_atom_specificity(cpdict, cpv_slot)
+                               pkg_defaults = ordered_by_atom_specificity(cpdict, cpv_slot)
                                if pkg_defaults:
                                        defaults.extend(pkg_defaults)
                defaults = " ".join(defaults)
@@ -1733,7 +1613,7 @@ class config(object):
                self.puse = ""
                cpdict = self.pusedict.get(cp)
                if cpdict:
-                       puse_matches = _ordered_by_atom_specificity(cpdict, cpv_slot)
+                       puse_matches = ordered_by_atom_specificity(cpdict, cpv_slot)
                        if puse_matches:
                                puse_list = []
                                for x in puse_matches:
@@ -1754,7 +1634,7 @@ class config(object):
                self._penv = []
                cpdict = self._penvdict.get(cp)
                if cpdict:
-                       penv_matches = _ordered_by_atom_specificity(cpdict, cpv_slot)
+                       penv_matches = ordered_by_atom_specificity(cpdict, cpv_slot)
                        if penv_matches:
                                for x in penv_matches:
                                        self._penv.extend(x)
@@ -1967,7 +1847,7 @@ class config(object):
                                usemask.append(self.usemask_list[i])
                        cpdict = pusemask_dict.get(cp)
                        if cpdict:
-                               pkg_usemask = _ordered_by_atom_specificity(cpdict, pkg)
+                               pkg_usemask = ordered_by_atom_specificity(cpdict, pkg)
                                if pkg_usemask:
                                        usemask.extend(pkg_usemask)
                return set(stack_lists(usemask, incremental=True))
@@ -1982,7 +1862,7 @@ class config(object):
                                useforce.append(self.useforce_list[i])
                        cpdict = puseforce_dict.get(cp)
                        if cpdict:
-                               pkg_useforce = _ordered_by_atom_specificity(cpdict, pkg)
+                               pkg_useforce = ordered_by_atom_specificity(cpdict, pkg)
                                if pkg_useforce:
                                        useforce.extend(pkg_useforce)
                return set(stack_lists(useforce, incremental=True))
@@ -2049,7 +1929,7 @@ class config(object):
                for pkeywords_dict in self._pkeywords_list:
                        cpdict = pkeywords_dict.get(cp)
                        if cpdict:
-                               pkg_keywords = _ordered_by_atom_specificity(cpdict, pkg)
+                               pkg_keywords = ordered_by_atom_specificity(cpdict, pkg)
                                if pkg_keywords:
                                        keywords.extend(pkg_keywords)
                return stack_lists(keywords, incremental=True)
@@ -2089,7 +1969,7 @@ class config(object):
                                cpdict = d.get(cp)
                                if cpdict:
                                        pkg_accept_keywords = \
-                                               _ordered_by_atom_specificity(cpdict, cpv_slot)
+                                               ordered_by_atom_specificity(cpdict, cpv_slot)
                                        if pkg_accept_keywords:
                                                for x in pkg_accept_keywords:
                                                        if not x:
@@ -2101,7 +1981,7 @@ class config(object):
                if pkgdict:
                        cpv_slot = "%s:%s" % (cpv, metadata["SLOT"])
                        pkg_accept_keywords = \
-                               _ordered_by_atom_specificity(pkgdict, cpv_slot)
+                               ordered_by_atom_specificity(pkgdict, cpv_slot)
                        if pkg_accept_keywords:
                                for x in pkg_accept_keywords:
                                        pgroups.extend(x)
@@ -2152,22 +2032,6 @@ class config(object):
                        missing = mygroups
                return missing
 
-       def _getPkgAcceptLicense(self, cpv, metadata):
-               """
-               Get an ACCEPT_LICENSE list, accounting for package.license.
-               """
-               accept_license = self._accept_license
-               cp = cpv_getkey(cpv)
-               cpdict = self._plicensedict.get(cp)
-               if cpdict:
-                       cpv_slot = "%s:%s" % (cpv, metadata["SLOT"])
-                       plicence_list = _ordered_by_atom_specificity(cpdict, cpv_slot)
-                       if plicence_list:
-                               accept_license = list(self._accept_license)
-                               for x in plicence_list:
-                                       accept_license.extend(x)
-               return accept_license
-
        def _getMissingLicenses(self, cpv, metadata):
                """
                Take a LICENSE string and return a list any licenses that the user may
@@ -2182,61 +2046,8 @@ class config(object):
                @rtype: List
                @return: A list of licenses that have not been accepted.
                """
-
-
-               licenses = set(use_reduce(metadata["LICENSE"], matchall=1, flat=True))
-               licenses.discard('||')
-
-               acceptable_licenses = set()
-               for x in self._getPkgAcceptLicense(cpv, metadata):
-                       if x == '*':
-                               acceptable_licenses.update(licenses)
-                       elif x == '-*':
-                               acceptable_licenses.clear()
-                       elif x[:1] == '-':
-                               acceptable_licenses.discard(x[1:])
-                       else:
-                               acceptable_licenses.add(x)
-
-               license_str = metadata["LICENSE"]
-               if "?" in license_str:
-                       use = metadata["USE"].split()
-               else:
-                       use = []
-
-               license_struct = use_reduce(license_str, uselist=use, opconvert=True)
-               return self._getMaskedLicenses(license_struct, acceptable_licenses)
-
-       def _getMaskedLicenses(self, license_struct, acceptable_licenses):
-               if not license_struct:
-                       return []
-               if license_struct[0] == "||":
-                       ret = []
-                       for element in license_struct[1:]:
-                               if isinstance(element, list):
-                                       if element:
-                                               tmp = self._getMaskedLicenses(element, acceptable_licenses)
-                                               if not tmp:
-                                                       return []
-                                               ret.extend(tmp)
-                               else:
-                                       if element in acceptable_licenses:
-                                               return []
-                                       ret.append(element)
-                       # Return all masked licenses, since we don't know which combination
-                       # (if any) the user will decide to unmask.
-                       return ret
-
-               ret = []
-               for element in license_struct:
-                       if isinstance(element, list):
-                               if element:
-                                       ret.extend(self._getMaskedLicenses(element,
-                                               acceptable_licenses))
-                       else:
-                               if element not in acceptable_licenses:
-                                       ret.append(element)
-               return ret
+               return self._license_manager.getMissingLicenses( \
+                       cpv, metadata["USE"], metadata["LICENSE"], metadata["SLOT"])
 
        def _getMissingProperties(self, cpv, metadata):
                """
@@ -2257,7 +2068,7 @@ class config(object):
                cpdict = self._ppropertiesdict.get(cp)
                if cpdict:
                        cpv_slot = "%s:%s" % (cpv, metadata["SLOT"])
-                       pproperties_list = _ordered_by_atom_specificity(cpdict, cpv_slot)
+                       pproperties_list = ordered_by_atom_specificity(cpdict, cpv_slot)
                        if pproperties_list:
                                accept_properties = list(self._accept_properties)
                                for x in pproperties_list:
@@ -2474,12 +2285,10 @@ class config(object):
                        mysplit = self._prune_incremental(mysplit)
                        accept_license_str = ' '.join(mysplit)
                        self.configlist[-1]['ACCEPT_LICENSE'] = accept_license_str
-                       if accept_license_str != self._accept_license_str:
-                               self._accept_license_str = accept_license_str
-                               self._accept_license = tuple(self.expandLicenseTokens(mysplit))
+                       self._license_manager.set_accept_license_str(accept_license_str)
                else:
                        # repoman will accept any license
-                       self._accept_license = ('*',)
+                       self._license_manager.set_accept_license_str("*")
 
                # ACCEPT_PROPERTIES works like ACCEPT_LICENSE, without groups
                if self.local_config: