getmaskingreason: handle UNKNOWN_REPO
[portage.git] / pym / portage / package / ebuild / getmaskingreason.py
index 000bb406ceaf55c309657254f6bdab811e3e900e..70a6bf2e611675055da15984eb4d12e8f849dfb4 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright 2010 Gentoo Foundation
+# Copyright 2010-2013 Gentoo Foundation
 # Distributed under the terms of the GNU General Public License v2
 
 __all__ = ['getmaskingreason']
@@ -6,12 +6,21 @@ __all__ = ['getmaskingreason']
 import portage
 from portage import os
 from portage.const import USER_CONFIG_PATH
-from portage.dep import match_from_list, _slot_separator, _repo_separator
+from portage.dep import Atom, match_from_list
+from portage.exception import InvalidAtom
 from portage.localization import _
+from portage.repository.config import _gen_valid_repo
 from portage.util import grablines, normalize_path
-from portage.versions import catpkgsplit
+from portage.versions import catpkgsplit, _pkg_str
 
-def getmaskingreason(mycpv, metadata=None, settings=None, portdb=None, return_location=False):
+def getmaskingreason(mycpv, metadata=None, settings=None,
+       portdb=None, return_location=False, myrepo=None):
+       """
+       If specified, the myrepo argument is assumed to be valid. This
+       should be a safe assumption since portdbapi methods always
+       return valid repo names and valid "repository" metadata from
+       aux_get.
+       """
        if settings is None:
                settings = portage.settings
        if portdb is None:
@@ -19,52 +28,88 @@ def getmaskingreason(mycpv, metadata=None, settings=None, portdb=None, return_lo
        mysplit = catpkgsplit(mycpv)
        if not mysplit:
                raise ValueError(_("invalid CPV: %s") % mycpv)
+
        if metadata is None:
                db_keys = list(portdb._aux_cache_keys)
                try:
-                       metadata = dict(zip(db_keys, portdb.aux_get(mycpv, db_keys, myrepo=metadata.get('repository'))))
+                       metadata = dict(zip(db_keys,
+                               portdb.aux_get(mycpv, db_keys, myrepo=myrepo)))
                except KeyError:
                        if not portdb.cpv_exists(mycpv):
                                raise
-       if metadata is None:
-               # Can't access SLOT due to corruption.
-               cpv_slot_list = [mycpv]
-       else:
-               pkg = "".join((mycpv, _slot_separator, metadata["SLOT"]))
-               if 'repository' in metadata:
-                       pkg = "".join((pkg, _repo_separator, metadata['repository']))
-               cpv_slot_list = [pkg]
-       mycp=mysplit[0]+"/"+mysplit[1]
+               else:
+                       if myrepo is None:
+                               myrepo = _gen_valid_repo(metadata["repository"])
+
+       elif myrepo is None:
+               myrepo = metadata.get("repository")
+               if myrepo is not None:
+                       myrepo = _gen_valid_repo(metadata["repository"])
+
+       if metadata is not None and \
+               not portage.eapi_is_supported(metadata["EAPI"]):
+               # Return early since otherwise we might produce invalid
+               # results given that the EAPI is not supported. Also,
+               # metadata is mostly useless in this case since it doesn't
+               # contain essential things like SLOT.
+               if return_location:
+                       return (None, None)
+               else:
+                       return None
+
+       # Sometimes we can't access SLOT or repository due to corruption.
+       pkg = mycpv
+       try:
+               pkg.slot
+       except AttributeError:
+               pkg = _pkg_str(mycpv, metadata=metadata, repo=myrepo)
+
+       cpv_slot_list = [pkg]
+
+       mycp = pkg.cp
 
-       # XXX- This is a temporary duplicate of code from the config constructor.
-       locations = [os.path.join(settings["PORTDIR"], "profiles")]
+       locations = []
+       if pkg.repo in settings.repositories:
+               for repo in settings.repositories[pkg.repo].masters + (settings.repositories[pkg.repo],):
+                       locations.append(os.path.join(repo.location, "profiles"))
        locations.extend(settings.profiles)
-       for ov in settings["PORTDIR_OVERLAY"].split():
-               profdir = os.path.join(normalize_path(ov), "profiles")
-               if os.path.isdir(profdir):
-                       locations.append(profdir)
        locations.append(os.path.join(settings["PORTAGE_CONFIGROOT"],
                USER_CONFIG_PATH))
        locations.reverse()
-       pmasklists = [(x, grablines(os.path.join(x, "package.mask"), recursive=1)) for x in locations]
+       pmasklists = []
+       for profile in locations:
+               pmask_filename = os.path.join(profile, "package.mask")
+               node = None
+               for l, recursive_filename in grablines(pmask_filename,
+                       recursive=1, remember_source_file=True):
+                       if node is None or node[0] != recursive_filename:
+                               node = (recursive_filename, [])
+                               pmasklists.append(node)
+                       node[1].append(l)
 
        pmaskdict = settings._mask_manager._pmaskdict
        if mycp in pmaskdict:
                for x in pmaskdict[mycp]:
                        if match_from_list(x, cpv_slot_list):
+                               x = x.without_repo
                                for pmask in pmasklists:
                                        comment = ""
                                        comment_valid = -1
-                                       pmask_filename = os.path.join(pmask[0], "package.mask")
+                                       pmask_filename = pmask[0]
                                        for i in range(len(pmask[1])):
                                                l = pmask[1][i].strip()
+                                               try:
+                                                       l_atom = Atom(l, allow_repo=True,
+                                                               allow_wildcard=True).without_repo
+                                               except InvalidAtom:
+                                                       l_atom = None
                                                if l == "":
                                                        comment = ""
                                                        comment_valid = -1
                                                elif l[0] == "#":
                                                        comment += (l+"\n")
                                                        comment_valid = i + 1
-                                               elif l == x:
+                                               elif l_atom == x:
                                                        if comment_valid != i:
                                                                comment = ""
                                                        if return_location:
@@ -72,7 +117,7 @@ def getmaskingreason(mycpv, metadata=None, settings=None, portdb=None, return_lo
                                                        else:
                                                                return comment
                                                elif comment_valid != -1:
-                                                       # Apparently this comment applies to muliple masks, so
+                                                       # Apparently this comment applies to multiple masks, so
                                                        # it remains valid until a blank line is encountered.
                                                        comment_valid += 1
        if return_location: