1 # Copyright 2010 Gentoo Foundation
2 # Distributed under the terms of the GNU General Public License v2
8 from itertools import chain
10 from portage.dep import ExtendedAtomDict, match_from_list
11 from portage.util import grabfile_package, stack_lists
12 from portage.versions import cpv_getkey
14 class MaskManager(object):
16 def __init__(self, pmask_locations, abs_user_config,
17 user_config=True, strict_umatched_removal=False):
18 self._punmaskdict = ExtendedAtomDict(list)
19 self._pmaskdict = ExtendedAtomDict(list)
21 repo_profiles, profiles = pmask_locations
23 #Read profile/package.mask form every repo. Stack them immediately
24 #to make sure that -atoms don't effect other repos.
25 repo_pkgmasklines = []
26 repo_pkgunmasklines = []
27 for x in repo_profiles:
28 repo_pkgmasklines.append(stack_lists([grabfile_package(
29 os.path.join(x, "package.mask"), recursive=1, remember_source_file=True, verify_eapi=True)], \
30 incremental=1, remember_source_file=True,
31 warn_for_unmatched_removal=True,
32 strict_warn_for_unmatched_removal=strict_umatched_removal))
33 repo_pkgunmasklines.append(stack_lists([grabfile_package(
34 os.path.join(x, "package.unmask"), recursive=1, remember_source_file=True, verify_eapi=True)], \
35 incremental=1, remember_source_file=True,
36 warn_for_unmatched_removal=True,
37 strict_warn_for_unmatched_removal=strict_umatched_removal))
38 repo_pkgmasklines = list(chain.from_iterable(repo_pkgmasklines))
39 repo_pkgunmasklines = list(chain.from_iterable(repo_pkgunmasklines))
41 #Read package.mask form the user's profile. Stack them in the end
42 #to allow profiles to override masks from their parent profiles.
43 profile_pkgmasklines = []
44 profile_pkgunmasklines = []
46 profile_pkgmasklines.append(grabfile_package(
47 os.path.join(x, "package.mask"), recursive=1, remember_source_file=True, verify_eapi=True))
48 profile_pkgunmasklines.append(grabfile_package(
49 os.path.join(x, "package.unmask"), recursive=1, remember_source_file=True, verify_eapi=True))
50 profile_pkgmasklines = stack_lists(profile_pkgmasklines, incremental=1, \
51 remember_source_file=True, warn_for_unmatched_removal=True,
52 strict_warn_for_unmatched_removal=strict_umatched_removal)
53 profile_pkgunmasklines = stack_lists(profile_pkgunmasklines, incremental=1, \
54 remember_source_file=True, warn_for_unmatched_removal=True,
55 strict_warn_for_unmatched_removal=strict_umatched_removal)
57 #Read /etc/portage/package.mask. Don't stack it to allow the user to
58 #remove mask atoms from everywhere with -atoms.
59 user_pkgmasklines = []
60 user_pkgunmasklines = []
62 user_pkgmasklines = grabfile_package(
63 os.path.join(abs_user_config, "package.mask"), recursive=1, \
64 allow_wildcard=True, remember_source_file=True, verify_eapi=False)
65 user_pkgunmasklines = grabfile_package(
66 os.path.join(abs_user_config, "package.unmask"), recursive=1, \
67 allow_wildcard=True, remember_source_file=True, verify_eapi=False)
69 #Stack everything together. At this point, only user_pkgmasklines may contain -atoms.
70 #Don't warn for unmatched -atoms here, since we don't do it for any other user config file.
71 pkgmasklines = stack_lists([repo_pkgmasklines, profile_pkgmasklines, user_pkgmasklines], \
72 incremental=1, remember_source_file=True, warn_for_unmatched_removal=False)
73 pkgunmasklines = stack_lists([repo_pkgunmasklines, profile_pkgunmasklines, user_pkgunmasklines], \
74 incremental=1, remember_source_file=True, warn_for_unmatched_removal=False)
76 for x, source_file in pkgmasklines:
77 self._pmaskdict.setdefault(x.cp, []).append(x)
79 for x, source_file in pkgunmasklines:
80 self._punmaskdict.setdefault(x.cp, []).append(x)
82 for d in (self._pmaskdict, self._punmaskdict):
83 for k, v in d.items():
86 def getMaskAtom(self, cpv, slot):
88 Take a package and return a matching package.mask atom, or None if no
89 such atom exists or it has been cancelled by package.unmask. PROVIDE
90 is not checked, so atoms will not be found for old-style virtuals.
92 @param cpv: The package name
94 @param slot: The package's slot
97 @return: An matching atom string or None if one is not found.
101 mask_atoms = self._pmaskdict.get(cp)
103 pkg_list = ["%s:%s" % (cpv, slot)]
104 unmask_atoms = self._punmaskdict.get(cp)
106 if not match_from_list(x, pkg_list):
109 for y in unmask_atoms:
110 if match_from_list(y, pkg_list):