1 |
--- |
2 |
.../package/ebuild/_config/InstallMaskManager.py | 59 ++++++++++++++++++++++ |
3 |
pym/portage/package/ebuild/config.py | 34 ++++++++++++- |
4 |
pym/portage/util/configparser.py | 19 ++++++- |
5 |
3 files changed, 110 insertions(+), 2 deletions(-) |
6 |
create mode 100644 pym/portage/package/ebuild/_config/InstallMaskManager.py |
7 |
|
8 |
diff --git a/pym/portage/package/ebuild/_config/InstallMaskManager.py b/pym/portage/package/ebuild/_config/InstallMaskManager.py |
9 |
new file mode 100644 |
10 |
index 0000000..96cb539 |
11 |
--- /dev/null |
12 |
+++ b/pym/portage/package/ebuild/_config/InstallMaskManager.py |
13 |
@@ -0,0 +1,59 @@ |
14 |
+# Copyright 2010-2016 Gentoo Foundation |
15 |
+# Distributed under the terms of the GNU General Public License v2 |
16 |
+ |
17 |
+__all__ = ( |
18 |
+ 'InstallMaskManager', |
19 |
+) |
20 |
+ |
21 |
+import sys |
22 |
+ |
23 |
+from portage import os |
24 |
+from portage.localization import _ |
25 |
+from portage.util import writemsg |
26 |
+from portage.util.configparser import (SafeConfigParser, ConfigParserError, |
27 |
+ MultiValueConfigParserDict, read_configs) |
28 |
+ |
29 |
+ |
30 |
+class InstallMaskManager(object): |
31 |
+ def __init__(self, repositories, abs_user_config, user_config=True): |
32 |
+ self._groups = {} |
33 |
+ |
34 |
+ # read repository defined groups |
35 |
+ self._read_config_from_repositories(repositories) |
36 |
+ |
37 |
+ if user_config: |
38 |
+ self._read_config(os.path.join(abs_user_config, 'install-mask.conf'), True) |
39 |
+ |
40 |
+ def _read_config_from_repositories(self, repositories): |
41 |
+ for r in repositories.repos_with_profiles(): |
42 |
+ self._read_config(os.path.join(r.location, 'metadata', 'install-mask.conf')) |
43 |
+ |
44 |
+ def _read_config(self, path, is_user_config=False): |
45 |
+ # use separate parsers to detect collisions properly |
46 |
+ cfp_kwargs = {} |
47 |
+ if sys.hexversion >= 0x03020000: |
48 |
+ cfp_kwargs['strict'] = False |
49 |
+ parser = SafeConfigParser(dict_type=MultiValueConfigParserDict, |
50 |
+ **cfp_kwargs) |
51 |
+ try: |
52 |
+ read_configs(parser, [path]) |
53 |
+ except ConfigParserError as e: |
54 |
+ writemsg( |
55 |
+ _("!!! Error while reading %s: %s\n") % (path, e), |
56 |
+ noiselevel=-1) |
57 |
+ return |
58 |
+ |
59 |
+ for sname in parser.sections(): |
60 |
+ if not is_user_config and sname in self._groups: |
61 |
+ writemsg( |
62 |
+ _("!!! Error while reading %s: duplicate group %s found\n") % (path, sname), |
63 |
+ noiselevel=-1) |
64 |
+ continue |
65 |
+ if not parser.has_option(sname, 'path'): |
66 |
+ continue |
67 |
+ |
68 |
+ paths = parser.get(sname, 'path').split('\n') |
69 |
+ self._groups[sname] = paths |
70 |
+ |
71 |
+ def expand_group(self, gname): |
72 |
+ return self._groups[gname] |
73 |
diff --git a/pym/portage/package/ebuild/config.py b/pym/portage/package/ebuild/config.py |
74 |
index 9d13703..dfbd7f2 100644 |
75 |
--- a/pym/portage/package/ebuild/config.py |
76 |
+++ b/pym/portage/package/ebuild/config.py |
77 |
@@ -60,6 +60,7 @@ from portage.package.ebuild._config.features_set import features_set |
78 |
from portage.package.ebuild._config.KeywordsManager import KeywordsManager |
79 |
from portage.package.ebuild._config.LicenseManager import LicenseManager |
80 |
from portage.package.ebuild._config.UseManager import UseManager |
81 |
+from portage.package.ebuild._config.InstallMaskManager import InstallMaskManager |
82 |
from portage.package.ebuild._config.LocationsManager import LocationsManager |
83 |
from portage.package.ebuild._config.MaskManager import MaskManager |
84 |
from portage.package.ebuild._config.VirtualsManager import VirtualsManager |
85 |
@@ -277,6 +278,7 @@ class config(object): |
86 |
# force instantiation of lazy immutable objects when cloning, so |
87 |
# that they're not instantiated more than once |
88 |
self._keywords_manager_obj = clone._keywords_manager |
89 |
+ self._install_mask_manager_obj = clone._install_mask_manager |
90 |
self._mask_manager_obj = clone._mask_manager |
91 |
|
92 |
# shared mutable attributes |
93 |
@@ -329,6 +331,7 @@ class config(object): |
94 |
else: |
95 |
# lazily instantiated objects |
96 |
self._keywords_manager_obj = None |
97 |
+ self._install_mask_manager_obj = None |
98 |
self._mask_manager_obj = None |
99 |
self._virtuals_manager_obj = None |
100 |
|
101 |
@@ -1032,6 +1035,15 @@ class config(object): |
102 |
return self._keywords_manager_obj |
103 |
|
104 |
@property |
105 |
+ def _install_mask_manager(self): |
106 |
+ if self._install_mask_manager_obj is None: |
107 |
+ self._install_mask_manager_obj = InstallMaskManager( |
108 |
+ self.repositories, |
109 |
+ self._locations_manager.abs_user_config, |
110 |
+ user_config=self.local_config) |
111 |
+ return self._install_mask_manager_obj |
112 |
+ |
113 |
+ @property |
114 |
def _mask_manager(self): |
115 |
if self._mask_manager_obj is None: |
116 |
self._mask_manager_obj = MaskManager(self.repositories, |
117 |
@@ -1774,7 +1786,8 @@ class config(object): |
118 |
_eapi_cache.clear() |
119 |
|
120 |
# Prepare the final value of INSTALL_MASK |
121 |
- install_mask = self.get("INSTALL_MASK", "").split() |
122 |
+ install_mask = list(self._replace_install_mask_groups( |
123 |
+ self.get("INSTALL_MASK", "").split())) |
124 |
if 'nodoc' in self.features: |
125 |
install_mask.append("/usr/share/doc") |
126 |
if 'noinfo' in self.features: |
127 |
@@ -1782,6 +1795,25 @@ class config(object): |
128 |
if 'noman' in self.features: |
129 |
install_mask.append("/usr/share/man") |
130 |
self.install_mask = install_mask |
131 |
+ print(install_mask) |
132 |
+ |
133 |
+ def _replace_install_mask_groups(self, vals): |
134 |
+ for v in vals: |
135 |
+ if v.startswith('@') or v.startswith('-@'): |
136 |
+ neg = '-' if v.startswith('-') else '' |
137 |
+ gname = v[2:] if neg else v[1:] |
138 |
+ for p in self._expand_install_mask_group(gname): |
139 |
+ yield '%s%s' % (neg, p) |
140 |
+ else: |
141 |
+ yield v |
142 |
+ |
143 |
+ def _expand_install_mask_group(self, gname): |
144 |
+ try: |
145 |
+ return self._install_mask_manager.expand_group(gname) |
146 |
+ except KeyError: |
147 |
+ writemsg(_("!!! Undefined INSTALL_MASK group: '%s'!\n") |
148 |
+ % gname, noiselevel=-1) |
149 |
+ return () |
150 |
|
151 |
def _grab_pkg_env(self, penv, container, protected_keys=None): |
152 |
if protected_keys is None: |
153 |
diff --git a/pym/portage/util/configparser.py b/pym/portage/util/configparser.py |
154 |
index c4c92a6..290bc5e 100644 |
155 |
--- a/pym/portage/util/configparser.py |
156 |
+++ b/pym/portage/util/configparser.py |
157 |
@@ -2,7 +2,8 @@ |
158 |
# Distributed under the terms of the GNU General Public License v2 |
159 |
|
160 |
__all__ = ['ConfigParserError', 'NoOptionError', 'ParsingError', |
161 |
- 'RawConfigParser', 'SafeConfigParser', 'read_configs'] |
162 |
+ 'RawConfigParser', 'SafeConfigParser', 'read_configs', |
163 |
+ 'MultiValueConfigParserDict'] |
164 |
|
165 |
# the following scary compatibility thing provides two classes: |
166 |
# - SafeConfigParser that provides safe interpolation for values, |
167 |
@@ -74,3 +75,19 @@ def read_configs(parser, paths): |
168 |
read_file(p, **kwargs) |
169 |
else: |
170 |
raise TypeError("Unsupported type %r of element %r of 'paths' argument" % (type(p), p)) |
171 |
+ |
172 |
+ |
173 |
+class MultiValueConfigParserDict(dict): |
174 |
+ """ |
175 |
+ A special variant of dict that stores all subsequent values assigned |
176 |
+ to its keys as a list, and returns this list when retrieved. Meant |
177 |
+ to be used with ConfigParser to process multi-key config files. |
178 |
+ """ |
179 |
+ |
180 |
+ def __setitem__(self, k, v): |
181 |
+ if isinstance(v, list): |
182 |
+ if not k in self: |
183 |
+ super(MultiValueConfigParserDict, self).__setitem__(k, []) |
184 |
+ self[k].extend(v) |
185 |
+ else: |
186 |
+ super(MultiValueConfigParserDict, self).__setitem__(k, v) |
187 |
-- |
188 |
2.8.3 |