Bug #124041 - Make emerge show an informative warning message when one
authorZac Medico <zmedico@gentoo.org>
Mon, 26 Nov 2007 01:16:16 +0000 (01:16 -0000)
committerZac Medico <zmedico@gentoo.org>
Mon, 26 Nov 2007 01:16:16 +0000 (01:16 -0000)
or more eclasses override eclasses from PORTDIR. The warning can be
permanently disabled by setting PORTAGE_ECLASS_WARNING_ENABLE="0" in
/etc/make.conf. (trunk r8668)

svn path=/main/branches/2.1.2/; revision=8669

bin/emerge
pym/eclass_cache.py
pym/portage.py

index a527c26cc77664ba93c1c61097a92907dab5994b..49204d9bed7620332952b6974696adbb6e0ef40d 100755 (executable)
@@ -6313,10 +6313,39 @@ def emerge_main():
 
        portage.deprecated_profile_check()
 
-       #Freeze the portdbapi for enhanced performance:
-       for myroot in trees:
-               trees[myroot]["porttree"].dbapi.freeze()
-               del myroot
+       eclasses_overridden = {}
+       for mytrees in trees.itervalues():
+               mydb = mytrees["porttree"].dbapi
+               # Freeze the portdbapi for performance (memoize all xmatch results).
+               mydb.freeze()
+               eclasses_overridden.update(mydb.eclassdb._master_eclasses_overridden)
+       del mytrees, mydb
+
+       if eclasses_overridden and \
+               settings.get("PORTAGE_ECLASS_WARNING_ENABLE") != "0":
+               prefix = bad(" * ")
+               if len(eclasses_overridden) == 1:
+                       writemsg(prefix + "Overlay eclass overrides " + \
+                               "eclass from PORTDIR:\n", noiselevel=-1)
+               else:
+                       writemsg(prefix + "Overlay eclasses override " + \
+                               "eclasses from PORTDIR:\n", noiselevel=-1)
+               writemsg(prefix + "\n", noiselevel=-1)
+               for eclass_name in sorted(eclasses_overridden):
+                       writemsg(prefix + "  '%s/%s.eclass'\n" % \
+                               (eclasses_overridden[eclass_name], eclass_name),
+                               noiselevel=-1)
+               writemsg(prefix + "\n", noiselevel=-1)
+               msg = "It is best to avoid overridding eclasses from PORTDIR " + \
+               "because it will trigger invalidation of cached ebuild metadata " + \
+               "that is distributed with the portage tree. If you must " + \
+               "override eclasses from PORTDIR then you are advised to run " + \
+               "`emerge --regen` after each time that you run `emerge --sync`. " + \
+               "Set PORTAGE_ECLASS_WARNING_ENABLE=\"0\" in /etc/make.conf if " + \
+               "you would like to disable this warning."
+               from textwrap import wrap
+               for line in wrap(msg, 72):
+                       writemsg("%s%s\n" % (prefix, line), noiselevel=-1)
 
        if "moo" in myfiles:
                print """
index ede081d9c2257b6118c076717fd914428fdc0e67..b8d8493683bbced517ba33c912381bae70a7e805 100644 (file)
@@ -23,6 +23,7 @@ class cache:
                self.porttrees = [self.porttree_root]+overlays
                self.porttrees = tuple(map(normalize_path, self.porttrees))
                self._master_eclass_root = os.path.join(self.porttrees[0],"eclass")
+               self._master_eclasses_overridden = {}
                self.update_eclasses()
 
        def close_caches(self):
@@ -41,6 +42,7 @@ class cache:
        def update_eclasses(self):
                self.eclasses = {}
                self._eclass_locations = {}
+               master_eclasses = {}
                eclass_len = len(".eclass")
                ignored_listdir_errnos = (errno.ENOENT, errno.ENOTDIR)
                for x in [normalize_path(os.path.join(y,"eclass")) for y in self.porttrees]:
@@ -63,7 +65,13 @@ class cache:
                                ys=y[:-eclass_len]
                                self.eclasses[ys] = (x, long(mtime))
                                self._eclass_locations[ys] = x
-       
+                               if x == self._master_eclass_root:
+                                       master_eclasses[ys] = mtime
+                               else:
+                                       master_mtime = master_eclasses.get(ys)
+                                       if master_mtime and master_mtime != mtime:
+                                               self._master_eclasses_overridden[ys] = x
+
        def is_eclass_data_valid(self, ec_dict):
                if not isinstance(ec_dict, dict):
                        return False
index f82074f74c413033d080e546e3223a89f610f149..bbaee8027b01ea78b8cdaf6b02fdef442b073ace 100644 (file)
@@ -961,7 +961,11 @@ class config:
        Generally if you need data like USE flags, FEATURES, environment variables,
        virtuals ...etc you look in here.
        """
-       
+
+       # Filter selected variables in the config.environ() method so that
+       # they don't needlessly propagate down into the ebuild environment.
+       _environ_filter = frozenset(["PORTAGE_ECLASS_WARNING_ENABLE"])
+
        def __init__(self, clone=None, mycpv=None, config_profile_path=None,
                config_incrementals=None, config_root=None, target_root=None,
                local_config=True):
@@ -2429,7 +2433,10 @@ class config:
        def environ(self):
                "return our locally-maintained environment"
                mydict={}
+               environ_filter = self._environ_filter
                for x in self:
+                       if x in environ_filter:
+                               continue
                        myvalue = self[x]
                        if not isinstance(myvalue, basestring):
                                writemsg("!!! Non-string value in config: %s=%s\n" % \