From 9d4459dfea72717c0565b0cfe39fa3a87a57ad9d Mon Sep 17 00:00:00 2001 From: Brian Harring Date: Mon, 24 Oct 2011 22:37:34 -0700 Subject: Track profile format, and if compatibility mode is in use. Warn if the profile is using portage-1 format, but isn't marked as such. --- .../package/ebuild/_config/LocationsManager.py | 67 ++++++++++++++++++---- pym/portage/package/ebuild/config.py | 1 + 2 files changed, 57 insertions(+), 11 deletions(-) (limited to 'pym') diff --git a/pym/portage/package/ebuild/_config/LocationsManager.py b/pym/portage/package/ebuild/_config/LocationsManager.py index 4072ffcae..a465935f2 100644 --- a/pym/portage/package/ebuild/_config/LocationsManager.py +++ b/pym/portage/package/ebuild/_config/LocationsManager.py @@ -13,8 +13,14 @@ from portage.exception import DirectoryNotFound, ParseError from portage.localization import _ from portage.util import ensure_dirs, grabfile, \ normalize_path, shlex_split, writemsg +from portage.repository.config import parse_layout_conf +_PORTAGE1_DIRECTORIES = frozenset([ + 'package.mask', 'package.provided', + 'package.use', 'package.use.mask', 'package.use.force', + 'use.mask', 'use.force']) + class LocationsManager(object): def __init__(self, config_root=None, eprefix=None, config_profile_path=None, local_config=True, \ @@ -37,17 +43,23 @@ class LocationsManager(object): self._check_var_directory("PORTAGE_CONFIGROOT", self.config_root) self.abs_user_config = os.path.join(self.config_root, USER_CONFIG_PATH) + self.config_profile_path = config_profile_path + + def load_profiles(self, known_repository_paths): + known_repos = [os.path.abspath(x) for x in set(known_repository_paths)] + # force a trailing '/' for ease of doing startswith checks + known_repos = [(x + '/', parse_layout_conf(x)[0]) for x in known_repos] - if config_profile_path is None: - config_profile_path = \ + if self.config_profile_path is None: + self.config_profile_path = \ os.path.join(self.config_root, PROFILE_PATH) - if os.path.isdir(config_profile_path): - self.profile_path = config_profile_path + if os.path.isdir(self.config_profile_path): + self.profile_path = self.config_profile_path else: - config_profile_path = \ + self.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 + if os.path.isdir(self.config_profile_path): + self.profile_path = self.config_profile_path else: self.profile_path = None else: @@ -55,14 +67,16 @@ class LocationsManager(object): # here, in order to create an empty profile # for checking dependencies of packages with # empty KEYWORDS. - self.profile_path = config_profile_path + self.profile_path = self.config_profile_path # The symlink might not exist or might not be a symlink. self.profiles = [] + self.profiles_complex = [] if self.profile_path: try: - self._addProfile(os.path.realpath(self.profile_path)) + self._addProfile(os.path.realpath(self.profile_path), + known_repos) except ParseError as e: writemsg(_("!!! Unable to parse profile: '%s'\n") % \ self.profile_path, noiselevel=-1) @@ -75,9 +89,11 @@ class LocationsManager(object): if os.path.exists(custom_prof): self.user_profile_dir = custom_prof self.profiles.append(custom_prof) + self.profiles_complex.append((custom_prof, True)) del custom_prof self.profiles = tuple(self.profiles) + self.profiles_complex = tuple(self.profiles_complex) def _check_var_directory(self, varname, var): if not os.path.isdir(var): @@ -86,7 +102,34 @@ class LocationsManager(object): noiselevel=-1) raise DirectoryNotFound(var) - def _addProfile(self, currentPath): + def _addProfile(self, currentPath, known_repos): + current_abs_path = os.path.abspath(currentPath) + allow_directories = True + compat_mode = False + intersecting_repos = [x for x in known_repos if current_abs_path.startswith(x[0])] + if intersecting_repos: + # protect against nested repositories. Insane configuration, but the longest + # path will be the correct one. + repo_loc, layout_data = max(intersecting_repos, key=lambda x:len(x[0])) + allow_directories = any(x.startswith("portage-1") + for x in layout_data['profile-formats']) + compat_mode = layout_data['profile-formats'] == ('portage-1-compat',) + + if compat_mode: + offenders = _PORTAGE1_DIRECTORIES.intersection(os.listdir(currentPath)) + offenders = sorted(x for x in offenders + if os.path.isdir(os.path.join(currentPath, x))) + if offenders: + writemsg((_("Profile '%(profile_path)s' in repository " + "'%(repo_name)s' is using 'portage-1' profile format, but " + "the repository is not configured for it. This will break " + "in the future. Please either convert the following paths " + "to files, or add\nprofile-format = portage-1\nto the " + "repositories layout.conf. Files: '%(files)s'\n") + % dict(profile_path=currentPath, repo_name=repo_loc, + files=', '.join(offenders))), + noiselevel=-1) + parentsFile = os.path.join(currentPath, "parent") eapi_file = os.path.join(currentPath, "eapi") f = None @@ -115,12 +158,14 @@ class LocationsManager(object): parentPath = normalize_path(os.path.join( currentPath, parentPath)) if os.path.exists(parentPath): - self._addProfile(parentPath) + self._addProfile(parentPath, known_repos) else: raise ParseError( _("Parent '%s' not found: '%s'") % \ (parentPath, parentsFile)) + self.profiles.append(currentPath) + self.profiles_complex.append((currentPath, allow_directories)) def set_root_override(self, root_overwrite=None): # Allow ROOT setting to come from make.conf if it's not overridden diff --git a/pym/portage/package/ebuild/config.py b/pym/portage/package/ebuild/config.py index d49ac600a..c4c5e660f 100644 --- a/pym/portage/package/ebuild/config.py +++ b/pym/portage/package/ebuild/config.py @@ -276,6 +276,7 @@ class config(object): locations_manager = LocationsManager(config_root=config_root, config_profile_path=config_profile_path, eprefix=eprefix, local_config=local_config, target_root=target_root) + locations_manager.load_profiles([]) eprefix = locations_manager.eprefix config_root = locations_manager.config_root -- cgit v1.2.3-1-g7c22