From 51df054e1b4480a896439f8d13ae52d6cd0ad8f6 Mon Sep 17 00:00:00 2001 From: Sebastian Luther Date: Fri, 27 Aug 2010 15:09:46 +0200 Subject: config: Add LocationsManager --- .../package/ebuild/_config/LocationsManager.py | 177 ++++++++++++++++++ pym/portage/package/ebuild/config.py | 198 ++++----------------- 2 files changed, 212 insertions(+), 163 deletions(-) create mode 100644 pym/portage/package/ebuild/_config/LocationsManager.py diff --git a/pym/portage/package/ebuild/_config/LocationsManager.py b/pym/portage/package/ebuild/_config/LocationsManager.py new file mode 100644 index 000000000..1fd462baa --- /dev/null +++ b/pym/portage/package/ebuild/_config/LocationsManager.py @@ -0,0 +1,177 @@ +# Copyright 2010 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 + +__all__ = ( + 'LocationsManager', +) + +import codecs +from portage import os, eapi_is_supported, _encodings, _unicode_encode +from portage.const import CUSTOM_PROFILE_PATH, GLOBAL_CONFIG_PATH, PROFILE_PATH, USER_CONFIG_PATH +from portage.dep import Atom +from portage.exception import DirectoryNotFound, InvalidAtom, ParseError +from portage.localization import _ +from portage.util import ensure_dirs, grabdict, grabfile, normalize_path, shlex_split, stack_dictlist, writemsg +from portage.versions import cpv_getkey + + +class LocationsManager(object): + + def __init__(self, config_root=None, eprefix=None, config_profile_path=None, local_config=True, \ + target_root=None): + self.user_profile_dir = None + self._local_repo_conf_path = None + self.eprefix = eprefix + self.config_root = config_root + self.target_root = target_root + + if self.eprefix is None: + self.eprefix = "" + + if self.config_root is None: + self.config_root = self.eprefix + os.sep + + self.config_root = normalize_path(os.path.abspath( + self.config_root)).rstrip(os.path.sep) + os.path.sep + + self._check_var_directory("PORTAGE_CONFIGROOT", self.config_root) + self.abs_user_config = os.path.join(self.config_root, USER_CONFIG_PATH) + + if not config_profile_path: + config_profile_path = \ + os.path.join(self.config_root, PROFILE_PATH) + if os.path.isdir(config_profile_path): + self.profile_path = config_profile_path + else: + config_profile_path = \ + os.path.join(self.abs_user_config, 'make.profile') + if os.path.isdir(config_profile_path): + self.profile_path = config_profile_path + else: + self.profile_path = None + else: + self.profile_path = config_profile_path + + + # The symlink might not exist or might not be a symlink. + self.profiles = [] + if self.profile_path is not None: + try: + self._addProfile(os.path.realpath(self.profile_path)) + except ParseError as e: + writemsg(_("!!! Unable to parse profile: '%s'\n") % \ + self.profile_path, noiselevel=-1) + writemsg("!!! ParseError: %s\n" % str(e), noiselevel=-1) + self.profiles = [] + + if local_config and self.profiles: + custom_prof = os.path.join( + self.config_root, CUSTOM_PROFILE_PATH) + if os.path.exists(custom_prof): + self.user_profile_dir = custom_prof + self.profiles.append(custom_prof) + del custom_prof + + self.profiles = tuple(self.profiles) + + def _check_var_directory(self, varname, var): + if not os.path.isdir(var): + writemsg(_("!!! Error: %s='%s' is not a directory. " + "Please correct this.\n") % (varname, var), + noiselevel=-1) + raise DirectoryNotFound(var) + + def _addProfile(self, currentPath): + parentsFile = os.path.join(currentPath, "parent") + eapi_file = os.path.join(currentPath, "eapi") + try: + eapi = codecs.open(_unicode_encode(eapi_file, + encoding=_encodings['fs'], errors='strict'), + mode='r', encoding=_encodings['content'], errors='replace' + ).readline().strip() + except IOError: + pass + else: + if not eapi_is_supported(eapi): + raise ParseError(_( + "Profile contains unsupported " + "EAPI '%s': '%s'") % \ + (eapi, os.path.realpath(eapi_file),)) + if os.path.exists(parentsFile): + parents = grabfile(parentsFile) + if not parents: + raise ParseError( + _("Empty parent file: '%s'") % parentsFile) + for parentPath in parents: + parentPath = normalize_path(os.path.join( + currentPath, parentPath)) + if os.path.exists(parentPath): + self._addProfile(parentPath) + else: + raise ParseError( + _("Parent '%s' not found: '%s'") % \ + (parentPath, parentsFile)) + self.profiles.append(currentPath) + + def set_root_override(self, root_overwrite=None): + # Allow ROOT setting to come from make.conf if it's not overridden + # by the constructor argument (from the calling environment). + if self.target_root is None and root_overwrite is not None: + self.target_root = root_overwrite + if not self.target_root.strip(): + self.target_root = None + if self.target_root is None: + self.target_root = "/" + + self.target_root = normalize_path(os.path.abspath( + self.target_root)).rstrip(os.path.sep) + os.path.sep + + ensure_dirs(self.target_root) + self._check_var_directory("ROOT", self.target_root) + + self.eroot = self.target_root.rstrip(os.sep) + self.eprefix + os.sep + + # make.globals should not be relative to config_root + # because it only contains constants. However, if EPREFIX + # is set then there are two possible scenarios: + # 1) If $ROOT == "/" then make.globals should be + # relative to EPREFIX. + # 2) If $ROOT != "/" then the correct location of + # make.globals needs to be specified in the constructor + # parameters, since it's a property of the host system + # (and the current config represents the target system). + self.global_config_path = GLOBAL_CONFIG_PATH + if self.eprefix: + if self.target_root == "/": + # case (1) above + self.global_config_path = os.path.join(self.eprefix, + GLOBAL_CONFIG_PATH.lstrip(os.sep)) + else: + # case (2) above + # For now, just assume make.globals is relative + # to EPREFIX. + # TODO: Pass in more info to the constructor, + # so we know the host system configuration. + self.global_config_path = os.path.join(self.eprefix, + GLOBAL_CONFIG_PATH.lstrip(os.sep)) + + def set_port_dirs(self, portdir, portdir_overlay): + self.portdir = portdir + self.portdir_overlay = portdir_overlay + if self.portdir_overlay is None: + self.portdir_overlay = "" + + self.overlay_profiles = [] + for ov in shlex_split(self.portdir_overlay): + ov = normalize_path(ov) + profiles_dir = os.path.join(ov, "profiles") + if os.path.isdir(profiles_dir): + self.overlay_profiles.append(profiles_dir) + + self.profile_locations = [os.path.join(portdir, "profiles")] + self.overlay_profiles + self.profile_locations = tuple(self.profile_locations) + + self.pmask_locations = [os.path.join(portdir, "profiles")] + self.pmask_locations.extend(self.profiles) + self.pmask_locations.extend(self.overlay_profiles) + self.pmask_locations = tuple(self.pmask_locations) diff --git a/pym/portage/package/ebuild/config.py b/pym/portage/package/ebuild/config.py index ca556c4ea..3c0736f4c 100644 --- a/pym/portage/package/ebuild/config.py +++ b/pym/portage/package/ebuild/config.py @@ -22,9 +22,9 @@ import portage portage.proxy.lazyimport.lazyimport(globals(), 'portage.data:portage_gid', ) -from portage import bsd_chflags, eapi_is_supported, \ +from portage import bsd_chflags, \ load_mod, os, selinux, _encodings, _unicode_encode, _unicode_decode -from portage.const import CACHE_PATH, CUSTOM_PROFILE_PATH, \ +from portage.const import CACHE_PATH, \ DEPCACHE_PATH, GLOBAL_CONFIG_PATH, INCREMENTALS, MAKE_CONF_FILE, \ MODULES_FILE_PATH, PORTAGE_BIN_PATH, PORTAGE_PYM_PATH, \ PRIVATE_PATH, PROFILE_PATH, SUPPORTED_FEATURES, USER_CONFIG_PATH, \ @@ -35,8 +35,7 @@ from portage.dbapi.vartree import vartree from portage.dep import Atom, isvalidatom, match_from_list, use_reduce from portage.eapi import eapi_exports_AA, eapi_supports_prefix, eapi_exports_replace_vars from portage.env.loaders import KeyValuePairFileLoader -from portage.exception import DirectoryNotFound, \ - InvalidDependString, ParseError, PortageException +from portage.exception import InvalidDependString, PortageException from portage.localization import _ from portage.output import colorize from portage.process import fakeroot_capable, sandbox_capable @@ -49,6 +48,7 @@ from portage.versions import catpkgsplit, catsplit, cpv_getkey from portage.package.ebuild._config.features_set import features_set from portage.package.ebuild._config.LicenseManager import LicenseManager from portage.package.ebuild._config.UseManager import UseManager +from portage.package.ebuild._config.LocationsManager import LocationsManager from portage.package.ebuild._config.MaskManager import MaskManager from portage.package.ebuild._config.VirtualsManager import VirtualsManager from portage.package.ebuild._config.helper import ordered_by_atom_specificity, prune_incremental @@ -349,11 +349,10 @@ class config(object): self._accept_properties = None self._features_overrides = [] - self.user_profile_dir = None self.local_config = local_config - self._local_repo_configs = None - self._local_repo_conf_path = None + self._local_repo_configs = None + if clone: # For immutable attributes, use shallow copy for # speed and memory conservation. @@ -377,8 +376,6 @@ class config(object): self._setcpv_args_hash = clone._setcpv_args_hash # immutable attributes (internal policy ensures lack of mutation) - self._local_repo_configs = clone._local_repo_configs - self._local_repo_conf_path = clone._local_repo_conf_path self._pkeywords_list = clone._pkeywords_list self._p_accept_keywords = clone._p_accept_keywords self._use_manager = clone._use_manager @@ -425,39 +422,31 @@ class config(object): self._expand_map = copy.deepcopy(clone._expand_map) else: + locations_manager = LocationsManager(eprefix=eprefix, config_profile_path=config_profile_path, \ + local_config=local_config) + + eprefix = locations_manager.eprefix + config_root = locations_manager.config_root + self.profiles = locations_manager.profiles + self.profile_path = locations_manager.profile_path + self.user_profile_dir = locations_manager.user_profile_dir + abs_user_config = locations_manager.abs_user_config + + make_conf = getconfig( + os.path.join(config_root, MAKE_CONF_FILE), + tolerant=tolerant, allow_sourcing=True) or {} - def check_var_directory(varname, var): - if not os.path.isdir(var): - writemsg(_("!!! Error: %s='%s' is not a directory. " - "Please correct this.\n") % (varname, var), - noiselevel=-1) - raise DirectoryNotFound(var) - - if eprefix is None: - eprefix = "" - if config_root is None: - config_root = eprefix + os.sep - - config_root = normalize_path(os.path.abspath( - config_root)).rstrip(os.path.sep) + os.path.sep - - check_var_directory("PORTAGE_CONFIGROOT", config_root) - abs_user_config = os.path.join(config_root, USER_CONFIG_PATH) + make_conf.update(getconfig( + os.path.join(abs_user_config, 'make.conf'), + tolerant=tolerant, allow_sourcing=True, + expand=make_conf) or {}) - if not config_profile_path: - config_profile_path = \ - os.path.join(config_root, PROFILE_PATH) - if os.path.isdir(config_profile_path): - self.profile_path = config_profile_path - else: - config_profile_path = \ - os.path.join(abs_user_config, 'make.profile') - if os.path.isdir(config_profile_path): - self.profile_path = config_profile_path - else: - self.profile_path = None - else: - self.profile_path = config_profile_path + # Allow ROOT setting to come from make.conf if it's not overridden + # by the constructor argument (from the calling environment). + locations_manager.set_root_override(make_conf.get("ROOT")) + target_root = locations_manager.target_root + eroot = locations_manager.eroot + global_config_path = locations_manager.global_config_path if config_incrementals is None: self.incrementals = INCREMENTALS @@ -491,59 +480,6 @@ class config(object): self.configlist.append({}) self.configdict["pkginternal"] = self.configlist[-1] - # The symlink might not exist or might not be a symlink. - if self.profile_path is None: - self.profiles = [] - else: - self.profiles = [] - def addProfile(currentPath): - parentsFile = os.path.join(currentPath, "parent") - eapi_file = os.path.join(currentPath, "eapi") - try: - eapi = codecs.open(_unicode_encode(eapi_file, - encoding=_encodings['fs'], errors='strict'), - mode='r', encoding=_encodings['content'], errors='replace' - ).readline().strip() - except IOError: - pass - else: - if not eapi_is_supported(eapi): - raise ParseError(_( - "Profile contains unsupported " - "EAPI '%s': '%s'") % \ - (eapi, os.path.realpath(eapi_file),)) - if os.path.exists(parentsFile): - parents = grabfile(parentsFile) - if not parents: - raise ParseError( - _("Empty parent file: '%s'") % parentsFile) - for parentPath in parents: - parentPath = normalize_path(os.path.join( - currentPath, parentPath)) - if os.path.exists(parentPath): - addProfile(parentPath) - else: - raise ParseError( - _("Parent '%s' not found: '%s'") % \ - (parentPath, parentsFile)) - self.profiles.append(currentPath) - try: - addProfile(os.path.realpath(self.profile_path)) - except ParseError as e: - writemsg(_("!!! Unable to parse profile: '%s'\n") % \ - self.profile_path, noiselevel=-1) - writemsg("!!! ParseError: %s\n" % str(e), noiselevel=-1) - del e - self.profiles = [] - if local_config and self.profiles: - custom_prof = os.path.join( - config_root, CUSTOM_PROFILE_PATH) - if os.path.exists(custom_prof): - self.user_profile_dir = custom_prof - self.profiles.append(custom_prof) - del custom_prof - - self.profiles = tuple(self.profiles) self.packages_list = [grabfile_package(os.path.join(x, "packages")) for x in self.profiles] self.packages = tuple(stack_lists(self.packages_list, incremental=1)) del self.packages_list @@ -589,32 +525,6 @@ class config(object): self._p_accept_keywords.append(cpdict) self._p_accept_keywords = tuple(self._p_accept_keywords) - make_conf = getconfig( - os.path.join(config_root, MAKE_CONF_FILE), - tolerant=tolerant, allow_sourcing=True) or {} - - make_conf.update(getconfig( - os.path.join(abs_user_config, 'make.conf'), - tolerant=tolerant, allow_sourcing=True, - expand=make_conf) or {}) - - # Allow ROOT setting to come from make.conf if it's not overridden - # by the constructor argument (from the calling environment). - if target_root is None and "ROOT" in make_conf: - target_root = make_conf["ROOT"] - if not target_root.strip(): - target_root = None - if target_root is None: - target_root = "/" - - target_root = normalize_path(os.path.abspath( - target_root)).rstrip(os.path.sep) + os.path.sep - - ensure_dirs(target_root) - check_var_directory("ROOT", target_root) - - eroot = target_root.rstrip(os.sep) + eprefix + os.sep - # The expand_map is used for variable substitution # in getconfig() calls, and the getconfig() calls # update expand_map with the value of each variable @@ -664,30 +574,6 @@ class config(object): self.configdict["env"] = LazyItemsDict(self.backupenv) - # make.globals should not be relative to config_root - # because it only contains constants. However, if EPREFIX - # is set then there are two possible scenarios: - # 1) If $ROOT == "/" then make.globals should be - # relative to EPREFIX. - # 2) If $ROOT != "/" then the correct location of - # make.globals needs to be specified in the constructor - # parameters, since it's a property of the host system - # (and the current config represents the target system). - global_config_path = GLOBAL_CONFIG_PATH - if eprefix: - if target_root == "/": - # case (1) above - global_config_path = os.path.join(eprefix, - GLOBAL_CONFIG_PATH.lstrip(os.sep)) - else: - # case (2) above - # For now, just assume make.globals is relative - # to EPREFIX. - # TODO: Pass in more info to the constructor, - # so we know the host system configuration. - global_config_path = os.path.join(eprefix, - GLOBAL_CONFIG_PATH.lstrip(os.sep)) - for x in (global_config_path,): self.mygcfg = getconfig(os.path.join(x, "make.globals"), expand=expand_map) @@ -788,11 +674,6 @@ class config(object): self._ppropertiesdict = portage.dep.ExtendedAtomDict(dict) self._penvdict = portage.dep.ExtendedAtomDict(dict) - # locations for "categories" and "arch.list" files - locations = [os.path.join(self["PORTDIR"], "profiles")] - pmask_locations = [os.path.join(self["PORTDIR"], "profiles")] - pmask_locations.extend(self.profiles) - """ repoman controls PORTDIR_OVERLAY via the environment, so no special cases are needed here.""" @@ -809,18 +690,10 @@ class config(object): self["PORTDIR_OVERLAY"] = " ".join(new_ov) self.backup_changes("PORTDIR_OVERLAY") - overlay_profiles = [] - for ov in shlex_split(self.get('PORTDIR_OVERLAY', '')): - ov = normalize_path(ov) - profiles_dir = os.path.join(ov, "profiles") - if os.path.isdir(profiles_dir): - overlay_profiles.append(profiles_dir) - locations += overlay_profiles - - pmask_locations.extend(overlay_profiles) + locations_manager.set_port_dirs(self["PORTDIR"], self["PORTDIR_OVERLAY"]) #getting categories from an external file now - categories = [grabfile(os.path.join(x, "categories")) for x in locations] + categories = [grabfile(os.path.join(x, "categories")) for x in locations_manager.profile_locations] category_re = dbapi._category_re self.categories = tuple(sorted( x for x in stack_lists(categories, incremental=1) @@ -837,20 +710,19 @@ class config(object): self.configdict["conf"].get("USE", "")) #Read license_groups and optionally license_groups and package.license from user config - self._license_manager = LicenseManager(locations, abs_user_config, user_config=local_config) + self._license_manager = LicenseManager(locations_manager.profile_locations, \ + abs_user_config, user_config=local_config) #Extract '*/*' entries from package.license self.configdict["conf"]["ACCEPT_LICENSE"] = \ self._license_manager.extract_global_changes( \ self.configdict["conf"].get("ACCEPT_LICENSE", "")) #Read package.mask and package.unmask from profiles and optionally from user config - self._mask_manager = MaskManager(pmask_locations, abs_user_config, user_config=local_config) + self._mask_manager = MaskManager(locations_manager.pmask_locations, abs_user_config, user_config=local_config) self._virtuals_manager = VirtualsManager(self.profiles) if local_config: - locations.append(abs_user_config) - # package.accept_keywords and package.keywords pkgdict = grabdict_package( os.path.join(abs_user_config, "package.keywords"), @@ -941,7 +813,7 @@ class config(object): self._local_repo_configs[repo_name] = \ _local_repo_config(repo_name, repo_opts) - archlist = [grabfile(os.path.join(x, "arch.list")) for x in locations] + archlist = [grabfile(os.path.join(x, "arch.list")) for x in locations_manager.profile_locations] archlist = stack_lists(archlist, incremental=1) self.configdict["conf"]["PORTAGE_ARCHLIST"] = " ".join(archlist) -- cgit v1.2.3-1-g7c22