Old "Change USE" message: Don't screw up if the highest version is masked and parent...
[portage.git] / bin / portageq
index e18760ce8936142fa74dca8e284cfabd3d0c0dc1..940575b1fee90f7e21b5e157657fb6e8d64cd9df 100755 (executable)
@@ -1,7 +1,8 @@
 #!/usr/bin/python -O
 # Copyright 1999-2006 Gentoo Foundation
 # Distributed under the terms of the GNU General Public License v2
-# $Id$
+
+from __future__ import print_function
 
 import sys
 # This block ensures that ^C interrupts are handled quietly.
@@ -41,8 +42,15 @@ except ImportError:
        import portage
 del pym_path
 
+from portage import os
 from portage.util import writemsg, writemsg_stdout
 
+def eval_atom_use(atom):
+       if 'USE' in os.environ:
+               use = frozenset(os.environ['USE'].split())
+               atom = atom.evaluate_conditionals(use)
+       return atom
+
 #-----------------------------------------------------------------------------
 #
 # To add functionality to this tool, add a function below.
@@ -69,20 +77,32 @@ def has_version(argv):
        Return code 0 if it's available, 1 otherwise.
        """
        if (len(argv) < 2):
-               print "ERROR: insufficient parameters!"
+               print("ERROR: insufficient parameters!")
                sys.exit(2)
-       if atom_validate_strict and not portage.isvalidatom(argv[1]):
-               portage.writemsg("ERROR: Invalid atom: '%s'\n" % argv[1],
-                       noiselevel=-1)
-               return 2
        try:
-               mylist=portage.db[argv[0]]["vartree"].dbapi.match(argv[1])
+               atom = portage.dep.Atom(argv[1])
+       except portage.exception.InvalidAtom:
+               if atom_validate_strict:
+                       portage.writemsg("ERROR: Invalid atom: '%s'\n" % argv[1],
+                               noiselevel=-1)
+                       return 2
+               else:
+                       atom = argv[1]
+       else:
+               atom = eval_atom_use(atom)
+
+       try:
+               mylist = portage.db[argv[0]]["vartree"].dbapi.match(atom)
                if mylist:
                        sys.exit(0)
                else:
                        sys.exit(1)
        except KeyError:
                sys.exit(1)
+       except portage.exception.InvalidAtom:
+               portage.writemsg("ERROR: Invalid atom: '%s'\n" % argv[1],
+                       noiselevel=-1)
+               return 2
 has_version.uses_root = True
 
 
@@ -91,15 +111,22 @@ def best_version(argv):
        Returns category/package-version (without .ebuild).
        """
        if (len(argv) < 2):
-               print "ERROR: insufficient parameters!"
+               print("ERROR: insufficient parameters!")
                sys.exit(2)
-       if atom_validate_strict and not portage.isvalidatom(argv[1]):
-               portage.writemsg("ERROR: Invalid atom: '%s'\n" % argv[1],
-                       noiselevel=-1)
-               return 2
        try:
-               mylist=portage.db[argv[0]]["vartree"].dbapi.match(argv[1])
-               print portage.best(mylist)
+               atom = portage.dep.Atom(argv[1])
+       except portage.exception.InvalidAtom:
+               if atom_validate_strict:
+                       portage.writemsg("ERROR: Invalid atom: '%s'\n" % argv[1],
+                               noiselevel=-1)
+                       return 2
+               else:
+                       atom = argv[1]
+       else:
+               atom = eval_atom_use(atom)
+       try:
+               mylist = portage.db[argv[0]]["vartree"].dbapi.match(atom)
+               print(portage.best(mylist))
        except KeyError:
                sys.exit(1)
 best_version.uses_root = True
