---
.../package/ebuild/_config/InstallMaskManager.py | 59 ++++++++++++++++++++++
pym/portage/package/ebuild/config.py | 34 ++++++++++++-
pym/portage/util/configparser.py | 19 ++++++-
3 files changed, 110 insertions(+), 2 deletions(-)
create mode 100644 pym/portage/package/ebuild/_config/InstallMaskManager.py
diff --git a/pym/portage/package/ebuild/_config/InstallMaskManager.py
b/pym/portage/package/ebuild/_config/InstallMaskManager.py
new file mode 100644
index 0000000..96cb539
--- /dev/null
+++ b/pym/portage/package/ebuild/_config/InstallMaskManager.py
@@ -0,0 +1,59 @@
+# Copyright 2010-2016 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+__all__ = (
+ 'InstallMaskManager',
+)
+
+import sys
+
+from portage import os
+from portage.localization import _
+from portage.util import writemsg
+from portage.util.configparser import (SafeConfigParser, ConfigParserError,
+ MultiValueConfigParserDict, read_configs)
+
+
+class InstallMaskManager(object):
+ def __init__(self, repositories, abs_user_config, user_config=True):
+ self._groups = {}
+
+ # read repository defined groups
+ self._read_config_from_repositories(repositories)
+
+ if user_config:
+ self._read_config(os.path.join(abs_user_config,
'install-mask.conf'), True)
+
+ def _read_config_from_repositories(self, repositories):
+ for r in repositories.repos_with_profiles():
+ self._read_config(os.path.join(r.location, 'metadata',
'install-mask.conf'))
+
+ def _read_config(self, path, is_user_config=False):
+ # use separate parsers to detect collisions properly
+ cfp_kwargs = {}
+ if sys.hexversion >= 0x03020000:
+ cfp_kwargs['strict'] = False
+ parser = SafeConfigParser(dict_type=MultiValueConfigParserDict,
+ **cfp_kwargs)
+ try:
+ read_configs(parser, [path])
+ except ConfigParserError as e:
+ writemsg(
+ _("!!! Error while reading %s: %s\n") % (path,
e),
+ noiselevel=-1)
+ return
+
+ for sname in parser.sections():
+ if not is_user_config and sname in self._groups:
+ writemsg(
+ _("!!! Error while reading %s:
duplicate group %s found\n") % (path, sname),
+ noiselevel=-1)
+ continue
+ if not parser.has_option(sname, 'path'):
+ continue
+
+ paths = parser.get(sname, 'path').split('\n')
+ self._groups[sname] = paths
+
+ def expand_group(self, gname):
+ return self._groups[gname]
diff --git a/pym/portage/package/ebuild/config.py
b/pym/portage/package/ebuild/config.py
index 9d13703..dfbd7f2 100644
--- a/pym/portage/package/ebuild/config.py
+++ b/pym/portage/package/ebuild/config.py
@@ -60,6 +60,7 @@ from portage.package.ebuild._config.features_set import
features_set
from portage.package.ebuild._config.KeywordsManager import KeywordsManager
from portage.package.ebuild._config.LicenseManager import LicenseManager
from portage.package.ebuild._config.UseManager import UseManager
+from portage.package.ebuild._config.InstallMaskManager import
InstallMaskManager
from portage.package.ebuild._config.LocationsManager import LocationsManager
from portage.package.ebuild._config.MaskManager import MaskManager
from portage.package.ebuild._config.VirtualsManager import VirtualsManager
@@ -277,6 +278,7 @@ class config(object):
# force instantiation of lazy immutable objects when
cloning, so
# that they're not instantiated more than once
self._keywords_manager_obj = clone._keywords_manager
+ self._install_mask_manager_obj =
clone._install_mask_manager
self._mask_manager_obj = clone._mask_manager
# shared mutable attributes
@@ -329,6 +331,7 @@ class config(object):
else:
# lazily instantiated objects
self._keywords_manager_obj = None
+ self._install_mask_manager_obj = None
self._mask_manager_obj = None
self._virtuals_manager_obj = None
@@ -1032,6 +1035,15 @@ class config(object):
return self._keywords_manager_obj
@property
+ def _install_mask_manager(self):
+ if self._install_mask_manager_obj is None:
+ self._install_mask_manager_obj = InstallMaskManager(
+ self.repositories,
+ self._locations_manager.abs_user_config,
+ user_config=self.local_config)
+ return self._install_mask_manager_obj
+
+ @property
def _mask_manager(self):
if self._mask_manager_obj is None:
self._mask_manager_obj = MaskManager(self.repositories,
@@ -1774,7 +1786,8 @@ class config(object):
_eapi_cache.clear()
# Prepare the final value of INSTALL_MASK
- install_mask = self.get("INSTALL_MASK", "").split()
+ install_mask = list(self._replace_install_mask_groups(
+ self.get("INSTALL_MASK", "").split()))
if 'nodoc' in self.features:
install_mask.append("/usr/share/doc")
if 'noinfo' in self.features:
@@ -1782,6 +1795,25 @@ class config(object):
if 'noman' in self.features:
install_mask.append("/usr/share/man")
self.install_mask = install_mask
+ print(install_mask)
+
+ def _replace_install_mask_groups(self, vals):
+ for v in vals:
+ if v.startswith('@') or v.startswith('-@'):
+ neg = '-' if v.startswith('-') else ''
+ gname = v[2:] if neg else v[1:]
+ for p in self._expand_install_mask_group(gname):
+ yield '%s%s' % (neg, p)
+ else:
+ yield v
+
+ def _expand_install_mask_group(self, gname):
+ try:
+ return self._install_mask_manager.expand_group(gname)
+ except KeyError:
+ writemsg(_("!!! Undefined INSTALL_MASK group: '%s'!\n")
+ % gname, noiselevel=-1)
+ return ()
def _grab_pkg_env(self, penv, container, protected_keys=None):
if protected_keys is None:
diff --git a/pym/portage/util/configparser.py b/pym/portage/util/configparser.py
index c4c92a6..290bc5e 100644
--- a/pym/portage/util/configparser.py
+++ b/pym/portage/util/configparser.py
@@ -2,7 +2,8 @@
# Distributed under the terms of the GNU General Public License v2
__all__ = ['ConfigParserError', 'NoOptionError', 'ParsingError',
- 'RawConfigParser', 'SafeConfigParser', 'read_configs']
+ 'RawConfigParser', 'SafeConfigParser', 'read_configs',
+ 'MultiValueConfigParserDict']
# the following scary compatibility thing provides two classes:
# - SafeConfigParser that provides safe interpolation for values,
@@ -74,3 +75,19 @@ def read_configs(parser, paths):
read_file(p, **kwargs)
else:
raise TypeError("Unsupported type %r of element %r of
'paths' argument" % (type(p), p))
+
+
+class MultiValueConfigParserDict(dict):
+ """
+ A special variant of dict that stores all subsequent values assigned
+ to its keys as a list, and returns this list when retrieved. Meant
+ to be used with ConfigParser to process multi-key config files.
+ """
+
+ def __setitem__(self, k, v):
+ if isinstance(v, list):
+ if not k in self:
+ super(MultiValueConfigParserDict,
self).__setitem__(k, [])
+ self[k].extend(v)
+ else:
+ super(MultiValueConfigParserDict, self).__setitem__(k,
v)
--
2.8.3