getmaskingreason: EAPI metadata safety
[portage.git] / pym / portage / package / ebuild / getmaskingreason.py
1 # Copyright 2010-2011 Gentoo Foundation
2 # Distributed under the terms of the GNU General Public License v2
3
4 __all__ = ['getmaskingreason']
5
6 import portage
7 from portage import os
8 from portage.const import USER_CONFIG_PATH
9 from portage.dep import Atom, match_from_list, _slot_separator, _repo_separator
10 from portage.exception import InvalidAtom
11 from portage.localization import _
12 from portage.repository.config import _gen_valid_repo
13 from portage.util import grablines, normalize_path
14 from portage.versions import catpkgsplit
15 from _emerge.Package import Package
16
17 def getmaskingreason(mycpv, metadata=None, settings=None,
18         portdb=None, return_location=False, myrepo=None):
19         """
20         If specified, the myrepo argument is assumed to be valid. This
21         should be a safe assumption since portdbapi methods always
22         return valid repo names and valid "repository" metadata from
23         aux_get.
24         """
25         if settings is None:
26                 settings = portage.settings
27         if portdb is None:
28                 portdb = portage.portdb
29         mysplit = catpkgsplit(mycpv)
30         if not mysplit:
31                 raise ValueError(_("invalid CPV: %s") % mycpv)
32
33         if metadata is None:
34                 db_keys = list(portdb._aux_cache_keys)
35                 try:
36                         metadata = dict(zip(db_keys,
37                                 portdb.aux_get(mycpv, db_keys, myrepo=myrepo)))
38                 except KeyError:
39                         if not portdb.cpv_exists(mycpv):
40                                 raise
41                 else:
42                         if myrepo is None:
43                                 myrepo = _gen_valid_repo(metadata["repository"])
44
45         elif myrepo is None:
46                 myrepo = metadata.get("repository")
47                 if myrepo is not None:
48                         myrepo = _gen_valid_repo(metadata["repository"])
49
50         if metadata is not None and \
51                 not portage.eapi_is_supported(metadata["EAPI"]):
52                 # Return early since otherwise we might produce invalid
53                 # results given that the EAPI is not supported. Also,
54                 # metadata is mostly useless in this case since it doesn't
55                 # contain essential things like SLOT.
56                 if return_location:
57                         return (None, None)
58                 else:
59                         return None
60
61         # Sometimes we can't access SLOT or repository due to corruption.
62         pkg = mycpv
63         if metadata is not None:
64                 pkg = "".join((mycpv, _slot_separator, metadata["SLOT"]))
65         # At this point myrepo should be None, a valid name, or
66         # Package.UNKNOWN_REPO which we ignore.
67         if myrepo is not None and myrepo != Package.UNKNOWN_REPO:
68                 pkg = "".join((pkg, _repo_separator, myrepo))
69         cpv_slot_list = [pkg]
70
71         mycp=mysplit[0]+"/"+mysplit[1]
72
73         # XXX- This is a temporary duplicate of code from the config constructor.
74         locations = [os.path.join(settings["PORTDIR"], "profiles")]
75         locations.extend(settings.profiles)
76         for ov in settings["PORTDIR_OVERLAY"].split():
77                 profdir = os.path.join(normalize_path(ov), "profiles")
78                 if os.path.isdir(profdir):
79                         locations.append(profdir)
80         locations.append(os.path.join(settings["PORTAGE_CONFIGROOT"],
81                 USER_CONFIG_PATH))
82         locations.reverse()
83         pmasklists = []
84         for profile in locations:
85                 pmask_filename = os.path.join(profile, "package.mask")
86                 pmasklists.append((pmask_filename, grablines(pmask_filename, recursive=1)))
87
88         pmaskdict = settings._mask_manager._pmaskdict
89         if mycp in pmaskdict:
90                 for x in pmaskdict[mycp]:
91                         if match_from_list(x, cpv_slot_list):
92                                 x = x.without_repo
93                                 for pmask in pmasklists:
94                                         comment = ""
95                                         comment_valid = -1
96                                         pmask_filename = pmask[0]
97                                         for i in range(len(pmask[1])):
98                                                 l = pmask[1][i].strip()
99                                                 try:
100                                                         l_atom = Atom(l, allow_repo=True,
101                                                                 allow_wildcard=True).without_repo
102                                                 except InvalidAtom:
103                                                         l_atom = None
104                                                 if l == "":
105                                                         comment = ""
106                                                         comment_valid = -1
107                                                 elif l[0] == "#":
108                                                         comment += (l+"\n")
109                                                         comment_valid = i + 1
110                                                 elif l_atom == x:
111                                                         if comment_valid != i:
112                                                                 comment = ""
113                                                         if return_location:
114                                                                 return (comment, pmask_filename)
115                                                         else:
116                                                                 return comment
117                                                 elif comment_valid != -1:
118                                                         # Apparently this comment applies to multiple masks, so
119                                                         # it remains valid until a blank line is encountered.
120                                                         comment_valid += 1
121         if return_location:
122                 return (None, None)
123         else:
124                 return None