@@ -110,22 +137,19 @@ def mass_best_version(argv):
        Returns category/package-version (without .ebuild).
        """
        if (len(argv) < 2):
-               print "ERROR: insufficient parameters!"
+               print("ERROR: insufficient parameters!")
                sys.exit(2)
        try:
                for pack in argv[1:]:
                        mylist=portage.db[argv[0]]["vartree"].dbapi.match(pack)
-                       print pack+":"+portage.best(mylist)
+                       print(pack+":"+portage.best(mylist))
        except KeyError:
                sys.exit(1)
 mass_best_version.uses_root = True
 
 def metadata(argv):
-       """<root> <pkgtype> <category/package> [<key>]+
-       Returns metadata values for the specified package.
-       """
        if (len(argv) < 4):
-               print >> sys.stderr, "ERROR: insufficient parameters!"
+               print("ERROR: insufficient parameters!", file=sys.stderr)
                sys.exit(2)
 
        root, pkgtype, pkgspec = argv[0:3]
@@ -135,7 +159,7 @@ def metadata(argv):
                "binary":"bintree",
                "installed":"vartree"}
        if pkgtype not in type_map:
-               print >> sys.stderr, "Unrecognized package type: '%s'" % pkgtype
+               print("Unrecognized package type: '%s'" % pkgtype, file=sys.stderr)
                sys.exit(1)
        trees = portage.db
        if os.path.realpath(root) == os.path.realpath(portage.settings["ROOT"]):
@@ -145,9 +169,16 @@ def metadata(argv):
                                pkgspec, metakeys)
                        writemsg_stdout(''.join('%s\n' % x for x in values), noiselevel=-1)
        except KeyError:
-               print >> sys.stderr, "Package not found: '%s'" % pkgspec
+               print("Package not found: '%s'" % pkgspec, file=sys.stderr)
                sys.exit(1)
 
+metadata.__doc__ = """
+<root> <pkgtype> <category/package> [<key>]+
+Returns metadata values for the specified package.
+Available keys: %s
+"""  % ','.join(sorted(x for x in portage.auxdbkeys \
+if not x.startswith('UNUSED_')))
+
 metadata.uses_root = True
 
 def contents(argv):
@@ -157,7 +188,7 @@ def contents(argv):
        <root>.
        """
        if len(argv) != 2:
-               print "ERROR: expected 2 parameters, got %d!" % len(argv)
+               print("ERROR: expected 2 parameters, got %d!" % len(argv))
                return 2
 
        root, cpv = argv
@@ -219,7 +250,7 @@ def owners(argv):
        owners = vardb._owners.get_owners(files)
 
        msg = []
-       for pkg, owned_files in owners.iteritems():
+       for pkg, owned_files in owners.items():
                cpv = pkg.mycpv
                msg.append("%s\n" % cpv)
                for f in sorted(owned_files):
@@ -349,13 +380,13 @@ def best_visible(argv):
        Returns category/package-version (without .ebuild).
        """
        if (len(argv) < 2):
-               print "ERROR: insufficient parameters!"
+               print("ERROR: insufficient parameters!")
                sys.exit(2)
        try:
                mylist=portage.db[argv[0]]["porttree"].dbapi.match(argv[1])
                visible=portage.best(mylist)
                if visible:
-                       print visible
+                       print(visible)
                        sys.exit(0)
                else:
                        sys.exit(1)
@@ -369,12 +400,12 @@ def mass_best_visible(argv):
        Returns category/package-version (without .ebuild).
        """
        if (len(argv) < 2):
-               print "ERROR: insufficient parameters!"
+               print("ERROR: insufficient parameters!")
                sys.exit(2)
        try:
                for pack in argv[1:]:
                        mylist=portage.db[argv[0]]["porttree"].dbapi.match(pack)
-                       print pack+":"+portage.best(mylist)
+                       print(pack+":"+portage.best(mylist))
        except KeyError:
                sys.exit(1)
 mass_best_visible.uses_root = True
@@ -385,13 +416,13 @@ def all_best_visible(argv):
        Returns all best_visible packages (without .ebuild).
        """
        if (len(argv) < 1):
-               print "ERROR: insufficient parameters!"
+               print("ERROR: insufficient parameters!")
        
        #print portage.db[argv[0]]["porttree"].dbapi.cp_all()
        for pkg in portage.db[argv[0]]["porttree"].dbapi.cp_all():
                mybest=portage.best(portage.db[argv[0]]["porttree"].dbapi.match(pkg))
                if mybest:
-                       print mybest
+                       print(mybest)
 all_best_visible.uses_root = True
 
 
@@ -402,7 +433,7 @@ def match(argv):
        be listed.
        """
        if len(argv) != 2:
