Merged from trunk 4816:4828
authorFabian Groffen <grobian@gentoo.org>
Thu, 26 Oct 2006 17:40:15 +0000 (17:40 -0000)
committerFabian Groffen <grobian@gentoo.org>
Thu, 26 Oct 2006 17:40:15 +0000 (17:40 -0000)
For bug #152726, ignore hidden files in vardbapi.cp_list().

For full compatibility with older versions of portage, write the path in
the serialized _eclasses_ when possible.

Fix broken is_eclass_data_valid comparison logic.

Test for basestring instead of types.DictType so that the test more
generic.

Reverse the relationship between __contains__ and has_key in all cache
classes since python handles the "in" operator more efficiently than a
has_key method call.

Streamline portage pythonpath handling and add an override analog to how
the bash side does it.

rename getmaskingreason() to getpmaskcomment() to clarify its function,
report each license as a separate mask instead of combining them all
together into a single value for getmaskingstatus()

need a mutable config instance to use setcpv

add function getlicensetexts() to extract license texts relevant to a
given cpv (to be used by emerge masked by display)

show licenses or pointer to license files on 'masked by' message

svn path=/main/branches/prefix/; revision=4831

28 files changed:
NEWS
bin/archive-conf
bin/chkcontents
bin/clean_locks
bin/dispatch-conf
bin/ebuild
bin/emaint
bin/emerge
bin/env-update
bin/fix-db.py
bin/fixpackages
bin/md5check.py
bin/pkgname
bin/portageq
bin/regenworld
bin/repoman
bin/xpak
pym/cache/anydbm.py
pym/cache/flat_hash.py
pym/cache/flat_list.py
pym/cache/metadata.py
pym/cache/metadata_overlay.py
pym/cache/sql_template.py
pym/cache/sqlite.py
pym/cache/template.py
pym/dispatch_conf.py
pym/eclass_cache.py
pym/portage.py

diff --git a/NEWS b/NEWS
index a5ecef4ae86ffcdf96f4b6406fa7182ba9e21453..a4c96ed62db92568bc17ecd17c1f553aa7e9e517 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -19,6 +19,8 @@ portage-2.1.2
   order and detection of circular dependencies.
 * The world and system sets allow automatic update of all installed slots.
 * DEPEND atoms support SLOT dependencies of the form ${CATEGORY}/${PN}:${SLOT}.
+* Development: Extend PORTAGE_PYM_PATH support to allow overriding the hardcoded 
+  /usr/lib/portage/pym for development/testing purposes
 
 portage-2.1.1
 ------------
index e50c3907897b654acb9e7193d5fe9570fd7c22d7..4909f9b33a3753dd7674eb208d8230a1f0e2ff1d 100755 (executable)
@@ -11,7 +11,7 @@
 #
 
 import os, sys, string
-sys.path = ["@PORTAGE_BASE@/pym"]+sys.path
+sys.path.insert(0, os.environ.get("PORTAGE_PYM_PATH", "@PORTAGE_BASE@/pym"))
 
 import portage, dispatch_conf
 
index 008b4de4f4e536309dda68e7449451e8de66ebd1..65f1a8190853ca0b89442fd0fa4529816affa98f 100755 (executable)
@@ -9,7 +9,7 @@
 # the right files).
 
 import string, os.path, os, sys
-sys.path = ["@PORTAGE_BASE@/pym"]+sys.path
+sys.path.insert(0, os.environ.get("PORTAGE_PYM_PATH", "@PORTAGE_BASE@/pym"))
 import portage
 
 def CONTENTScheck(path):
index 855e9fc9443c80b29913470b9018596a798ed6d4..d6cfee1512cd28ac94992117d8cdd1b9b50ed8b1 100755 (executable)
@@ -3,8 +3,8 @@
 # Distributed under the terms of the GNU General Public License v2
 # $Id: /var/cvsroot/gentoo-src/portage/bin/clean_locks,v 1.1 2004/09/26 10:44:31 carpaski Exp $
 
