diff options
Diffstat (limited to 'trunk/src/equery/equery')
-rwxr-xr-x | trunk/src/equery/equery | 1865 |
1 files changed, 0 insertions, 1865 deletions
diff --git a/trunk/src/equery/equery b/trunk/src/equery/equery deleted file mode 100755 index fd8fa4f..0000000 --- a/trunk/src/equery/equery +++ /dev/null @@ -1,1865 +0,0 @@ -#!/usr/bin/python -# -# Copyright 2003-2004 Karl Trygve Kalleberg -# Copyright 2003-2004 Gentoo Technologies, Inc. -# Distributed under the terms of the GNU General Public License v2 -# -# $Header$ -# Author: Karl Trygve Kalleberg <karltk@gentoo.org> - -__author__ = "Karl Trygve Kalleberg" -__email__ = "karltk@gentoo.org" -__version__ = "0.1.4" -__productname__ = "equery" -__description__ = "Gentoo Package Query Tool" - -import os -import re -import sys -import time -from glob import glob - -# portage (output module) and gentoolkit need special path modifications -sys.path.insert(0, "/usr/lib/gentoolkit/pym") - -import gentoolkit -try: - import portage -except ImportError: - sys.path.insert(0, "/usr/lib/portage/pym") - import portage - -try: - import portage.checksum as checksum - from portage.util import unique_array -except ImportError: - import portage_checksum as checksum - from portage_util import unique_array - -import gentoolkit.pprinter as pp -from gentoolkit.pprinter import print_info, print_error, print_warn, die - -# Auxiliary functions - -def fileAsStr(name, fdesc, showType=0, showMD5=0, showTimestamp=0): - """ - Return file in fdesc as a filename - @param name: - @param fdesc: - @param showType: - @param showMD5: - @param showTimestamp: - @rtype: string - """ - type = ""; fname = ""; stamp = ""; md5sum = "" - - if fdesc[0] == 'obj': - type = "file" - fname = name - stamp = timestampAsStr(int(fdesc[1])) - md5sum = fdesc[2] - elif fdesc[0] == "dir": - type = "dir" - fname = pp.path(name) - elif fdesc[0] == "sym": - type = "symlink" - stamp = timestampAsStr(int(fdesc[1].replace(")",""))) - tgt = fdesc[2].split()[0] - if Config["piping"]: - fname = name - else: - fname = pp.path_symlink(name + " -> " + tgt) - elif fdesc[0] == "fif": - type = "fifo" - fname = name - elif fdesc[0] == "dev": - type = "device" - fname = name - else: - raise Exception(name + " has unknown type: " + fdesc[0]) - - s = "" - if showType: - s += "%6s " % type - s += fname - if showTimestamp: - s += " " + stamp + " " - if showMD5: - s += " " + md5sum + " " - return s - -def timestampAsStr(timestamp): - return time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(timestamp)) - - -class Command: - """ - Abstract root class for all equery commands - """ - def __init__(self): - pass - def shortHelp(self): - """Return a help formatted to fit a single line, approx 70 characters. - Must be overridden in the subclass.""" - return " - not implemented yet" - def longHelp(self): - """Return full, multiline, color-formatted help. - Must be overridden in the subclass.""" - return "help for syntax and options" - def perform(self, args): - """Stub code for performing the command. - Must be overridden in the subclass""" - pass - def parseArgs(self, args): - """Stub code for parsing command line arguments for this command. - Must be overridden in the subclass.""" - pass - - -class CmdListFiles(Command): - """List files owned by a particular package""" - def __init__(self): - self.default_options = { - "showType": 0, - "showTimestamp": 0, - "showMD5": 0, - "tree": 0, - "filter": None - } - - def parseArgs(self,args): - query = "" - need_help = 0 - opts = self.default_options - for x in args: - if x in ["-h", "--help"]: - need_help = 1 - elif x in ["--md5sum"]: - opts["showMD5"] = 1 - elif x in ["--timestamp"]: - opts["showTimestamp"] = 1 - elif x in ["--type"]: - opts["showType"] = 1 - elif x in ["--tree"]: - opts["tree"] = 1 - elif x[:9] == "--filter=": - opts["filter"] = x[9:].split(',') - elif x[0] == "/": - die(2, "The query '" + pp.pkgquery(x) + "' does not appear to be a valid package specification") - elif x[0] == "-": - print_warn("unknown local option %s, ignoring" % x) - else: - query = x - - if need_help or query == "": - print_info(0, self.longHelp()) - sys.exit(-1) - - return (query, opts) - - def filterContents(self, cnt, filter): - if filter in [None,[]]: - return cnt - - mycnt = {} - - for mytype in filter: - # Filter elements by type (as recorded in CONTENTS). - if mytype in ["dir","obj","sym","dev","fif"]: - for mykey in cnt.keys(): - if cnt[mykey][0] == mytype: - mycnt[mykey] = cnt[mykey] - - if "cmd" in filter: - # List files that are in $PATH. - userpath = map(os.path.normpath,os.environ["PATH"].split(os.pathsep)) - for mykey in cnt.keys(): - if cnt[mykey][0] in ['obj','sym'] \ - and os.path.dirname(mykey) in userpath: - mycnt[mykey] = cnt[mykey] - - if "path" in filter: - # List only dirs where some files where actually installed, - # and also skip their subdirs. - mykeys = cnt.keys() - mykeys.sort() - while len(mykeys): - mykey = mykeys.pop(0) - if cnt[mykey][0] == 'dir': - i = 0 - while i < len(mykeys) : - if cnt[mykeys[i]][0] != "dir" \ - and os.path.dirname(mykeys[i]) == mykey: - mycnt[mykey] = cnt[mykey] - break - i += 1 - if i < len(mykeys): - while len(mykeys) \ - and len(mykey+"/") < len(mykeys[0]) \ - and mykey+"/" == mykeys[0][:len(mykey)+1]: - mykeys.pop(0) - - if "conf" in filter: - # List configuration files. - conf_path = gentoolkit.settings["CONFIG_PROTECT"].split() - conf_mask_path = gentoolkit.settings["CONFIG_PROTECT_MASK"].split() - conf_path = map(os.path.normpath, conf_path) - conf_mask_path = map(os.path.normpath, conf_mask_path) - for mykey in cnt.keys(): - is_conffile = False - if cnt[mykey][0] == 'obj': - for conf_dir in conf_path: - if conf_dir+"/" == mykey[:len(conf_dir)+1]: - is_conffile = True - for conf_mask_dir in conf_mask_path: - if conf_mask_dir+"/" == mykey[:len(conf_mask_dir)+1]: - is_conffile = False - break - break - if is_conffile: - mycnt[mykey] = cnt[mykey] - - - for mydoctype in ["doc","man","info"]: - # List only files from /usr/share/{doc,man,info} - mydocpath = "/usr/share/"+mydoctype+"/" - if mydoctype in filter: - for mykey in cnt.keys(): - if cnt[mykey][0] == 'obj' \ - and mykey[:len(mydocpath)] == mydocpath : - mycnt[mykey] = cnt[mykey] - - return mycnt - - def perform(self, args): - - (query, opts) = self.parseArgs(args) - - # Turn off filtering for tree output - if opts["tree"]: - opts["filter"] = None - - if not Config["piping"] and Config["verbosityLevel"] >= 3: - print_info(3, "[ Searching for packages matching " + pp.pkgquery(query) + "... ]") - - pkgs = gentoolkit.find_installed_packages(query, True) - for x in pkgs: - if not x.is_installed(): - continue - - if not Config["piping"] and Config["verbosityLevel"] >= 3: - print_info(1, pp.section("* ") + "Contents of " + pp.cpv(x.get_cpv()) + ":") - - cnt = self.filterContents(x.get_contents(),opts["filter"]) - - filenames = cnt.keys() - filenames.sort() - - last=[] - for name in filenames: - if not opts["tree"]: - print_info(0, fileAsStr(name, - cnt[name], - showType=opts["showType"], - showTimestamp=opts["showTimestamp"], - showMD5=opts["showMD5"])) - else: - c = name.split( "/" )[1:] - if cnt[name][0] == "dir": - if len(last) == 0: - last = c - print pp.path(" /" + c[0]) - continue - numol = 0 - for d in c: - if d in last: - numol = last.index(d) + 1 - continue - last = c - if len(last) == 1: - print pp.path(" " + last[0]) - continue - print pp.path(" " * ( numol * 3 ) + "> " + "/" + last[-1]) - elif cnt[name][0] == "sym": - print pp.path(" " * ( bl * 3 ) + "+ ") + pp.path_symlink(c[-1] + " -> " + cnt[name][2]) - else: - bl = len(last) - print pp.path(" " * ( bl * 3 ) + "+ ") + c[-1] - - def longHelp(self): - return "List files owned by a particular package\n" + \ - "\n" + \ - "Syntax:\n" + \ - " " + pp.command("files") + pp.localoption(" <local-opts> ") + pp.pkgquery("<cat/>packagename<-version>") + "\n" + \ - "\n" + \ - "Note: category and version parts are optional. \n" + \ - "\n" + \ - pp.localoption("<local-opts>") + " is either of: \n" + \ - " " + pp.localoption("--timestamp") + " - append timestamp\n" + \ - " " + pp.localoption("--md5sum") + " - append md5sum\n" + \ - " " + pp.localoption("--type") + " - prepend file type\n" + \ - " " + pp.localoption("--tree") + " - display results in a tree (turns off other options)\n" + \ - " " + pp.localoption("--filter=<rules>") + " - filter output\n" + \ - " " + pp.localoption("<rules>") + " is a comma separated list of elements you want to see:\n" + \ - " " + " " + pp.localoption("dir") + \ - ", " + pp.localoption("obj") + \ - ", " + pp.localoption("sym") + \ - ", " + pp.localoption("dev") + \ - ", " + pp.localoption("fifo") + \ - ", " + pp.localoption("path") + \ - ", " + pp.localoption("conf") + \ - ", " + pp.localoption("cmd") + \ - ", " + pp.localoption("doc") + \ - ", " + pp.localoption("man") + \ - ", " + pp.localoption("info") - - def shortHelp(self): - return pp.localoption("<local-opts> ") + pp.pkgquery("pkgspec") + " - list files owned by " + pp.pkgquery("pkgspec") - - -class CmdListBelongs(Command): - """List all packages owning a particular file""" - def __init__(self): - self.default_opts = { - "category": "*", - "fullRegex": 0, - "earlyOut": 0, - "nameOnly": 0 - } - - def parseArgs(self, args): - - query = [] - need_help = 0 - opts = self.default_opts - skip = 0 - - for i in xrange(len(args)): - - if skip: - skip -= 1 - continue - x = args[i] - - if x in ["-h","--help"]: - need_help = 1 - break - elif x in ["-c", "--category"]: - opts["category"] = args[i+1] - skip = 1 - elif x in ["-e", "--earlyout"]: - opts["earlyOut"] = 1 - elif x in ["-f", "--full-regex"]: - opts["fullRegex"] = 1 - elif x in ["-n", "--name-only"]: - opts["nameOnly"] = 1 - elif x[0] == "-": - print_warn("unknown local option %s, ignoring" % x) - else: - query.append(x) - - if need_help or query == []: - print_info(0, self.longHelp()) - sys.exit(-1) - - return (query, opts) - - def perform(self, args): - (query, opts) = self.parseArgs(args) - - if opts["fullRegex"]: - q = query - else: - # Trim trailing and multiple slashes from query - for i in range(0, len(query)): - query[i] = re.compile('/+').sub('/', query[i]) - query[i] = query[i].rstrip('/') - q = map(lambda x: ((len(x) and x[0] == "/") and "^" or "/") - + re.escape(x) + "$", query) - try: - q = "|".join(q) - rx = re.compile(q) - except: - die(2, "The query '" + pp.regexpquery(q) + "' does not appear to be a valid regular expression") - - # Pick out only selected categories - cat = opts["category"] - filter_fn = None - if cat != "*": - filter_fn = lambda x: x.find(cat+"/")==0 - - if not Config["piping"] and Config["verbosityLevel"] >= 3: - print_info(3, "[ Searching for file(s) " + pp.regexpquery(",".join(query)) + " in " + pp.cpv(cat) + "... ]") - - matches = portage.db["/"]["vartree"].dbapi.cpv_all() - #matches = gentoolkit.find_all_installed_packages(filter_fn) - - found = 0 - - def dumpToPipe(pkg): - mysplit = pkg.split("/") - cnt = portage.dblink(mysplit[0], mysplit[1], "/", gentoolkit.settings).getcontents() - #cnt = pkg.get_contents() - if not cnt: return - for file in cnt.keys(): - if rx.search(file) and (opts["category"] == "*" or portage.catpkgsplit(pkg)[0] == opts["category"]): - if opts["nameOnly"]: - x = portage.catpkgsplit(pkg) - print x[0]+"/"+x[1] - else: - print pkg - return - - class DummyExp: - pass - - def dumpToScreen(pkg): - mysplit = pkg.split("/") - cnt = portage.dblink(mysplit[0], mysplit[1], "/", gentoolkit.settings).getcontents() - #cnt = pkg.get_contents() - if not cnt: return - for file in cnt.keys(): - if rx.search(file) and (opts["category"] == "*" or portage.catpkgsplit(pkg)[0] == opts["category"]): - if opts["nameOnly"]: - x = portage.catpkgsplit(pkg) - s = x[0]+"/"+x[1] - else: - s = pkg - s += " (" + pp.path(fileAsStr(file, cnt[file])) + ")" - print_info(0, s) - if opts["earlyOut"]: - raise DummyExp - - try: - if Config["piping"]: - map(dumpToPipe, matches) - else: - map(dumpToScreen, matches) - except DummyExp: - pass - - def shortHelp(self): - return pp.localoption("<local-opts> ") + pp.path("files...") + " - list all packages owning " + pp.path("files...") - def longHelp(self): - return "List all packages owning a particular set of files" + \ - "\n" + \ - "\n" + \ - pp.emph("Note: ") + "Normally, only one package will own a file. If multiple packages own the same file, it usually consitutes a problem, and should be reported.\n" + \ - "\n" + \ - "Syntax:\n" + \ - " " + pp.command("belongs") + pp.localoption(" <local-opts> ") + pp.path("filename") + \ - "\n" + \ - pp.localoption("<local-opts>") + " is either of: \n" + \ - " " + pp.localoption("-c, --category cat") + " - only search in category " + \ - pp.pkgquery("cat") + "\n" + \ - " " + pp.localoption("-f, --full-regex") + " - supplied query is a regex\n" + \ - " " + pp.localoption("-e, --earlyout") + " - stop when first match is found\n" + \ - " " + pp.localoption("-n, --name-only") + " - don't print the version." - -class CmdDisplayUSEs(Command): - """Advanced report of a package's USE flags""" - def __init__(self): - self.default_opts = { - "allPackages" : False - } - def parseArgs(self, args): - - query = "" - need_help = 0 - opts = self.default_opts - skip = 0 - - for i in xrange(len(args)): - - if skip: - skip -= 1 - continue - x = args[i] - - if x in ["-h","--help"]: - need_help = 1 - break - elif x in ["-a", "--all"]: - opts["allPackages"] = True - elif x[0] == "-": - print_warn("unknown local option %s, ignoring" % x) - else: - query = x - - if need_help or query == "": - print_info(0, self.longHelp()) - sys.exit(-1) - - return (query, opts) - - def perform(self, args): - - (query, opts) = self.parseArgs(args) - - if not Config["piping"] and Config["verbosityLevel"] >= 3: - print_info(3, "[ Searching for packages matching " + pp.pkgquery(query) + "... ]") - - if not opts["allPackages"]: - matches = gentoolkit.find_installed_packages(query, True) - if not matches: - matches = gentoolkit.find_packages(query, False) - if matches: - matches = gentoolkit.sort_package_list(matches) - matches = matches[-1:] - else: - matches = gentoolkit.find_packages(query, True) - - if not matches: - die(3, "No matching packages found for \"" + pp.pkgquery(query) + "\"") - - - useflags = gentoolkit.settings["USE"].split() - usedesc = {} - uselocaldesc = {} - - # Load global USE flag descriptions - try: - fd = open(gentoolkit.settings["PORTDIR"]+"/profiles/use.desc") - usedesc = {} - for line in fd.readlines(): - if line[0] == "#": - continue - fields = line.split(" - ", 1) - if len(fields) == 2: - usedesc[fields[0].strip()] = fields[1].strip() - except IOError: - print_warn(5, "Could not load USE flag descriptions from " + ppath(gentoolkit.settings["PORTDIR"] + "/profiles/use.desc")) - - # TODO: Add USE_EXPANDED variables to usedesc hash -- Bug #238005 - # Pseudo-code: - # for all files in gentoolkit.settings["PORTDIR"]+"/desc/*.desc - # variable name = <filename>_<field1> - # description = <field 2> - for descfile in glob(gentoolkit.settings["PORTDIR"]+"/profiles/desc/*.desc"): - try: - fd = open(descfile) - for line in fd.readlines(): - if line[0] == "#": - continue - fields = [field.strip() for field in line.split(" - ", 1)] - if len(fields) == 2: - usedesc["%s_%s" % (descfile.split("/")[-1][0:-5], fields[0],)] = fields[1] - except IOError: - print_warn(5, "Could not load USE flag descriptions from " + descfile) - - # Load local USE flag descriptions - try: - fd = open(gentoolkit.settings["PORTDIR"]+"/profiles/use.local.desc") - for line in fd.readlines(): - if line[0] == "#": - continue - fields = line.split(" - ", 1) - if len(fields) == 2: - catpkguse = re.search("(.*):(.*)", fields[0]) - if catpkguse: - if not uselocaldesc.has_key(catpkguse.group(1).strip()): - uselocaldesc[catpkguse.group(1).strip()] = {catpkguse.group(2).strip() : fields[1].strip()} - else: - uselocaldesc[catpkguse.group(1).strip()][catpkguse.group(2).strip()] = fields[1].strip() - except IOError: - print_warn(5, "Could not load USE flag descriptions from " + path(gentoolkit.settings["PORTDIR"] + "/profiles/use.local.desc")) - - if not Config["piping"] and Config["verbosityLevel"] >= 3: - print_info(3, "[ Colour Code : " + pp.useflagon("set") + " " + pp.useflagoff("unset") + " ]") - print_info(3, "[ Legend : Left column (U) - USE flags from make.conf ]") - print_info(3, "[ : Right column (I) - USE flags packages was installed with ]") - - # Iterate through matches, printing a report for each package - matches = gentoolkit.sort_package_list(matches) - matches_found = 0 - for p in matches: - - matches_found += 1 - - bestver = p.get_cpv() - iuse = p.get_env_var("IUSE") - - if iuse: - # Fix Bug #91623 by making sure the list of USE flags is unique - # Added sort to make output prettier - usevar = unique_array(iuse.split()) - - # Remove prefixed +/- from flags in IUSE, Bug #232019 - for i in range(len(usevar)): - if usevar[i][0] == "+" or usevar[i][0] == "-": - usevar[i] = usevar[i][1:] - - usevar.sort() - else: - usevar = [] - - inuse = [] - if p.is_installed(): - used = p.get_use_flags().split() - else: - # cosmetic issue here as noninstalled packages don't have "used" flags - used = useflags - - # store (inuse, inused, flag, desc) - output = [] - - for u in usevar: - inuse = 0 - inused = 0 - try: - desc = usedesc[u] - except KeyError: - try: - desc = uselocaldesc[p.get_category() + "/" + p.get_name()][u] - except KeyError: - desc = "" - - if u in p.get_settings("USE").split(): - inuse = 1 - if u in used: - inused = 1 - - output.append((inuse, inused, u, desc)) - - # pretty print - if output: - if not Config["piping"] and Config["verbosityLevel"] >= 3: - print_info(0, "[ Found these USE variables for " + pp.cpv(bestver) + " ]") - print_info(3, pp.emph(" U I")) - maxflag_len = 0 - for inuse, inused, u, desc in output: - if len(u) > maxflag_len: - maxflag_len = len(u) - - for in_makeconf, in_installed, flag, desc in output: - markers = ["-","+"] - colour = [pp.useflagoff, pp.useflagon] - if Config["piping"]: - print_info(0, markers[in_makeconf] + flag) - else: - if in_makeconf != in_installed: - print_info(0, pp.emph(" %s %s" % (markers[in_makeconf], markers[in_installed])), False) - else: - print_info(0, " %s %s" % (markers[in_makeconf], markers[in_installed]), False) - - print_info(0, " " + colour[in_makeconf](flag.ljust(maxflag_len)), False) - - # print description - if desc: - print_info(0, " : " + desc) - else: - print_info(0, " : <unknown>") - else: - if not Config["piping"] and Config["verbosityLevel"] >= 3: - print_info(1, "[ No USE flags found for " + pp.cpv(p.get_cpv()) + "]") - - if Config["verbosityLevel"] >= 2: - if matches_found == 0: - s = "" - die(3, "No " + s + "packages found for " + pp.pkgquery(query)) - - - def shortHelp(self): - return pp.localoption("<local-opts> ") + pp.pkgquery("pkgspec") + " - display USE flags for " + pp.pkgquery("pkgspec") - def longHelp(self): - return "Display USE flags for a given package\n" + \ - "\n" + \ - "Syntax:\n" + \ - " " + pp.command("uses") + pp.localoption(" <local-opts> ") + pp.pkgquery("pkgspec") + \ - "\n" + \ - pp.localoption("<local-opts>") + " is: \n" + \ - " " + pp.localoption("-a, --all") + " - include all package versions\n" - - -class CmdDisplayDepGraph(Command): - """Display tree graph of dependencies for a query""" - - def __init__(self): - self.default_opts = { - "displayUSEFlags": 1, - "fancyFormatting": 1, - "depth": 0 - } - - def parseArgs(self, args): - - query = "" - need_help = 0 - opts = self.default_opts - skip = 0 - - for i in xrange(len(args)): - - if skip: - skip -= 1 - continue - x = args[i] - - if x in ["-h","--help"]: - need_help = 1 - break - elif x in ["-U","--no-useflags"]: - opts["displayUSEFlags"] = 0 - elif x in ["-l","--linear"]: - opts["fancyFormatting"] = 0 - elif x[:8] == "--depth=": - opts["depth"] = int(x[8:]) - elif x[0] == "-": - print_warn("unknown local option %s, ignoring" % x) - else: - query = x - - if need_help or query == "": - print_info(0, self.longHelp()) - sys.exit(-1) - - return (query, opts) - - def perform(self, args): - (query, opts) = self.parseArgs(args) - - if not Config["piping"] and Config["verbosityLevel"] >= 3: - print_info(3, "[ Searching for packages matching " + pp.pkgquery(query) + "... ]") - - matches = gentoolkit.find_packages(query, True) - - for pkg in matches: - if not Config["piping"] and Config["verbosityLevel"] >= 3: - print_info(3, pp.section("* ") + "dependency graph for " + pp.cpv(pkg.get_cpv())) - else: - print_info(0, pkg.get_cpv() + ":") - - stats = { "maxdepth": 0, "packages": 0 } - self._graph(pkg, opts, stats, 0, [], "") - if not Config["piping"] and Config["verbosityLevel"] >= 3: - print_info(0, "[ " + pp.cpv(pkg.get_cpv()) + " stats: packages (" + pp.number(str(stats["packages"])) + \ - "), max depth (" + pp.number(str(stats["maxdepth"])) + ") ]") - - def _graph(self, pkg, opts, stats, level=0, pkgtbl=[], suffix=""): - - stats["packages"] += 1 - stats["maxdepth"] = max(stats["maxdepth"], level) - - cpv = pkg.get_cpv() - - pfx = "" - if opts["fancyFormatting"]: - pfx = level * " " + "`-- " - print_info(0, pfx + cpv + suffix) - - pkgtbl.append(cpv) - - pkgdeps = pkg.get_runtime_deps() + pkg.get_compiletime_deps() + pkg.get_postmerge_deps() - for x in pkgdeps: - suffix = "" - cpv = x[2] - pkg = gentoolkit.find_best_match(x[0] + cpv) - if not pkg: - print pfx + x[0] + cpv + " (unable to resolve to a package / package masked or removed)" - continue - if pkg.get_cpv() in pkgtbl: - continue - if cpv.find("virtual") == 0: - suffix += " (" + pp.cpv(cpv) + ")" - if len(x[1]) and opts["displayUSEFlags"]: - suffix += " [ " + pp.useflagon(' '.join(x[1])) + " ]" - if (level < opts["depth"] or opts["depth"] <= 0): - pkgtbl = self._graph(pkg, opts, stats, level+1, pkgtbl, suffix) - return pkgtbl - - def shortHelp(self): - return pp.localoption("<local-opts> ") + pp.pkgquery("pkgspec") + " - display a dependency tree for " + pp.pkgquery("pkgspec") - def longHelp(self): - return "Display a dependency tree for a given package\n" + \ - "\n" + \ - "Syntax:\n" + \ - " " + pp.command("depgraph") + pp.localoption(" <local-opts> ") + pp.pkgquery("pkgspec") + \ - "\n" + \ - pp.localoption("<local-opts>") + " is either of: \n" + \ - " " + pp.localoption("-U, --no-useflags") + " - do not show USE flags\n" + \ - " " + pp.localoption("-l, --linear") + " - do not use fancy formatting\n" + \ - " " + pp.localoption(" --depth=n") + " - limit dependency graph to specified depth" - - -class CmdDisplaySize(Command): - """Display disk size consumed by a package""" - def __init__(self): - self.default_opts = { - "regex": 0, - "exact": 0, - "reportSizeInBytes": 0 - } - - def parseArgs(self, args): - - query = "" - need_help = 0 - opts = self.default_opts - skip = 0 - - for i in xrange(len(args)): - - if skip: - skip -= 1 - continue - x = args[i] - - if x in ["-h","--help"]: - need_help = 1 - break - elif x in ["-b","--bytes"]: - opts["reportSizeInBytes"] = 1 - elif x in ["-f", "--full-regex"]: - opts["regex"] = 1 - elif x in ["-e", "--exact-name"]: - opts["exact"] = 1 - elif x[0] == "-": - print_warn("unknown local option %s, ignoring" % x) - else: - query = x - -# if need_help or query == "": - if need_help: - print_info(0, self.longHelp()) - sys.exit(-1) - - return (query, opts) - - def perform(self, args): - (query, opts) = self.parseArgs(args) - - rev = "" - name = "" - ver = "" - cat = "" - - if query != "": - (cat, name, ver, rev) = gentoolkit.split_package_name(query) - if rev == "r0": rev = "" - - # replace empty strings with .* and escape regular expression syntax - if query != "": - if not opts["regex"]: - cat, name, ver, rev = [re.sub('^$', ".*", re.escape(x)) for x in cat, name, ver, rev] - else: - cat, name, ver, rev = [re.sub('^$', ".*", x) for x in cat, name, ver, rev] - - try: - if opts["exact"]: - filter_fn = lambda x: re.match(cat+"/"+name, x) - else: - filter_fn = lambda x: re.match(cat+"/.*"+name, x) - matches = gentoolkit.find_all_installed_packages(filter_fn) - except: - die(2, "The query '" + pp.regexpquery(query) + "' does not appear to be a valid regular expression") - else: - cat, name, ver, rev = [re.sub('^$', ".*", x) for x in cat, name, ver, rev] - matches = gentoolkit.find_all_installed_packages() - - matches = gentoolkit.sort_package_list(matches) - - if not Config["piping"] and Config["verbosityLevel"] >= 3: - print_info(3, "[ Searching for packages matching " + pp.pkgquery(query) + "... ]") - - # If no version supplied, fix regular expression - if ver == ".*": ver = "[0-9]+[^-]*" - - if rev != ".*": # revision supplied - ver = ver + "-" + rev - - if opts["exact"]: - rx = re.compile(cat + "/" + name + "-" + ver) - else: - rx = re.compile(cat + "/.*" + name + ".*-" + ver) - - for pkg in matches: - if rx.search(pkg.get_cpv()): - (size, files, uncounted) = pkg.size() - - if Config["piping"]: - print_info(0, pkg.get_cpv() + ": total(" + str(files) + "), inaccessible(" + str(uncounted) + \ - "), size(" + str(size) + ")") - else: - print_info(0, pp.section("* ") + "size of " + pp.cpv(pkg.get_cpv())) - print_info(0, " Total files : ".rjust(25) + pp.number(str(files))) - - if uncounted: - print_info(0, " Inaccessible files : ".rjust(25) + pp.number(str(uncounted))) - - sz = "%.2f KiB" % (size/1024.0) - if opts["reportSizeInBytes"]: - sz = pp.number(str(size)) + " bytes" - - print_info(0, "Total size : ".rjust(25) + pp.number(sz)) - - - def shortHelp(self): - return pp.localoption("<local-opts> ") + pp.pkgquery("pkgspec") + " - print size of files contained in package " + pp.pkgquery("pkgspec") - def longHelp(self): - return "Print size total size of files contained in a given package" + \ - "\n" + \ - "Syntax:\n" + \ - " " + pp.command("size") + pp.localoption(" <local-opts> ") + pp.pkgquery("pkgspec") + \ - "\n" + \ - pp.localoption("<local-opts>") + " is: \n" + \ - " " + pp.localoption("-b, --bytes") + " - report size in bytes\n" \ - " " + pp.localoption("-f, --full-regex") + " - query is a regular expression\n" + \ - " " + pp.localoption("-e, --exact-name") + " - list only those packages that exactly match\n" - -class CmdDisplayChanges(Command): - """Display changes for pkgQuery""" - pass - -class CheckException: - def __init__(self, s): - self.s = s - -class CmdCheckIntegrity(Command): - """Check timestamps and md5sums for files owned by pkgspec""" - def __init__(self): - self.default_opts = { - "showSummary" : 1, - "showGoodFiles" : 0, - "showBadFiles" : 1, - "checkTimestamp" : 1, - "checkMD5sum": 1 - } - - def parseArgs(self, args): - - query = "" - need_help = 0 - opts = self.default_opts - skip = 0 - - for i in xrange(len(args)): - if skip: - skip -= 1 - continue - x = args[i] - - if x in ["-h","--help"]: - need_help = 1 - break - elif x[0] == "-": - print_warn("unknown local option %s, ignoring" % x) - else: - query = x - - if need_help: - print_info(0, self.longHelp()) - sys.exit(-1) - - return (query, opts) - - def getMD5sum(self, file): - return checksum.perform_md5(file, calc_prelink=1) - - def perform(self, args): - (query, opts) = self.parseArgs(args) - - if query == "": - matches=gentoolkit.find_all_installed_packages() - else: - matches = gentoolkit.find_packages(query, True) - - matches = gentoolkit.sort_package_list(matches) - - for pkg in matches: - if not pkg.is_installed(): - continue - if not Config["piping"] and Config["verbosityLevel"] >= 3: - print_info(1, "[ Checking " + pp.cpv(pkg.get_cpv()) + " ]") - else: - print_info(0, pkg.get_cpv() + ":") - - files = pkg.get_contents() - checked_files = 0 - good_files = 0 - for file in files.keys(): - type = files[file][0] - try: - st = os.lstat(file) - if type == "dir": - if not os.path.isdir(file): - raise CheckException(file + " exists, but is not a directory") - elif type == "obj": - mtime = files[file][1] - md5sum = files[file][2] - if opts["checkMD5sum"]: - try: - actual_checksum = self.getMD5sum(file) - except: - raise CheckException("Failed to calculate MD5 sum for " + file) - - if self.getMD5sum(file) != md5sum: - raise CheckException(file + " has incorrect md5sum") - if opts["checkTimestamp"]: - if int(st.st_mtime) != int(mtime): - raise CheckException(file + (" has wrong mtime (is %d, should be %s)" % (st.st_mtime, mtime))) - elif type == "sym": - # FIXME: nastry strippery; portage should have this fixed! - t = files[file][2] - # target = os.path.normpath(t.strip()) - target = t.strip() - if not os.path.islink(file): - raise CheckException(file + " exists, but is not a symlink") - tgt = os.readlink(file) - if tgt != target: - raise CheckException(file + " does not point to " + target) - elif type == "fif": - pass - else: - pp.print_error(file) - pp.print_error(files[file]) - pp.print_error(type) - raise CheckException(file + " has unknown type " + type) - good_files += 1 - except CheckException, (e): - print_error(e.s) - except OSError: - print_error(file + " does not exist") - checked_files += 1 - print_info(0, pp.section(" * ") + pp.number(str(good_files)) + " out of " + pp.number(str(checked_files)) + " files good") - - def shortHelp(self): - return pp.pkgquery("pkgspec") + " - check MD5sums and timestamps of " + pp.pkgquery("pkgspec") + "'s files" - def longHelp(self): - return "Check package's files against recorded MD5 sums and timestamps" + \ - "\n" + \ - "Syntax:\n" + \ - " " + pp.command("check") + pp.pkgquery(" pkgspec") - -class CmdDisplayStatistics(Command): - """Display statistics about installed and uninstalled packages""" - pass - -class CmdWhich(Command): - """Display the filename of the ebuild for a given package - that would be used by Portage with the current configuration.""" - def __init__(self): - self.default_opts = { - "includeMasked": False - } - - def parseArgs(self, args): - - query = "" - need_help = 0 - opts = self.default_opts - skip = 0 - - for i in xrange(len(args)): - - if skip: - skip -= 1 - continue - x = args[i] - - if x in ["-h","--help"]: - need_help = 1 - break - elif x in ["-m", "--include-masked"]: - opts["includeMasked"] = True - elif x[0] == "-": - print_warn("unknown local option %s, ignoring" % x) - else: - query = x - - if need_help or query == "": - print_info(0, self.longHelp()) - sys.exit(-1) - - return (query, opts) - - def perform(self, args): - (query, opts) = self.parseArgs(args) - - matches = gentoolkit.find_packages(query, opts["includeMasked"]) - matches = gentoolkit.sort_package_list(matches) - - if matches: - pkg = matches[-1] - ebuild_path = pkg.get_ebuild_path() - if ebuild_path: - print_info(0, os.path.normpath(ebuild_path)) - else: - print_warn("There are no ebuilds to satisfy %s" % pkg.get_name()) - else: - print_error("No masked or unmasked packages found for " + pp.pkgquery(query)) - - def shortHelp(self): - return pp.pkgquery("pkgspec") + " - print full path to ebuild for package " + pp.pkgquery("pkgspec") - def longHelp(self): - # Not documenting --include-masked at this time, since I'm not sure that it is needed. - FuzzyRay - return "Print full path to ebuild for a given package" + \ - "\n" + \ - "Syntax:\n" + \ - " " + pp.command("which ") + pp.pkgquery("pkgspec") - -class CmdListGLSAs(Command): - """List outstanding GLSAs.""" - pass - -class CmdListDepends(Command): - """List all packages directly or indirectly depending on pkgQuery""" - def __init__(self): - self.default_opts = { - "onlyDirect": 1, - "onlyInstalled": 1, - "spacing": 0, - "depth": -1 - } - # Used to cache and detect looping - self.pkgseen = [] - self.pkglist = [] - self.pkgdeps = {} - self.deppkgs = {} - - def parseArgs(self, args): - - query = "" - need_help = 0 - opts = self.default_opts - skip = 0 - - for i in xrange(len(args)): - if skip: - skip -= 1 - continue - x = args[i] - - if x in ["-h","--help"]: - need_help = 1 - break - elif x in ["-d", "--direct"]: - opts["onlyDirect"] = 1 - elif x in ["-D", "--indirect"]: - opts["onlyDirect"] = 0 - elif x in ["-a", "--all-packages"]: - opts["onlyInstalled"] = 0 - elif x[:10] == "--spacing=": - opts["spacing"] = int(x[10:]) - elif x[:8] == "--depth=": - opts["depth"] = int(x[8:]) - elif x[0] == "-": - print_warn("unknown local option %s, ignoring" % x) - else: - query = x - - if need_help or query == "": - print self.longHelp() - sys.exit(-1) - return (query, opts) - - def perform(self, args): - - (query, opts) = self.parseArgs(args) - - # We call ourself recursively if --indirect specified. spacing is used to control printing the tree. - spacing = opts["spacing"] - - if not Config["piping"] and Config["verbosityLevel"] >= 3 and not spacing: - print_info(3, "[ Searching for packages depending on " + pp.pkgquery(query) + "... ]") - - isdepend = gentoolkit.split_package_name(query) - isdepends = map((lambda x: x.get_cpv()), gentoolkit.find_packages(query)) - if not isdepends: - print_warn("Warning: No packages found matching %s" % query) - - # Cache the list of packages - if not self.pkglist: - if opts["onlyInstalled"]: - packages = gentoolkit.find_all_installed_packages() - else: - packages = gentoolkit.find_all_packages() - - packages = gentoolkit.sort_package_list(packages) - self.pkglist = packages - else: - packages = self.pkglist - - for pkg in packages: - pkgcpv = pkg.get_cpv() - if not pkgcpv in self.pkgdeps: - try: - deps = pkg.get_runtime_deps() + pkg.get_compiletime_deps() + pkg.get_postmerge_deps() - except KeyError, e: - # If the ebuild is not found... - continue - # Remove duplicate deps - deps = unique_array(deps) - self.pkgdeps[pkgcpv] = deps - else: - deps = self.pkgdeps[pkgcpv] - isdep = 0 - for dependency in deps: - # TODO determine if dependency is enabled by USE flag - # Find all packages matching the dependency - depstr = dependency[0]+dependency[2] - if not depstr in self.deppkgs: - try: - depcpvs = map((lambda x: x.get_cpv()), gentoolkit.find_packages(depstr)) - self.deppkgs[depstr] = depcpvs - except KeyError, e: - print_warn("") - print_warn("Package: " + pkgcpv + " contains invalid dependency specification.") - print_warn("Portage error: " + str(e)) - print_warn("") - continue - else: - depcpvs = self.deppkgs[depstr] - for x in depcpvs: - cpvs=gentoolkit.split_package_name(x) - if x in isdepends: - cat_match=1 - name_match=1 - ver_match=1 - else: - cat_match=0 - name_match=0 - ver_match=0 - # Match Category - if not isdepend[0] or cpvs[0] == isdepend[0]: - cat_match=1 - # Match Name - if cpvs[1] == isdepend[1]: - name_match=1 - # Match Version - if not isdepend[2] or ( cpvs[2] == isdepend[2] and (isdepend[3] \ - or isdepend[3] == "r0" or cpvs[3] == isdepend[3])): - ver_match=1 - - if cat_match and ver_match and name_match: - if not isdep: - if dependency[1]: - if not Config["piping"] and Config["verbosityLevel"] >= 3: - print " " * (spacing * 2) + pp.cpv(pkg.get_cpv()), - print "(" + \ - pp.useflag(" & ".join(dependency[1]) + "? ") + \ - pp.pkgquery(dependency[0]+dependency[2]) + ")" - else: - print " " * (spacing * 2) + pkg.get_cpv() - else: - if not Config["piping"] and Config["verbosityLevel"] >= 3: - print " " * (spacing * 2) + pp.cpv(pkg.get_cpv()), - print "(" + pp.pkgquery(dependency[0]+dependency[2]) + ")" - else: - print " " * (spacing * 2) + pkg.get_cpv() - isdep = 1 - elif not Config["piping"] and Config["verbosityLevel"] >= 3: - if dependency[1]: - print " "*len(pkg.get_cpv()) + " " * (spacing * 2) + \ - " (" + pp.useflag("&".join(dependency[1]) + "? ") + \ - pp.pkgquery(dependency[0]+dependency[2]) + ")" - else: - print " "*len(pkg.get_cpv()) + " " * (spacing * 2) + " (" + \ - pp.pkgquery(dependency[0]+dependency[2]) + ")" - - break - - # if --indirect specified, call ourselves again with the dependency - # Do not call, if we have already called ourselves. - if isdep and not opts["onlyDirect"] and pkg.get_cpv() not in self.pkgseen \ - and (spacing < opts["depth"] or opts["depth"] == -1): - self.pkgseen.append(pkg.get_cpv()) - self.perform(['=' + pkg.get_cpv(), '--indirect', '--spacing=' + str(int(opts["spacing"]+1))]) - opts["spacing"] = spacing; - - - def shortHelp(self): - return pp.localoption("<local-opts> ") + pp.pkgquery("pkgspec") + " - list all direct dependencies matching " + \ - pp.pkgquery("pkgspec") - - def longHelp(self): - return "List all direct dependencies matching a query pattern" + \ - "\n" + \ - "Syntax:\n" + \ - " " + pp.command("depends") + pp.localoption(" <local-opts> ") + pp.pkgquery("pkgspec") + \ - "\n" + \ - pp.localoption("<local-opts>") + " is either of: \n" + \ - " " + pp.localoption("-a, --all-packages") + " - search in all available packages (slow)\n" + \ - " " + pp.localoption("-d, --direct") + " - search direct dependencies only (default)\n" + \ - " " + pp.localoption("-D, --indirect") + " - search indirect dependencies (VERY slow)\n" + \ - " " + pp.localoption(" --depth=n") + " - limit indirect dependency tree to specified depth" - - -class CmdListPackages(Command): - """List packages satisfying pkgQuery""" - def __init__(self): - self.default_opts = { - "category": "*", - "includeInstalled": 1, - "includePortTree": 0, - "includeOverlayTree": 0, - "includeMasked": 1, - "regex": 0, - "exact": 0, - "duplicates": 0 - } - - def parseArgs(self, args): - - query = "" - need_help = 0 - opts = self.default_opts - skip = 0 - - for i in xrange(len(args)): - - if skip: - skip -= 1 - continue - x = args[i] - - if x in ["-h","--help"]: - need_help = 1 - break - elif x in ["-i", "--installed"]: - opts["includeInstalled"] = 1 - elif x in ["-I", "--exclude-installed"]: - # If -I is the only option, warn - # (warning located in perform()) - opts["includeInstalled"] = 0 - elif x in ["-p", "--portage-tree"]: - opts["includePortTree"] = 1 - elif x in ["-o", "--overlay-tree"]: - opts["includeOverlayTree"] = 1 - elif x in ["-m", "--exclude-masked"]: - opts["includeMasked"] = 0 - elif x in ["-f", "--full-regex"]: - opts["regex"] = 1 - elif x in ["-e", "--exact-name"]: - opts["exact"] = 1 - elif x in ["-d", "--duplicates"]: - opts["duplicates"] = 1 - elif x[0] == "-": - print_warn("unknown local option %s, ignoring" % x) - else: - query = x - - # Only search installed packages when listing duplicated packages - if opts["duplicates"]: - opts["includeInstalled"] = 1 - opts["includePortTree"] = 0 - opts["includeOverlayTree"] = 0 - - if need_help: - print_info(0, self.longHelp()) - sys.exit(-1) - - return (query, opts) - - def perform(self, args): - (query, opts) = self.parseArgs(args) - - rev = "" - name = "" - ver = "" - cat = "" - - if query != "": - try: (cat, name, ver, rev) = gentoolkit.split_package_name(query) - except ValueError, e: - if str(e) == 'too many values to unpack': - print_error("A pattern to match against package names was expected, ") - warn_msg = "but %s has too many slashes ('/') to match any package." - die (1, warn_msg % query) - else: raise ValueError(e) - if rev == "r0": rev = "" - - package_finder = None - - if opts["includeInstalled"]: - if opts["includePortTree"] or opts["includeOverlayTree"]: - package_finder = gentoolkit.find_all_packages - else: - package_finder = gentoolkit.find_all_installed_packages - elif opts["includePortTree"] or opts["includeOverlayTree"]: - package_finder = gentoolkit.find_all_uninstalled_packages - else: - # -I was specified, and no selection of what packages to list was made - print_warn("With -I you must specify one of -i, -p or -o. Assuming -p") - opts["includePortTree"] = 1 - package_finder = gentoolkit.find_all_uninstalled_packages - - filter_fn = None - - if Config["verbosityLevel"] >= 3: - scat = "'" + cat + "'" - if not cat: - scat = "all categories" - sname = "package '" + name + "'" - if not name: - sname = "all packages" - if not Config["piping"] and Config["verbosityLevel"] >= 3: - print_info(1, "[ Searching for " + pp.cpv(sname) + " in " + pp.cpv(scat) + " among: ]") - - # replace empty strings with .* and escape regular expression syntax - if query != "": - if not opts["regex"]: - cat, name, ver, rev = [re.sub('^$', ".*", re.escape(x)) for x in cat, name, ver, rev] - else: - cat, name, ver, rev = [re.sub('^$', ".*", x) for x in cat, name, ver, rev] - - try: - if opts["exact"]: - filter_fn = lambda x: re.match(cat+"/"+name, x) - else: - filter_fn = lambda x: re.match(cat+"/.*"+name, x) - matches = package_finder(filter_fn) - except: - die(2, "The query '" + pp.regexpquery(query) + "' does not appear to be a valid regular expression") - else: - cat, name, ver, rev = [re.sub('^$', ".*", x) for x in cat, name, ver, rev] - filter_fn = lambda x: True - matches = package_finder(filter_fn) - - # Find duplicate packages - if opts["duplicates"]: - dups = {} - newmatches = [] - for pkg in matches: - mykey = pkg.get_category() + "/" + pkg.get_name() - if dups.has_key(mykey): - dups[mykey].append(pkg) - else: - dups[mykey] = [pkg] - - for mykey in dups.keys(): - if len(dups[mykey]) > 1: - newmatches += dups[mykey] - - matches = newmatches - - matches = gentoolkit.sort_package_list(matches) - - # If no version supplied, fix regular expression - if ver == ".*": ver = "[0-9]+[^-]*" - - if rev != ".*": # revision supplied - ver = ver + "-" + rev - - if opts["exact"]: - rx = re.compile(cat + "/" + name + "-" + ver) - else: - rx = re.compile(cat + "/.*" + name + ".*-" + ver) - - if opts["includeInstalled"]: - self._print_installed(matches, rx) - - if opts["includePortTree"]: - self._print_porttree(matches, rx) - - if opts["includeOverlayTree"]: - self._print_overlay(matches, rx) - - def _get_mask_status(self, pkg): - pkgmask = 0 - if pkg.is_masked(): - # Uncomment to only have package masked files show an 'M' - # maskreasons = portage.getmaskingstatus(pkg.get_cpv()) - # if "package.mask" in maskreasons: - pkgmask = pkgmask + 3 - keywords = pkg.get_env_var("KEYWORDS").split() - if gentoolkit.settings["ARCH"] not in keywords: - if "~" + gentoolkit.settings["ARCH"] in keywords: - pkgmask = pkgmask + 1 - elif "-" + gentoolkit.settings["ARCH"] in keywords or "-*" in keywords: - pkgmask = pkgmask + 2 - return pkgmask - - def _generic_print(self, header, exclude, matches, rx, status): - if Config["verbosityLevel"] >= 3: - print_info(1, header) - - pfxmodes = [ "---", "I--", "-P-", "--O" ] - maskmodes = [ " ", " ~", " -", "M ", "M~", "M-" ] - - for pkg in matches: - if exclude(pkg): - continue - - pkgmask = self._get_mask_status(pkg) - - slot = pkg.get_env_var("SLOT") - - if rx.search(pkg.get_cpv()): - if Config["piping"]: - print_info(0, pkg.get_cpv()) - else: - print_info(0, "[" + pp.installedflag(pfxmodes[status]) + "] [" + pp.maskflag(maskmodes[pkgmask]) + "] " + pp.cpv(pkg.get_cpv()) + " (" + pp.slot(slot) + ")") - - def _print_overlay(self, matches, rx): - self._generic_print( - pp.section(" *") + " overlay tree (" + pp.path(gentoolkit.settings["PORTDIR_OVERLAY"]) + ")", - lambda x: not x.is_overlay(), - matches, rx, 3) - - def _print_porttree(self, matches, rx): - self._generic_print( - pp.section(" *") + " Portage tree (" + pp.path(gentoolkit.settings["PORTDIR"]) + ")", - lambda x: x.is_overlay() or x.is_installed(), - matches, rx, 2) - - def _print_installed(self, matches, rx): - self._generic_print( - pp.section(" *") + " installed packages", - lambda x: not x.is_installed(), - matches, rx, 1) - - def shortHelp(self): - return pp.localoption("<local-opts> ") + pp.pkgquery("pkgspec") + " - list all packages matching " + pp.pkgquery("pkgspec") - def longHelp(self): - return "List all packages matching a query pattern" + \ - "\n" + \ - "Syntax:\n" + \ - " " + pp.command("list") + pp.localoption(" <local-opts> ") + pp.pkgquery("pkgspec") + \ - "\n" + \ - pp.localoption("<local-opts>") + " is either of: \n" + \ - " " + pp.localoption("-i, --installed") + " - search installed packages (default)\n" + \ - " " + pp.localoption("-I, --exclude-installed") + " - do not search installed packages\n" + \ - " " + pp.localoption("-p, --portage-tree") + " - also search in portage tree (" + gentoolkit.settings["PORTDIR"] + ")\n" + \ - " " + pp.localoption("-o, --overlay-tree") + " - also search in overlay tree (" + gentoolkit.settings["PORTDIR_OVERLAY"] + ")\n" + \ - " " + pp.localoption("-f, --full-regex") + " - query is a regular expression\n" + \ - " " + pp.localoption("-e, --exact-name") + " - list only those packages that exactly match\n" + \ - " " + pp.localoption("-d, --duplicates") + " - list only installed duplicate packages\n" - -class CmdFindUSEs(Command): - """Find all packages with a particular USE flag.""" - def __init__(self): - self.default_opts = { - "category": "*", - "includeInstalled": 1, - "includePortTree": 0, - "includeOverlayTree": 0, - "includeMasked": 1, - "regex": 0 - } - - def parseArgs(self, args): - - query = "" - need_help = 0 - opts = self.default_opts - skip = 0 - - for i in xrange(len(args)): - - if skip: - skip -= 1 - continue - x = args[i] - - if x in ["-h","--help"]: - need_help = 1 - break - elif x in ["-i", "--installed"]: - opts["includeInstalled"] = 1 - elif x in ["-I", "--exclude-installed"]: - opts["includeInstalled"] = 0 - elif x in ["-p", "--portage-tree"]: - opts["includePortTree"] = 1 - elif x in ["-o", "--overlay-tree"]: - opts["includeOverlayTree"] = 1 - elif x in ["-m", "--exclude-masked"]: - opts["includeMasked"] = 0 - elif x[0] == "-": - print_warn("unknown local option %s, ignoring" % x) - else: - query = x - - if need_help: - print_info(0, self.longHelp()) - sys.exit(-1) - - return (query, opts) - - def perform(self, args): - (query, opts) = self.parseArgs(args) - - rev = ".*" - name = ".*" - ver = ".*" - cat = ".*" - - package_finder = None - - if opts["includeInstalled"] and (opts["includePortTree"] or opts["includeOverlayTree"]): - package_finder = gentoolkit.find_all_packages - elif opts["includeInstalled"]: - package_finder = gentoolkit.find_all_installed_packages - elif opts["includePortTree"] or opts["includeOverlayTree"]: - package_finder = gentoolkit.find_all_uninstalled_packages - - if not package_finder: - die(2,"You must specify one of -i, -p or -o") - - filter_fn = lambda x: True - - if Config["verbosityLevel"] >= 3: - scat = "'" + cat + "'" - if cat == ".*": - scat = "all categories" - if not Config["piping"]: - print_info(2, "[ Searching for USE flag " + pp.useflag(query) + " in " + pp.cpv(scat) + " among: ]") - if opts["includeInstalled"]: - print_info(1, pp.section(" *") + " installed packages") - if opts["includePortTree"]: - print_info(1, pp.section(" *") + " Portage tree (" + pp.path(gentoolkit.settings["PORTDIR"]) + ")") - if opts["includeOverlayTree"]: - print_info(1, pp.section(" *") + " overlay tree (" + pp.path(gentoolkit.settings["PORTDIR_OVERLAY"]) + ")") - - matches = package_finder(filter_fn) - - rx = re.compile(cat + "/" + name + "-" + ver + "(-" + rev + ")?") - pfxmodes = [ "---", "I--", "-P-", "--O" ] - maskmodes = [ " ", " ~", " -", "M ", "M~", "M-" ] - for pkg in matches: - status = 0 - if pkg.is_installed(): - status = 1 - elif pkg.is_overlay(): - status = 3 - else: - status = 2 - - useflags = pkg.get_env_var("IUSE").split() - useflags = [f.lstrip("+-") for f in useflags] - - if query not in useflags: - continue - - # Determining mask status - pkgmask = 0 - if pkg.is_masked(): - pkgmask = pkgmask + 3 - keywords = pkg.get_env_var("KEYWORDS").split() - if "~"+gentoolkit.settings["ARCH"] in keywords: - pkgmask = pkgmask + 1 - elif "-*" in keywords or "-"+gentoolkit.settings["ARCH"] in keywords: - pkgmask = pkgmask + 2 - - # Determining SLOT value - slot = pkg.get_env_var("SLOT") - - if (status == 1 and opts["includeInstalled"]) or \ - (status == 2 and opts["includePortTree"]) or \ - (status == 3 and opts["includeOverlayTree"]): - if Config["piping"]: - print_info(0, pkg.get_cpv()) - else: - print_info(0, "[" + pp.installedflag(pfxmodes[status]) + "] [" + pp.maskflag(maskmodes[pkgmask]) + "] " + pp.cpv(pkg.get_cpv()) + " (" + pp.slot(slot) + ")") - - def shortHelp(self): - return pp.localoption("<local-opts> ") + pp.pkgquery("useflag") + " - list all packages with " + pp.pkgquery("useflag") - def longHelp(self): - return "List all packages with a particular USE flag" + \ - "\n" + \ - "Syntax:\n" + \ - " " + pp.command("list") + pp.localoption(" <local-opts> ") + pp.pkgquery("useflag") + \ - "\n" + \ - pp.localoption("<local-opts>") + " is either of: \n" + \ - " " + pp.localoption("-i, --installed") + " - search installed packages (default)\n" + \ - " " + pp.localoption("-I, --exclude-installed") + " - do not search installed packages\n" + \ - " " + pp.localoption("-p, --portage-tree") + " - also search in portage tree (" + gentoolkit.settings["PORTDIR"] + ")\n" + \ - " " + pp.localoption("-o, --overlay-tree") + " - also search in overlay tree (" + gentoolkit.settings["PORTDIR_OVERLAY"] + ")\n" - -# -# Command line tokens to commands mapping -# - -Known_commands = { - "list" : CmdListPackages(), - "files" : CmdListFiles(), - "belongs" : CmdListBelongs(), - "depends" : CmdListDepends(), - "hasuse" : CmdFindUSEs(), - "uses" : CmdDisplayUSEs(), - "depgraph" : CmdDisplayDepGraph(), - "changes" : CmdDisplayChanges(), - "size" : CmdDisplaySize(), - "check" : CmdCheckIntegrity(), - "stats" : CmdDisplayStatistics(), - "glsa" : CmdListGLSAs(), - "which": CmdWhich() - } - -# Short command line tokens - -Short_commands = { - "a" : "glsa", - "b" : "belongs", - "c" : "changes", - "d" : "depends", - "f" : "files", - "g" : "depgraph", - "h" : "hasuse", - "k" : "check", - "l" : "list", - "s" : "size", - "t" : "stats", - "u" : "uses", - "w" : "which" -} - -from gentoolkit import Config - -Config = { - # Query will include packages installed on the system - "installedPackages": 1, - # Query will include packages available for installation - "uninstalledPackages": 0, - # Query will include overlay packages (iff uninstalledPackages==1) - "overlayPackages": 1, - # Query will include masked packages (iff uninstalledPackages==1) - "maskedPackages": 0, - # Query will only consider packages in the following categories, empty means all. - "categoryFilter": [], - # Enable color output (-1 = use Portage setting, 0 = force off, 1 = force on) - "color": -1, - # Level of detail on the output - "verbosityLevel": 3, - # Query will display info for multiple SLOTed versions - "considerDuplicates": 1, - # Are we writing to a pipe? - "piping": 0 -} - -def printVersion(): - """Print the version of this tool to the console.""" - print_info(0, __productname__ + "(" + __version__ + ") - " + \ - __description__) - print_info(0, "Author(s): " + __author__) - -def buildReverseMap(m): - r = {} - for x in m.keys(): - r[m[x]] = x - return r - -def printUsage(): - """Print full usage information for this tool to the console.""" - - short_cmds = buildReverseMap(Short_commands); - - print_info(0, pp.emph("Usage: ") + pp.productname(__productname__) + pp.globaloption(" <global-opts> ") + pp.command("command") + pp.localoption(" <local-opts>")) - print_info(0, "where " + pp.globaloption("<global-opts>") + " is one of") - print_info(0, pp.globaloption(" -q, --quiet") + " - minimal output") - print_info(0, pp.globaloption(" -C, --nocolor") + " - turn off colours") - print_info(0, pp.globaloption(" -h, --help") + " - this help screen") - print_info(0, pp.globaloption(" -V, --version") + " - display version info") - print_info(0, pp.globaloption(" -N, --no-pipe") + " - turn off pipe detection") - - print_info(0, "where " + pp.command("command") + "(" + pp.command("short") + ") is one of") - keys = Known_commands.keys() - keys.sort() - for x in keys: - print_info(0, " " + pp.command(x) + "(" + pp.command(short_cmds[x]) + ") " + \ - Known_commands[x].shortHelp()) - print - -def configure(): - """Set up default configuration. - """ - - # Guess colour output - if (Config["color"] == -1 and \ - ((not sys.stdout.isatty()) or (gentoolkit.settings["NOCOLOR"] in ["yes","true"]))): - pp.output.nocolor() - - # Guess piping output - if not sys.stdout.isatty(): - Config["piping"] = True - else: - Config["piping"] = False - - -def parseArgs(args): - """Parse tool-specific arguments. - - Arguments are on the form equery <tool-specific> [command] <command-specific> - - This function will only parse the <tool-specific> bit. - """ - command = None - local_opts = [] - showhelp = 0 - - def expand(x): - if x in Short_commands.keys(): - return Short_commands[x] - return x - - for i in xrange(len(args)): - x = args[i] - if 0: - pass - elif x in ["-h", "--help"]: - showhelp = True - elif x in ["-V", "--version"]: - printVersion() - sys.exit(0) - elif x in ["-C", "--nocolor"]: - Config["color"] = 0 - pp.output.nocolor() - elif x in ["-N", "--no-pipe"]: - Config["piping"] = False - elif x in ["-q","--quiet"]: - Config["verbosityLevel"] = 0 - elif expand(x) in Known_commands.keys(): - command = Known_commands[expand(x)] - local_opts.extend(args[i+1:]) - if showhelp: - local_opts.append("--help") - break - else: - print_warn("unknown global option %s, reusing as local option" % x) - local_opts.append(x) - - if not command and showhelp: - printUsage() - sys.exit(0) - - return (command, local_opts) - -if __name__ == "__main__": - configure() - (cmd, local_opts) = parseArgs(sys.argv[1:]) - if cmd: - try: - cmd.perform(local_opts) - except KeyError, e: - if e and e[0].find("Specific key requires an operator") >= 0: - print_error("Invalid syntax: missing operator") - print_error("If you want only specific versions please use one of") - print_error("the following operators as prefix for the package name:") - print_error(" > >= = <= <") - print_error("Example to only match gcc versions greater or equal 3.2:") - print_error(" >=sys-devel/gcc-3.2") - print_error("") - print_error("Note: The symbols > and < are used for redirection in the shell") - print_error("and must be quoted if either one is used.") - - else: - print_error("Internal portage error, terminating") - if len(e[0]): - print_error(str(e)) - sys.exit(2) - except ValueError, e: - if isinstance(e[0], list): - print_error("Ambiguous package name " + pp.emph("\"" + local_opts[0] + "\"")) - print_error("Please use one of the following long names:") - for p in e[0]: - print_error(" " + str(p)) - else: - print_error("Internal portage error, terminating") - if len(e[0]): - print_error(str(e[0])) - sys.exit(2) - except KeyboardInterrupt: - print_info(0, "Interrupted by user, aborting.") - else: - print_error("No command or unknown command given") - printUsage() - |