-               print "ERROR: expected 2 parameters, got %d!" % len(argv)
+               print("ERROR: expected 2 parameters, got %d!" % len(argv))
                sys.exit(2)
        root, atom = argv
        if atom:
@@ -415,7 +446,7 @@ def match(argv):
                results = portage.db[root]["vartree"].dbapi.cpv_all()
                results.sort()
        for cpv in results:
-               print cpv
+               print(cpv)
 match.uses_root = True
 
 
@@ -433,49 +464,49 @@ def gentoo_mirrors(argv):
        """
        Returns the mirrors set to use in the portage configuration.
        """
-       print portage.settings["GENTOO_MIRRORS"]
+       print(portage.settings["GENTOO_MIRRORS"])
 
 
 def portdir(argv):
        """
        Returns the PORTDIR path.
        """
-       print portage.settings["PORTDIR"]
+       print(portage.settings["PORTDIR"])
 
 
 def config_protect(argv):
        """
        Returns the CONFIG_PROTECT paths.
        """
-       print portage.settings["CONFIG_PROTECT"]
+       print(portage.settings["CONFIG_PROTECT"])
 
 
 def config_protect_mask(argv):
        """
        Returns the CONFIG_PROTECT_MASK paths.
        """
-       print portage.settings["CONFIG_PROTECT_MASK"]
+       print(portage.settings["CONFIG_PROTECT_MASK"])
 
 
 def portdir_overlay(argv):
        """
        Returns the PORTDIR_OVERLAY path.
        """
-       print portage.settings["PORTDIR_OVERLAY"]
+       print(portage.settings["PORTDIR_OVERLAY"])
 
 
 def pkgdir(argv):
        """
        Returns the PKGDIR path.
        """
-       print portage.settings["PKGDIR"]
+       print(portage.settings["PKGDIR"])
 
 
 def distdir(argv):
        """
        Returns the DISTDIR path.
        """
-       print portage.settings["DISTDIR"]
+       print(portage.settings["DISTDIR"])
 
 
 def envvar(argv):
@@ -488,33 +519,33 @@ def envvar(argv):
                argv.pop(argv.index("-v"))
 
        if len(argv) == 0:
-               print "ERROR: insufficient parameters!"
+               print("ERROR: insufficient parameters!")
                sys.exit(2)
 
        for arg in argv:
                if verbose:
-                       print arg +"='"+ portage.settings[arg] +"'"
+                       print(arg +"='"+ portage.settings[arg] +"'")
                else:
-                       print portage.settings[arg]
+                       print(portage.settings[arg])
 
 def get_repos(argv):
        """<root>
        Returns all repos with names (repo_name file) argv[0] = $ROOT
        """
        if len(argv) < 1:
-               print "ERROR: insufficient parameters!"
+               print("ERROR: insufficient parameters!")
                sys.exit(2)
-       print " ".join(portage.db[argv[0]]["porttree"].dbapi.getRepositories())
+       print(" ".join(portage.db[argv[0]]["porttree"].dbapi.getRepositories()))
 
 def get_repo_path(argv):
        """<root> <repo_id>+
        Returns the path to the repo named argv[1], argv[0] = $ROOT
        """
        if len(argv) < 2:
-               print "ERROR: insufficient parameters!"
+               print("ERROR: insufficient parameters!")
                sys.exit(2)
        for arg in argv[1:]:
-               print portage.db[argv[0]]["porttree"].dbapi.getRepositoryPath(arg)
+               print(portage.db[argv[0]]["porttree"].dbapi.getRepositoryPath(arg))
 
 def list_preserved_libs(argv):
        """<root>
@@ -524,9 +555,9 @@ def list_preserved_libs(argv):
        """
 
        if len(argv) != 1:
-               print "ERROR: wrong number of arguments"
+               print("ERROR: wrong number of arguments")
                sys.exit(2)
-       mylibs = portage.db[argv[0]]["vartree"].dbapi.plib_registry.getPreservedLibs()
+       mylibs = portage.db[argv[0]]["vartree"].dbapi._plib_registry.getPreservedLibs()
        rValue = 0
        msg = []
        for cpv in sorted(mylibs):