-import os,sys
-sys.path = ["@PORTAGE_BASE@/pym"]+sys.path
+import os,sys,errno
+sys.path.insert(0, os.environ.get("PORTAGE_PYM_PATH", "@PORTAGE_BASE@/pym"))
 
 import portage_locks, portage_const
 
index eb18fcfc7fc73d8c65c96eb7df678cb2beed41f0..fe524517d47655c761532b5fb523431214fe884a 100755 (executable)
@@ -15,7 +15,7 @@
 from stat import *
 from random import *
 import atexit, commands, os, re, shutil, stat, string, sys
-sys.path = ["@PORTAGE_BASE@/pym"]+sys.path
+sys.path.insert(0, os.environ.get("PORTAGE_PYM_PATH", "@PORTAGE_BASE@/pym"))
 
 import portage, dispatch_conf, portage_const
 
index 5d7f2def836fd1c58687f52749ab0f013c9739b9..d47c9258232def6730e2753dc0c0c82edc44741c 100755 (executable)
@@ -21,7 +21,7 @@ if "merge" in pargs:
        os.environ["FEATURES"] = os.environ.get("FEATURES", "") + " -noauto"
 
 os.environ["PORTAGE_CALLER"]="ebuild"
-sys.path = ["@PORTAGE_BASE@/pym"]+sys.path
+sys.path.insert(0, os.environ.get("PORTAGE_PYM_PATH", "@PORTAGE_BASE@/pym"))
 
 import portage, portage_util, portage_const
 
index f29013ae22ef34c85124bd92830639afdc565109..23ca3bc9745c8b28fef4073a480f1546e01f1099 100755 (executable)
@@ -1,7 +1,7 @@
 #!@PYTHON@ -O
 
-import sys
-sys.path.insert(0, "@PORTAGE_BASE@/pym")
+import sys, os
+sys.path.insert(0, os.environ.get("PORTAGE_PYM_PATH", "@PORTAGE_BASE@/pym"))
 from optparse import OptionParser, OptionValueError
 
 import re
index e0a05f32bc2474765bc8324c68d6882da0035917..69ef549a4760dcddae19d246144ca06f19b8869a 100755 (executable)
@@ -21,7 +21,7 @@ except KeyboardInterrupt:
        sys.exit(1)
 
 import os, stat
-sys.path = ["@PORTAGE_BASE@/pym"]+sys.path
+sys.path.insert(0, os.environ.get("PORTAGE_PYM_PATH", "@PORTAGE_BASE@/pym"))
 
 os.environ["PORTAGE_LEGACY_GLOBALS"] = "false"
 import portage
@@ -1359,15 +1359,30 @@ class depgraph:
                                                        print "\n!!! "+red("All ebuilds that could satisfy ")+green(xinfo)+red(" have been masked.")
                                                        print "!!! One of the following masked packages is required to complete your request:"
                                                        oldcomment = ""
+                                                       shown_licenses = []
                                                        for p in alleb:
                                                                mreasons = portage.getmaskingstatus(p,
                                                                        settings=pkgsettings, portdb=portdb)
                                                                print "- "+p+" (masked by: "+string.join(mreasons, ", ")+")"
-                                                               comment = portage.getmaskingreason(p,
-                                                                       settings=pkgsettings, portdb=portdb)
-                                                               if comment and comment != oldcomment:
-                                                                       print comment
-                                                                       oldcomment = comment
+                                                               if "package.mask" in mreasons:
+                                                                       comment = portage.getpmaskcomment(p,
+                                                                               settings=pkgsettings, portdb=portdb)
+                                                                       if comment and comment != oldcomment:
+                                                                               print comment
+                                                                               oldcomment = comment
+                                                               licdict = portage.getlicensetexts(p, settings=pkgsettings, portdb=portdb, onlymasked=True)
+                                                               for lic in licdict.keys():
+                                                                       if lic+" license" in mreasons and not lic in shown_licenses:
+                                                                               if len(licdict[lic][1]) > 2000:
+                                                                                       print "Please read the text of license %s in %s" % (lic, licdict[lic][0])
+                                                                                       print
+                                                                               else:
+                                                                                       print "License text for license %s:" % lic
+                                                                                       print
+                                                                                       print licdict[lic][1]
+                                                                                       print
+                                                                               shown_licenses.append(lic)
+                                                                               
                                                        print
                                                        print "For more information, see MASKED PACKAGES section in the emerge man page or "
                                                        print "refer to the Gentoo Handbook."
