Track profile format, and if compatibility mode is in use.
authorBrian Harring <ferringb@chromium.org>
Tue, 25 Oct 2011 05:37:34 +0000 (22:37 -0700)
committerZac Medico <zmedico@gentoo.org>
Tue, 25 Oct 2011 21:36:42 +0000 (14:36 -0700)
Warn if the profile is using portage-1 format, but isn't marked as such.

pym/portage/package/ebuild/_config/LocationsManager.py
pym/portage/package/ebuild/config.py

index 4072ffcae8b00776eb0d48fdbdb7f08677429812..a465935f2206cd83f819440d500af56194bd7709 100644 (file)
@@ -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
index d49ac600a872ad674fc369cf1385123bcf142726..c4c5e660fb92b0cf226d961d9a73e227ed5859bb 100644 (file)
@@ -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