@@ -544,42 +575,46 @@ list_preserved_libs.uses_root = True
 # DO NOT CHANGE CODE BEYOND THIS POINT - IT'S NOT NEEDED!
 #
 
+if not portage.const._ENABLE_PRESERVE_LIBS:
+       del list_preserved_libs
+
+non_commands = frozenset(['eval_atom_use', 'exithandler', 'main',
+       'usage', 'writemsg', 'writemsg_stdout'])
+commands = sorted(k for k, v in globals().items() \
+       if type(v) is types.FunctionType and k not in non_commands)
+
 def usage(argv):
-       print ">>> Portage information query tool"
-       print ">>> $Id$"
-       print ">>> Usage: portageq <command> [<option> ...]"
-       print ""
-       print "Available commands:"
+       print(">>> Portage information query tool")
+       print(">>> %s" % portage.VERSION)
+       print(">>> Usage: portageq <command> [<option> ...]")
+       print("")
+       print("Available commands:")
 
        #
        # Show our commands -- we do this by scanning the functions in this
        # file, and formatting each functions documentation.
        #
-       non_commands = frozenset(['exithandler', 'main',
-               'usage', 'writemsg', 'writemsg_stdout'])
-       commands = sorted(k for k, v in globals().iteritems() \
-               if type(v) is types.FunctionType and k not in non_commands)
-
+       help_mode = '--help' in sys.argv
        for name in commands:
                # Drop non-functions
                obj = globals()[name]
 
                doc = obj.__doc__
                if (doc == None):
-                       print "   "+name
-                       print "      MISSING DOCUMENTATION!"
-                       print ""
+                       print("   " + name)
+                       print("      MISSING DOCUMENTATION!")
+                       print("")
                        continue
 
                lines = doc.split("\n")
-               print "   "+name+" "+lines[0].strip()
+               print("   " + name + " " + lines[0].strip())
                if (len(sys.argv) > 1):
-                       if ("--help" not in sys.argv):
+                       if (not help_mode):
                                lines = lines[:-1]
                        for line in lines[1:]:
-                               print "      "+line.strip()
+                               print("      " + line.strip())
        if (len(sys.argv) == 1):
-               print "\nRun portageq with --help for info"
+               print("\nRun portageq with --help for info")
 
 atom_validate_strict = "EBUILD_PHASE" in os.environ
 
@@ -593,7 +628,7 @@ def main():
 
        cmd = sys.argv[1]
        function = globals().get(cmd)
-       if function is None:
+       if function is None or cmd not in commands:
                usage(sys.argv)
                sys.exit(os.EX_USAGE)
        function = globals()[cmd]
@@ -607,9 +642,9 @@ def main():
                os.environ["ROOT"] = sys.argv[2]
 
        args = sys.argv[2:]
-       if args and not isinstance(args[0], unicode):
-               for i in xrange(len(args)):
-                       args[i] = unicode(args[i], encoding='utf_8', errors='replace')
+       if args and sys.hexversion < 0x3000000 and not isinstance(args[0], unicode):
+               for i in range(len(args)):
+                       args[i] = portage._unicode_decode(args[i])
 
        try:
                if uses_root:
@@ -617,17 +652,13 @@ def main():
                retval = function(args)
                if retval:
                        sys.exit(retval)
-       except portage.exception.PermissionDenied, e:
+       except portage.exception.PermissionDenied as e:
                sys.stderr.write("Permission denied: '%s'\n" % str(e))
                sys.exit(e.errno)
-       except portage.exception.ParseError, e:
+       except portage.exception.ParseError as e:
                sys.stderr.write("%s\n" % str(e))
                sys.exit(1)
-       except ValueError, e:
-               if not e.args or \
-                       not hasattr(e.args[0], "__len__") or \
-                       len(e.args[0]) < 2:
-                       raise
+       except portage.exception.AmbiguousPackageName as e:
                # Multiple matches thrown from cpv_expand
                pkgs = e.args[0]
                # An error has occurred so we writemsg to stderr and exit nonzero.