index bbb159127bd5e7a69765d4873e8d87a06573f3e6..6390ae4d989cf314f598b54d535d5b2e651b7d7c 100755 (executable)
@@ -4,7 +4,7 @@
 # $Id: /var/cvsroot/gentoo-src/portage/bin/env-update,v 1.9 2004/10/04 13:56:50 vapier Exp $
 
 import os,sys
-sys.path = ["@PORTAGE_BASE@/pym"]+sys.path
+sys.path.insert(0, os.environ.get("PORTAGE_PYM_PATH", "@PORTAGE_BASE@/pym"))
 
 def usage(status):
        print "Usage: env-update [--no-ldconfig]"
index 34a422e9168cd268973fc6b58a8bebc6a5e6cbe0..b12b316c8d4cddb06551c7e39eb87fad11943051 100755 (executable)
@@ -4,7 +4,7 @@
 # $Id: /var/cvsroot/gentoo-src/portage/bin/fix-db.py,v 1.8 2004/10/11 04:01:00 jstubbs Exp $
 
 import os,sys,re
-sys.path = ["@PORTAGE_BASE@/pym"]+sys.path
+sys.path.insert(0, os.environ.get("PORTAGE_PYM_PATH", "@PORTAGE_BASE@/pym"))
 
 from stat import *
 from output import *
index 8b9172fc27a177952aeb7a7b50251f080a3ae3f9..928a7107c6f10be7605a49695c39d4dab459a771 100755 (executable)
@@ -5,7 +5,7 @@
 
 import os,sys
 os.environ["PORTAGE_CALLER"]="fixpackages"
-sys.path = ["@PORTAGE_BASE@/pym"]+sys.path
+sys.path.insert(0, os.environ.get("PORTAGE_PYM_PATH", "@PORTAGE_BASE@/pym"))
 
 import portage
 
index 16157bd0034dc1f454d0a8f3e1af90eb8cd94566..df95ad2a89e37ebfe3096e3082a9fd7c2de35921 100755 (executable)
@@ -5,7 +5,7 @@
 
 import os,sys,string
 os.environ["FEATURES"]="mirror cvs"
-sys.path = ["@PORTAGE_BASE@/pym"]+sys.path
+sys.path.insert(0, os.environ.get("PORTAGE_PYM_PATH", "@PORTAGE_BASE@/pym"))
 
 import portage
 from threading import *
index d60bac8035d983d2ffb5292922d50fd5b67deef8..ef946abe70d74e8593f1ccafc707b491730bd1d7 100755 (executable)
@@ -3,8 +3,8 @@
 # Distributed under the terms of the GNU General Public License v2
 # $Id: /var/cvsroot/gentoo-src/portage/bin/pkgname,v 1.8 2004/10/04 13:56:50 vapier Exp $
 
-import sys
-sys.path = ["@PORTAGE_BASE@/pym"]+sys.path
+import sys, os
+sys.path.insert(0, os.environ.get("PORTAGE_PYM_PATH", "@PORTAGE_BASE@/pym"))
 
 import portage
 
index 7bb21d32198b5ab03b4f919aa4d3505b1eb6dcbc..f4fe1f5cdb70c1667aac873905f2d6aa083ba4bc 100755 (executable)
@@ -20,7 +20,7 @@ except KeyboardInterrupt:
        sys.exit(1)
 
 import os
-sys.path = ["@PORTAGE_BASE@/pym"]+sys.path
+sys.path.insert(0, os.environ.get("PORTAGE_PYM_PATH", "@PORTAGE_BASE@/pym"))
 
 import types,string
 
index e8f4f0d5e9596223e508cc4944accf5919fc1a66..ebf315d77fe40395229eb89362afe69008798144 100755 (executable)
@@ -3,9 +3,8 @@
 # Distributed under the terms of the GNU General Public License v2
 # $Id: /var/cvsroot/gentoo-src/portage/bin/regenworld,v 1.10.2.1 2005/01/11 03:40:57 carpaski Exp $
 
-import sys
-sys.path.insert(0, "@PORTAGE_BASE@/pym")
-import os
+import sys, os
+sys.path.insert(0, os.environ.get("PORTAGE_PYM_PATH", "@PORTAGE_BASE@/pym"))
 import portage, string, re, portage_const
 
 __candidatematcher__ = re.compile("^[0-9]+: \\*\\*\\* emerge ")
index b4a108da53ced4d74ee958c0e8e248a9bd5c1c1e..3a63c5ce3e05144b6337258ff8a68728fb56e90a 100755 (executable)
@@ -11,7 +11,7 @@ import errno, os, shutil, sys
 if not hasattr(__builtins__, "set"):
        from sets import Set as set
 exename=os.path.basename(sys.argv[0])  
-sys.path = ["@PORTAGE_BASE@/pym"]+sys.path
+sys.path.insert(0, os.environ.get("PORTAGE_PYM_PATH", "@PORTAGE_BASE@/pym"))
 version="1.2"  
 
 allowed_filename_chars="a-zA-Z0-9._-+:"
index 85553ba2769e2c546b81de0df2821402328fa69d..c983c14392c64ec4ecaae95824826cc82e016a03 100755 (executable)
--- a/bin/xpak
+++ b/bin/xpak
@@ -3,12 +3,12 @@
 # Distributed under the terms of the GNU General Public License v2
 # $Id: xpak 3483 2006-06-10 21:40:40Z genone $
 
-import sys
+import sys, os
 if len(sys.argv)!=3:
        print "xpak: expecting three arguments."
        sys.exit(1)
 
-sys.path = ["@PORTAGE_BASE@/pym"]+sys.path
+sys.path.insert(0, os.environ.get("PORTAGE_PYM_PATH", "@PORTAGE_BASE@/pym"))
 
 import xpak
 xpak.xpak(sys.argv[1],sys.argv[2])
index ac9081aaf7e12f1160c8c2f8588a8e5a30258a3e..a632fe12c09e9253b6a374672c8418787c3e11e6 100644 (file)
@@ -63,7 +63,7 @@ class database(fs_template.FsBased):
        def iterkeys(self):
                return iter(self.__db)
 
-       def has_key(self, cpv):
+       def __contains__(self, cpv):
                return cpv in self.__db
 
        def __del__(self):
index 26861e49456cc03d36548e4930955e3d213fdc88..bbfb557205d0726e452660aeb4ed84acecb1e88f 100644 (file)
@@ -98,7 +98,7 @@ class database(fs_template.FsBased):
                                raise cache_errors.CacheCorruption(cpv, e)
 
 
-       def has_key(self, cpv):
+       def __contains__(self, cpv):
                return os.path.exists(os.path.join(self.location, cpv))
 
 
index 65fe5a781876a8ff20177ae52f554d14e886ee1a..85efa4c0214cc7ac56bfd44702be3b282cd126d2 100644 (file)
@@ -82,7 +82,7 @@ class database(fs_template.FsBased):
                                raise cache_errors.CacheCorruption(cpv, e)
 
 
-       def has_key(self, cpv):
+       def __contains__(self, cpv):
                return os.path.exists(os.path.join(self._base, cpv))
 
 
index 5c1c593a294b68e4c9c55ab2d82be10e0f08000f..9eace6a279da793cb3f5795a6c04c37bf1789de9 100644 (file)
@@ -68,8 +68,10 @@ class database(flat_hash.database):
                        if "INHERITED" in d:
                                d["_eclasses_"] = self.ec.get_eclass_data(d["INHERITED"].split(), from_master_only=True)
                                del d["INHERITED"]
-               else:
-                       d["_eclasses_"] = reconstruct_eclasses(cpv, d["_eclasses_"])
+               elif isinstance(d["_eclasses_"], basestring):
+                       # We skip this if flat_hash.database._parse_data() was called above
+                       # because it calls reconstruct_eclasses() internally.
+                       d["_eclasses_"] = reconstruct_eclasses(None, d["_eclasses_"])
 
                return d
 
index f4871674e544e0ce5e7b4203924b4a6b771c05b3..1716e3dd45966d6aaeee4794944f37ab5f3c40fb 100644 (file)
@@ -54,7 +54,7 @@ class database(template.database):
                else:
                        del self.db_rw[cpv]
 
-       def has_key(self, cpv):
+       def __contains__(self, cpv):
                try:
                        self[cpv] # validates whiteout when necessary
                except KeyError:
index 533b099ec4d1e7219f42ee62bdcb234f14a5b5ac..0734222b1d9095841eed5bf7f8d2357e4b53c1eb 100644 (file)
@@ -196,7 +196,7 @@ class SQLDatabase(template.database):
                return self.con.fetchone()[0]
 
 
-       def has_key(self, cpv):
+       def __contains__(self, cpv):
                if not self.autocommits:
                        try:    self.commit()
                        except self._BaseError, e:
index 571eff39b9509a386fb095bd8dd72e4df0616dda..6b1a3d32318dc3389029341e184d22981a334761 100644 (file)
@@ -200,7 +200,7 @@ class database(fs_template.FsBased):
                        self._db_table["packages"]["package_key"],
                        self._db_escape_string(cpv)))
 
-       def has_key(self, cpv):
+       def __contains__(self, cpv):
                cursor = self._db_cursor
                cursor.execute(" ".join(
                        ["SELECT %s FROM %s" %
index d68138f89b7f206e76383b1346761d8783a9a068..5c72da286dedd21439543dfef4b82e1bbb84fecb 100644 (file)
@@ -89,7 +89,7 @@ class database(object):
                raise NotImplementedError
 
        def has_key(self, cpv):
-               raise NotImplementedError
+               return cpv in self
 
        def keys(self):
                return tuple(self.iterkeys())
@@ -114,7 +114,7 @@ class database(object):
                        raise NotImplementedError
 
        def __contains__(self, cpv):
-               return self.has_key(cpv)
+               raise NotImplementedError
 
        def get_matches(self, match_dict):
                """generic function for walking the entire cache db, matching restrictions to
@@ -158,10 +158,9 @@ def serialize_eclasses(eclass_dict):
        return "\t".join(["%s\t%s" % (k, str(v)) \
                for k, v in eclass_dict.iteritems()])
        """
-       """ This is a variation of the old format that uses a relative path instead
-       of the full path of the eclass.  It should only force a regen in older
-       versions of portage (rather than a traceback)."""
-       return "\t".join(["%s\teclass\t%s" % (k, str(v)) \
+       if not eclass_dict:
+               return ""
+       return "\t".join(["%s\t%s\t%s" % (k, v[0], str(v[1])) \
                for k, v in eclass_dict.iteritems()])
 
 def reconstruct_eclasses(cpv, eclass_string):
@@ -177,11 +176,11 @@ def reconstruct_eclasses(cpv, eclass_string):
        try:
                if eclasses[1].isdigit():
                        for x in xrange(0, len(eclasses), 2):
-                               d[eclasses[x]] = long(eclasses[x + 1])
+                               d[eclasses[x]] = ("", long(eclasses[x + 1]))
                else:
                        # The old format contains paths that will be discarded.
                        for x in xrange(0, len(eclasses), 3):
-                               d[eclasses[x]] = long(eclasses[x + 2])
+                               d[eclasses[x]] = (eclasses[x + 1], long(eclasses[x + 2]))
        except ValueError:
                raise cache_errors.CacheCorruption(cpv, "_eclasses_ mtime conversion to long failed")
        del eclasses
index 9ca57f0da2271747418569859f0a125bafe628e2..e7a7da039c7d7ea1b26730f86912b22c1dd0c2c7 100644 (file)
@@ -10,7 +10,7 @@
 from stat import *
 import os, sys, commands, shutil
 
-sys.path = ["/usr/lib/portage/pym"]+sys.path
+sys.path.insert(0, os.environ.get("PORTAGE_PYM_PATH", "/usr/lib/portage/pym"))
 import portage
 
 RCS_BRANCH = '1.1.1'
index 904e63261d21de39bb0b765175707a6826bfede1..b0f82fd02661cd56c007d3ad2edd40f38bb3c202 100644 (file)
@@ -50,14 +50,19 @@ class cache:
                                except OSError:
                                        continue
                                ys=y[:-eclass_len]
-                               self.eclasses[ys] = long(mtime)
+                               self.eclasses[ys] = (x, long(mtime))
                                self._eclass_locations[ys] = x
        
        def is_eclass_data_valid(self, ec_dict):
                if not isinstance(ec_dict, dict):
                        return False
-               for eclass, mtime in ec_dict.iteritems():
-                       if eclass not in self.eclasses or mtime != self.eclasses[eclass]:
+               for eclass, tup in ec_dict.iteritems():
+                       cached_data = self.eclasses.get(eclass, None)
+                       """ Only use the mtime for validation since the probability of a
+                       collision is small and, depending on the cache implementation, the
+                       path may not be specified (cache from rsync mirrors, for example).
+                       """
+                       if cached_data is None or tup[1] != cached_data[1]:
                                return False
 
                return True
index c745e7c23390499b19ca47a118b6640f3af5053e..e5d91bccdaa6a5d4e3cac192f6d23b481f57fa50 100644 (file)
@@ -3837,7 +3837,34 @@ def cpv_expand(mycpv, mydb=None, use_cache=1, settings=None):
        else:
                return mykey
 
-def getmaskingreason(mycpv, settings=None, portdb=None):
+def getlicensetexts(mycpv, settings=None, portdb=None, onlymasked=True):
+       if portdb is None:
+               portdb = globals()["portdb"]
+       if settings is None:
+               settings = config(clone=globals()["settings"])
+
+       license_data = portdb.aux_get(mycpv, ["LICENSE"])[0]
+       settings.setcpv(mycpv, mydb=portdb)
+       acceptable_licenses = settings.acceptable_licenses(mycpv)
+
+       def str_matches(myatom):
+               return (not onlymasked) and (myatom in acceptable_licenses)
+
+       license_list = dep_check(license_data, None, settings,
+               str_matches=str_matches)[1]
+       if onlymasked and "*" in acceptable_licenses:
+               license_list = []
+
+       rValue = {}
+       for lic in license_list:
+               # Account for overlays here? How?
+               licfilename = os.path.join(settings["PORTDIR"], "licenses", lic)
+               fd = open(licfilename, "r")
+               rValue[lic] = (licfilename, fd.read())
+               fd.close()
+       return rValue
+
+def getpmaskcomment(mycpv, settings=None, portdb=None):
        from portage_util import grablines
        if settings is None:
                settings = globals()["settings"]
@@ -3882,10 +3909,12 @@ def getmaskingreason(mycpv, settings=None, portdb=None):
                                                return comment
                                        i = i + 1
        return None
+# Compability name
+getmaskingreason=getpmaskcomment
 
 def getmaskingstatus(mycpv, settings=None, portdb=None):
        if settings is None:
-               settings = globals()["settings"]
+               settings = config(clone=globals()["settings"])
        if portdb is None:
                portdb = globals()["portdb"]
        mysplit = catpkgsplit(mycpv)
@@ -3970,7 +3999,7 @@ def getmaskingstatus(mycpv, settings=None, portdb=None):
                license_req = dep_check(mylicense, None, settings,
                        str_matches=str_matches)[1]
                if license_req:
-                       rValue.append(" ".join(license_req) + " license(s)")
+                       rValue += [x+" license" for x in license_req]
        
        return rValue
 
@@ -4459,6 +4488,8 @@ class vardbapi(dbapi):
                        return []
                returnme=[]
                for x in list:
+                       if x.startswith("."):
+                               continue
                        if x[0] == '-':
                                #writemsg(red("INCOMPLETE MERGE:")+str(x[len("-MERGING-"):])+"\n")
                                continue