Rewriting to Python; improving gentoolkit module
authorkarltk <karltk@gentoo.org>
Mon, 28 Jul 2003 20:24:07 +0000 (20:24 -0000)
committerkarltk <karltk@gentoo.org>
Mon, 28 Jul 2003 20:24:07 +0000 (20:24 -0000)
svn path=/; revision=35

trunk/src/etcat/etcat
trunk/src/gentoolkit/gentoolkit.py
trunk/src/qpkg/qpkg
trunk/src/qpkg/qpkg.sh [new file with mode: 0644]

index f148a1fe8eee736b5818ddf2d677d154152b2f4f..d6345015c1127899cf51e6243aa6d8c90c1361af 100755 (executable)
@@ -312,24 +312,16 @@ def output_log(lines, package_ver=""):
 
 def changes(query):
     matches=gentoolkit.find_packages(query)
-    if not report_matches(matches,query):
+    if not report_matches(query,matches):
         return
-    
+
     for pkg in matches:
-        changelog_file = pkg.get_portage_path() + "/ChangeLog"
+        changelog_file = pkg.get_package_path() + "/ChangeLog"
        if os.path.exists(changelog_file):
-           if tup[2] and tup[3]:
-               printed = output_log(open(changelog_file).readlines(),match.split('/')[1] + ".*-" + tup[2] + "-" + tup[3]) or printed
-           elif tup[2]:
-               printed = output_log(open(changelog_file).readlines(),match.split('/')[1] + ".*-" + tup[2]) or printed
-           else:
-               printed = output_log(open(changelog_file).readlines()) or printed
+            output_log(open(changelog_file).readlines(), pkg.get_name()+"-"+pkg.get_version())
        else:
-           print "Error: No Changelog for " + match
-           return
-    
-    if not printed:
-       print "Error: No Changelog entry for " + query
+           print red("Error") + ": No Changelog for " + pkg.get_cpv()
+
 
 # .-------------------------------------------------------.
 # | Versions Function                                     |
@@ -339,82 +331,52 @@ def changes(query):
 # `-------------------------------------------------------'    
        
 def versions(query):
+    matches = gentoolkit.find_packages(query)
+    if not report_matches(query,matches):
+        return
+
+    # FIXME: old version printed result of regex search on name,
+    # so "ant" would return app-emacs/semantic, etc...
     
-    tup = smart_pkgsplit(query)
-    if tup[0] and tup[1]:
-       matches = [ tup[0] + "/" + tup[1] ]
-    elif tup[1]:
-       matches = gentoolkit.find_packages(tup[1])
-    
-    print "[ Results for search key : " + white(query) + " ]"
-    print "[ Applications found : " + white(str(len(matches))) + " ]"
-    print
-    
-    for package in matches:
-       print green("*") + "  " + white(package.get_cpv()) + " :"
-       versions = portage.portdb.xmatch("match-all", package)
-       unmasked = portage.portdb.xmatch("match-visible",package)
-       curver = portage.db["/"]["vartree"].dep_bestmatch(package)
-       if (curver) and (curver not in versions):
-           versions.append(curver)
-       
-       versions.sort(pkgcmp)
-       
-       for ver in versions:
+    for pkg in matches:
+       print green("*") + "  " + white(pkg.get_cpv()) + " :"
             
-            state = []
-            color = green
-            unstable = 0
-           overlay = ""
+        state = []
+        color = green
+        unstable = 0
+        overlay = ""
             
-            # check if masked
-            if ver not in unmasked:
-                state.append(red("M"))
-                color = red
-            else:
-                state.append(" ")
-
-            # check if in unstable
-           try:
-               ver_keywords =  portage.db["/"]["porttree"].dbapi.aux_get(ver,["KEYWORDS"])
-           except KeyError:
-               ver_keywords = [""]
-            keywords_list = ver_keywords[0].split()
-           
-            if "~" + portage.settings["ARCH"] in keywords_list:
-                state.append(yellow("~"))
-               if color != red:
-                   color = yellow
-                unstable = 1
-            else:
-                state.append(" ")
+        # check if masked
+        if pkg.is_masked():
+            state.append(red("M"))
+            color = red
+        else:
+            state.append(" ")
+
+        # check if in unstable
+        kwd = pkg.get_env_var("KEYWORDS")
+        if "~" + gentoolkit.settings["ARCH"] in kwd.split():
+            state.append(yellow("~"))
+            if color != red:
+                color = yellow
+            unstable = 1
+        else:
+            state.append(" ")
                 
-            # check if installed
-            cat, pkg = ver.split("/")            
-            if portage.dblink(cat,pkg,"/").exists():
-                state.append(turquoise("I"))
-                color = turquoise
-            else:
-                state.append(" ")
-               
-           # check if this is a OVERLAY ebuilds
-           try:
-               if portage.portdb.oroot:
-                   if os.path.exists(portage.portdb.oroot + "/" + package + "/" + pkg + ".ebuild"):
-                       overlay = " OVERLAY"
-           except AttributeError:
-               pass
-
-            # print
-           try:
-               slot = portage.db["/"]["porttree"].dbapi.aux_get(ver,["SLOT"])
-               if not slot:
-                   slot = ["0"]
-           except KeyError:
-               slot = ["?"]
-               
-            print " "*8 + "[" + string.join(state,"") + "] " + color(ver) + " (" + color(slot[0]) + ")" + overlay
-
+        # check if installed
+        if pkg.is_installed():
+            state.append(turquoise("I"))
+            color = turquoise
+        else:
+            state.append(" ")
+
+        # check if this is a OVERLAY ebuilds
+        if pkg.is_overlay():
+            overlay = " OVERLAY"
+
+        ver = pkg.get_version()
+        slot = pkg.get_env_var("SLOT")
+        print " "*8 + "[" + string.join(state,"") + "] " + color(ver) + " (" + color(slot) + ")" + overlay
         print
 
 # .-------------------------------------------------------.
@@ -422,7 +384,7 @@ def versions(query):
 # +-------------------------------------------------------+
 # | Just uses the new IUSE parameter in ebuilds           |
 # `-------------------------------------------------------' 
-def uses(query):
+def uses(query): # FIXME: Use gentoolkit
     
     tup = smart_pkgsplit(query)
     if tup[0] and tup[1]:
@@ -604,7 +566,7 @@ def old_uses(query):
 # `-------------------------------------------------------'
 graphcache = []
 
-def graph(query):
+def graph(query): # FIXME: Use gentoolkit
     print "attempt to graph dependencies"
     print red("warning, this is BETA, will probably report the wrong results")
     rgraph(query, [])
@@ -711,7 +673,7 @@ def rgraph(dep, path):
 # | Find what packages require a given package name       |
 # `-------------------------------------------------------'
 
-def depends(query):
+def depends(query): # FIXME: Use gentoolkit
     
     print "[ Results for search key : " + white(query) + " ]"
 
@@ -750,7 +712,32 @@ def depends(query):
 # | Finds what package a file belongs to                  |
 # `-------------------------------------------------------'        
            
-def belongs(query):
+def belongs(query): # FIXME: use gentoolkit
+
+    q = query.split()
+
+    if len(q) > 1:
+        item=q[0]
+        cat=q[1]
+        fn=lambda x: x.find(cat)==0
+    else:
+        item=q[0]
+        cat="*"
+        fn=None
+
+    print "Searching for " + item + " in " + cat + " ..."
+
+    matches = gentoolkit.find_all_packages(fn)
+    rx = re.compile(item)
+
+    # FIXME: Speedup
+    # FIXME: Add category selection
+    for pkg in matches:
+        for fn in pkg.get_contents().keys():
+            if rx.search(fn):
+                print pkg.get_cpv()
+    return
+        
     query = query.split()
     # FIXME: use portage.settings
     dbdir = "/var/db/pkg"
@@ -809,7 +796,7 @@ def report_matches(query, matches):
     print
     
     if matches:
-       print " Only printing found installed programs."
+#      print " Only printing found installed programs."
        print
         return 1
     else:
index 333212050d9b2380102f7f605185bb2d017472b5..fab5b865da273be87e4363e50459218e8d1b5df7 100644 (file)
@@ -18,6 +18,7 @@ __description__ = "Gentoolkit Common Library"
 import os
 import portage
 import re
+import string
 
 settings = portage.settings
 porttree = portage.db[portage.root]["porttree"]
@@ -63,14 +64,17 @@ class Package:
         """Returns true if this package is installed (merged)"""
         self._initdb()
         return os.path.exists(self._db.getpath())
+    def is_overlay(self):
+        dir,ovl=portage.portdb.findname2(self._cpv)
+        return ovl
     def is_masked(self):
         """Returns true if this package is masked against installation. Note: We blindly assume that
         the package actually exists on disk somewhere."""
-        unmasked = portage.portdb.xmatch("match-visible", self.get_category()+"/"+self.get_name())
+        unmasked = portage.portdb.xmatch("match-visible", "=" + self._cpv)
         return self._cpv not in unmasked
     def get_ebuild_path(self):
         """Returns the complete path to the .ebuild file"""
-        return porttree.getname(self._cpv)
+        return portage.portdb.findname(self._cpv)
     def get_package_path(self):
         """Returns the path to where the ChangeLog, Manifest, .ebuild files reside"""
         p=self.get_ebuild_path()
@@ -79,7 +83,10 @@ class Package:
             return string.join(sp[:-1],"/")
     def get_env_var(self, var):
         """Returns one of the predefined env vars DEPEND, RDEPEND, SRC_URI,...."""
-        return porttree.dbapi.aux_get(self._cpv,[var])
+        r=porttree.dbapi.aux_get(self._cpv,[var])
+        if len(r)!=1:
+            raise "Should only get one element!"
+        return r[0]
     def get_contents(self):
         """Returns the full contents, as a dictionary, on the form
         [ '/bin/foo' : [ 'obj', '1052505381', '45ca8b8975d5094cd75bdc61e9933691' ], ... ]"""
@@ -125,10 +132,15 @@ def find_packages(search_key):
     t=portage.portdb.match(search_key)
     return map(lambda x: Package(x), t)
 
-def find_all_packages():
+def find_all_packages(prefilter=None):
     """Returns a list of all known packages, installed or not."""
     t=portage.portdb.cp_all()
-    return map(lambda x: Package(x), t)
+    if prefilter:
+        t=filter(prefilter,t)
+    t2=[]
+    for x in t:
+        t2 += portage.portdb.cp_list(x)
+    return map(lambda x: Package(x), t2)
 
 if __name__ == "__main__":
     print "This module is for import only"
index cdbe3c73f1a6f8c9a826fc69b0fb96beeaf897b4..37366906514f8ae68e6934780e93cd0bfd3081fb 100644 (file)
-#!/bin/bash
+#! /usr/bin/env python2.2
+#
+# Copyright 2003 Karl Trygve Kalleberg
+# Copyright 2003 Gentoo Technologies, Inc.
+# Distributed under the terms of the GNU General Public License v2
+#
+# $Header$
+# Author: Karl Trygve Kalleberg <karltk@gentoo.org>
 #
-# qpkg - query portage package system for various information
 #
-# Copyright (c) Vitaly Kushneriuk <vitaly_kushneriuk@yahoo.com>
-# This program is distributed under the terms of GPL version 2.
+# qpkg - query portage package system for various information
 #
-# Maintainer: Brandon Low <lostlogic@gentoo.org>
-# Additional code thanks to:
-#            Josh Goebel <dreamer@firesedge.org>
+# This is a reimplementation of the qpkg written in bash, by 
+# Vitaly Kushneriuk <vitaly_kushneriuk@yahoo.com>,
+# Brandon Low <lostlogic@gentoo.org>,
+# Josh Goebel <dreamer@firesedge.org>
 #
 # $Header$
+
+import sys
+from output import *
+
+__author__ = "Karl Trygve Kalleberg"
+__email__ = "karltk@gentoo.org"
+__version__ = "0.2.0"
+__productname__ = "qpkg"
+__description__ = "Query Portage package system CLI tool"
+
+class Config:
+    showUsage=0
+    pass
+
+def showUsage():
+    
+    print turquoise("qpkg") + " v" + __version__ + " - Gentoo package query tool"
+
+    print white("Usage:")
+
+    print "\t" + turquoise("qpkg") + " " +\
+          "[" + white("options") + "] " + \
+          "[" + yellow("pkgname") + "] " + \
+          "[" + blue("-g") + " " + yellow("group") + "] " + \
+          "[" + blue("-f") + " " + yellow("<file>") + "|" + blue("-fp") + " " + yellow("<pattern") + "]"
+
+    print "\t" + turquoise("qpkg") + " " + blue("--dups") + " [" + blue("--slot") + "]"
+    print "\t" + turquoise("qpkg") + " " + blue("--help")
+
+    print "\n" + white("Duplicates:")
+    print blue("-d,   --dups") + "\t\tprint packages that have multiple versions installed"
+    print blue("-s,   --slot") + "\t\tmake " + blue("-d") + " SLOT only print dups of the same SLOT"
+
+    print "\n" + white("Selection:")
+    print blue("-f,   --find-file") + "\tfinds package that owns file <file>"
+    print blue("-fp,  --find-pattern") + "\tfinds package that owns file matching *<pattern>*"
+    """
+
+${BR}Package Selection:
+  ${BL}-f,  --find-file${NO}${T}finds package that owns file <file>
+  ${BL}-fp, --find-pattern${NO}${T}finds to package that owns file matching *<pattern>*
+  ${BL}-m,  --masked${NO}${T}Include${YL} only${NO} masked packages
+  ${BL}-n,  --non-masked${NO}${T}Include${YL} only${NO} non-masked packages
+  ${BL}-I,  --installed${NO}${T}Include${YL} only${NO} installed packages
+  ${BL}-U,  --uninstalled${NO}${T}Include${YL} only${NO} uninstalled packages
+  ${BL}-g,  --group${NO}${T}${T}Find by goup (can be combined with other searches)
+
+${BR}Information Selection:
+  ${BL}-l,  --list${NO}${T}${T}List package content
+  ${BL}-i,  --info${NO}${T}${T}Get package description and home page.
+  ${BL}-ct, --check-time${NO}
+  ${BL}-tc, --time-check${NO}${T}Verify package files timestamps
+  ${BL}-cm, --check-md5${NO}
+  ${BL}-mc, --md5-check${NO}${T}Verify package files md5
+  ${BL}-c,  --check${NO}${T}${T}Verify mtimes${YL} and${NO} md5.
+  ${BL}-q,  --query-deps${NO}${T}display all installed packages 
+${T}${T}${T}depending on selected packages
+
+${BR}Operation Modifiers:
+  ${BL}-nc, --no-color${NO}${T}don't use colors
+  ${BL}-v,  --verbose${NO}${T}Be more verbose [ can be repeated twise ]
+  ${BL}-vv${NO}${T}${T}${T}Same as ${BL}-v -v${NO}
+
+${YL}Notes${NO}: 
+${YL}*${NO} ${BL}-f${NO}, ${BL}-fp, ${BL}-d${NO}, ${BL}-l${NO}, ${BL}-ct${NO}, ${BL}-cm${NO}, and ${BL}-c${NO} apply only to installed packages.
+${YL}*${NO} Short options may not be combined on the command-line, yet.
+${YL}*${NO} The operation of some flags has been changed by the
+  stripping of version numbers from some output to see
+  the version numbers play with ${BL}-v${NO} and ${BL}-vv${NO}.
+${YL}*${NO} When using${BL} -f${NO} with ${BL}-l${NO} or ${BL}--check.. -v${NO} options, only
+  matching files will be displayed, unless ${BL}-v${NO} is doubled, 
+  (yet more verbose) or ${BL}-vv${NO} is used.
+
+
+${YL}Examples${NO}:
+  ${PROG} --dups               print duplicates oldest first
+  ${PROG} --dups -v    .. with versions
+  ${PROG}                      print list of installed packages
+  ${PROG} porta -I             print versions of installed portage
+  ${PROG} porta -i             .. + versions in portage tree + descriptions 
+                       and homepages
+  ${PROG} gawk -c -v   check integrity all installed versions of gawk
+                       the older will have \"damaged\" files.
+  ${PROG} -f /bin/ls   print package(s) that own /bin/ls
+"""
+
+def parse_args():
+    if len(sys.argv) < 2:
+        Config.showUsage = 1
+        return
+    for i in sys.argv[1:]:
+        if i in ["-h","--help"]:
+            Config.showUsage = 1
+        
+def main():
+    parse_args()
+    if Config.showUsage:
+        showUsage()
+    
+if __name__ == "__main__":
+    main()
+
+"""    
 ID='$Id$'
 VERSION=0.`echo ${ID} | cut -d\  -f3`
 
@@ -518,3 +627,4 @@ done | (
                -e "s:^obj ::;s:^sym ::;s:^dir ::"
 
 )
+"""
diff --git a/trunk/src/qpkg/qpkg.sh b/trunk/src/qpkg/qpkg.sh
new file mode 100644 (file)
index 0000000..cdbe3c7
--- /dev/null
@@ -0,0 +1,520 @@
+#!/bin/bash
+#
+# qpkg - query portage package system for various information
+#
+# Copyright (c) Vitaly Kushneriuk <vitaly_kushneriuk@yahoo.com>
+# This program is distributed under the terms of GPL version 2.
+#
+# Maintainer: Brandon Low <lostlogic@gentoo.org>
+# Additional code thanks to:
+#            Josh Goebel <dreamer@firesedge.org>
+#
+# $Header$
+ID='$Id$'
+VERSION=0.`echo ${ID} | cut -d\  -f3`
+
+PROG=`basename ${0}`
+
+# Parse args
+verb=0
+group="*"
+params=${#}
+while [ ${#} -gt 0 ]
+do
+       a=${1}
+       shift
+       case "${a}" in
+
+       -h|--help)
+               usage=y
+               break
+               ;;
+
+       -i|--info)
+               info=y
+               ;;
+
+       -d|--dups)
+               dups=y
+               inst=y
+               ;;
+
+       -q|--query-deps)
+               query=y
+               ;;
+
+       -s|--slot)
+               slot=y
+               ;;
+
+       -f|--find-file)
+               ffind=y
+               inst=y
+               ;;
+
+       -fp|--find-pattern)
+               ffind=y
+               fpat=y
+               inst=y
+               ;;
+
+       -I|--installed)
+               inst=y
+               ;;
+
+       -m|--masked)
+               grepmask="-L"
+               ;;
+
+       -n|--non-masked)
+               grepmask="-l"
+               ;;
+
+       -U|--uninstalled)
+               uninst=y
+               ;;
+
+       -g|--group)
+               group=$1
+               shift
+               ;;
+
+       -l|--list)
+               list=y
+               inst=y
+               ;;
+
+       -ct|--check-time|-tc|--time-check)
+               tcheck=y
+               inst=y
+               ;;
+
+       -cm|--check-md5|-mc|--md5-check)
+               mcheck=y
+               inst=y
+               ;;
+
+       -c|--check)
+               mcheck=y
+               tcheck=y
+               inst=y
+               ;;
+
+       -v|--verbose)
+               let $((verb++))
+               ;;
+
+       -vv)
+               let $((verb++))
+               let $((verb++))
+               ;;
+
+       -nc|--no-color|--nocolor|--no-colors|--nocolors)
+               nocolor=y
+               ;;
+
+       -*)
+               echo -e ${CY}${PROG}${NO}:${YL} Invalid option ${RD}$a 1>&2
+               usage=y
+               break
+               ;;
+       *)
+               if [ -n "${arg}" ]; then
+                       echo -e ${CY}${PROG}: ${YL}Only one argument supported
+                       usage=y
+                       break
+               fi
+               arg=$a
+               ;;
+               
+       esac
+done
+
+#This is a dumb way to handle things, take it out next time
+T="\t"
+
+#Set up colors
+if [ ! "${nocolor}" ]; then
+       NO="\x1b[0;0m"
+       BR="\x1b[0;01m"
+       CY="\x1b[36;01m"
+       RD="\x1b[31;01m"
+       GR="\x1b[32;01m"
+       YL="\x1b[33;01m"
+       BL="\x1b[34;01m"
+       STAR=" *"
+elif [ ! "${inst}" ] && [ ! "${uninst}" ]; then
+       STAR=" *"
+fi
+
+
+# check for option conflicts
+if [ "${inst}" -a "${uninst}" \
+       -o \( "${ffind}" -o "${list}" -o "${tcheck}" -o "${mcheck}" \) \
+       -a "${uninst}"  ]; then
+       echo -e ${CY}${PROG}${NO}:${YL} conflicting options/modes${NO}
+       usage=y
+fi
+
+if [ "${usage}" ]; then
+       echo -e "${CY}${PROG} v. ${VERSION}${NO}
+
+${CY}${PROG}${NO} is GenToolKit's \"query package\" tool, using it, you can
+find packages owning files on your filesystem, check the integrity
+of installed packages, and do other queries against installed or
+uninstalled packages.
+
+${BR}Usage:
+${T}${CY}${PROG}${NO} [${BR}options${NO}] [${YL}pkgname${NO}] [${BL}-g${YL} group${NO}] [${BL}-f${YL} <file>${NO}|${BL}-fp${YL} <patern>${NO}]
+${T}${CY}${PROG}${NO} ${BL}--dups${NO} [${BL}--slot${NO}]
+${T}${CY}${PROG}${NO} ${BL}--help${NO}
+
+${BR}Duplicate Locating:
+  ${BL}-d,  --dups${NO}${T}${T}print packages that have multiple versions installed
+  ${BL}-s,  --slot${NO}${T}${T}make ${BL}-d${NO} SLOT only print dups of the same SLOT
+
+${BR}Package Selection:
+  ${BL}-f,  --find-file${NO}${T}finds package that owns file <file>
+  ${BL}-fp, --find-pattern${NO}${T}finds to package that owns file matching *<pattern>*
+  ${BL}-m,  --masked${NO}${T}Include${YL} only${NO} masked packages
+  ${BL}-n,  --non-masked${NO}${T}Include${YL} only${NO} non-masked packages
+  ${BL}-I,  --installed${NO}${T}Include${YL} only${NO} installed packages
+  ${BL}-U,  --uninstalled${NO}${T}Include${YL} only${NO} uninstalled packages
+  ${BL}-g,  --group${NO}${T}${T}Find by goup (can be combined with other searches)
+
+${BR}Information Selection:
+  ${BL}-l,  --list${NO}${T}${T}List package content
+  ${BL}-i,  --info${NO}${T}${T}Get package description and home page.
+  ${BL}-ct, --check-time${NO}
+  ${BL}-tc, --time-check${NO}${T}Verify package files timestamps
+  ${BL}-cm, --check-md5${NO}
+  ${BL}-mc, --md5-check${NO}${T}Verify package files md5
+  ${BL}-c,  --check${NO}${T}${T}Verify mtimes${YL} and${NO} md5.
+  ${BL}-q,  --query-deps${NO}${T}display all installed packages 
+${T}${T}${T}depending on selected packages
+
+${BR}Operation Modifiers:
+  ${BL}-nc, --no-color${NO}${T}don't use colors
+  ${BL}-v,  --verbose${NO}${T}Be more verbose [ can be repeated twise ]
+  ${BL}-vv${NO}${T}${T}${T}Same as ${BL}-v -v${NO}
+
+${YL}Notes${NO}: 
+${YL}*${NO} ${BL}-f${NO}, ${BL}-fp, ${BL}-d${NO}, ${BL}-l${NO}, ${BL}-ct${NO}, ${BL}-cm${NO}, and ${BL}-c${NO} apply only to installed packages.
+${YL}*${NO} Short options may not be combined on the command-line, yet.
+${YL}*${NO} The operation of some flags has been changed by the
+  stripping of version numbers from some output to see
+  the version numbers play with ${BL}-v${NO} and ${BL}-vv${NO}.
+${YL}*${NO} When using${BL} -f${NO} with ${BL}-l${NO} or ${BL}--check.. -v${NO} options, only
+  matching files will be displayed, unless ${BL}-v${NO} is doubled, 
+  (yet more verbose) or ${BL}-vv${NO} is used.
+
+
+${YL}Examples${NO}:
+  ${PROG} --dups               print duplicates oldest first
+  ${PROG} --dups -v    .. with versions
+  ${PROG}                      print list of installed packages
+  ${PROG} porta -I             print versions of installed portage
+  ${PROG} porta -i             .. + versions in portage tree + descriptions 
+                       and homepages
+  ${PROG} gawk -c -v   check integrity all installed versions of gawk
+                       the older will have \"damaged\" files.
+  ${PROG} -f /bin/ls   print package(s) that own /bin/ls
+"
+       exit
+fi
+
+#For the --dups switch only
+if [ "${dups}" ]; then
+if [ "${grepmask}" ]; then
+       mask=`python -c 'import portage; print portage.settings["ACCEPT_KEYWORDS"];' 2> /dev/null`
+       echo -e "Currently accepted keywords: ${BL}${mask}${NO}"
+       echo -e
+       mask=`echo ${mask} | perl -pe 's/\s+/|/'`
+fi
+
+       #First dig out the list of packages with duplicates
+       find /var/db/pkg -iname "*${arg}*.ebuild" 2> /dev/null > /tmp/qpkg.lst
+       dups=`cat /tmp/qpkg.lst | cut -f7 -d/ |
+               sed -e 's:\.ebuild$::; s:-r[0-9]*$::; s:-[^-]*$::; /^$/d' |
+               sort | 
+               uniq -d`
+
+       #Next get all the exact versions
+       duppak=`cat /tmp/qpkg.lst | fgrep "${dups}"`
+
+       #Now cut that down to the directory name so we can be smart
+       dirs=`sed -e 's:/[^/]*$::' /tmp/qpkg.lst`
+
+       #Go through each package's DB and create a sortable file
+       #to play with
+       declare -i defcount=`cat /var/cache/edb/counter`
+       for DIR in ${dirs}
+       do      #Package COUNTER
+               NUM=`cat "${DIR}/COUNTER" 2> /dev/null`
+               [ -z "${NUM}" ] && NUM=defcount
+               #Package slot if requested
+               [ ${slot} ] && SLOT=`cat "${DIR}/SLOT"`
+               #Package fullname
+               PKG=`ls --color=no -1 ${DIR}/*.ebuild|cut -f5,7 -d"/"`
+               #Package basename
+               NAME=`echo "${PKG}"|sed -e 's:\.ebuild$::; s:-r[0-9]\+$::; s:-[0-9].*$::'`
+               echo "${NUM} ${PKG} ${NAME}${SLOT}"
+       #Finish loop, and sort that nice sortable file based on 
+       #installation order, and then based on package basename
+       #bash hates me so I decided to use a temp file
+       done |sort -t" " -k3 -k1g,2|uniq -D -f2 > /tmp/qpkg.lst
+       duppak=`cat /tmp/qpkg.lst`
+       rm /tmp/qpkg.lst
+
+       #If max verbosity is set output with full path to each ebuild
+       if [ "${verb}" -gt 1 ]; then
+               echo -n "${duppak}"|cut -f2 -d" "| \
+                                   sed -e "s:^:${BL}/var/db/pkg/${BR}:" \
+                                       -e "s:\(/\)\([^/]*\)\(.ebuild\):\1${CY}\2${NO}\1\2\3:"
+
+       #If normal verbosity output package group, package name and package version
+       elif [ "${verb}" -gt 0 ]; then
+               echo -n "${duppak}"|cut -f2 -d" "| \
+                                   sed -e "s:\(^[^/]*/\)\(.*\)\(\.ebuild\):${BR}\1${CY}\2${NO}:"
+
+       #Otherwise just output package group and package name
+       else
+               echo -n "${duppak}"|cut -f2 -d" "| \
+                                   sed -e "s:-r[0-9]\+$::" \
+                                       -e "s:-[0-9].*$::" \
+                                       -e "s:\(^[^/]*/\)\(.*\):${BR}\1${CY}\2${NO}:"|uniq
+       fi
+       exit
+fi
+
+# get list of ebuilds to work on
+if [ "${ffind}" ]; then
+       # file find mode - list all ebuilds for 
+       # package/CONTENTS containing <arg>
+       if [ "${fpat}" ]; then
+               dirs=`ls /var/db/pkg/${group}/*/CONTENTS \
+               | xargs grep -l "${arg}" \
+               | xargs --no-run-if-empty -n 1 dirname`
+       else
+               # if the user didnt specify a full path assume they
+               # want to check in the working dir #17331
+               [ "${arg:0:1}" != "/" ] && arg="${PWD}/${arg}"
+
+               dirs=`ls /var/db/pkg/${group}/*/CONTENTS \
+               | xargs grep -l " ${arg}\( .*\)*$" \
+               | xargs --no-run-if-empty -n 1 dirname`
+       fi
+       ipak=`(
+       for d in ${dirs} -;do
+               [ "-" = "$d" ] && break
+               ls ${d}/*.ebuild
+       done)`
+else
+       # normal mode - list ebuilds for ebuild name containing <arg>
+
+       # installed packages
+       if [ ! "${uninst}" ]; then
+               ipak=`find /var/db/pkg/ -iname "*.ebuild" 2>/dev/null`
+               if [[ ${group} != "*" ]]; then
+                   ipak=`echo ${ipak}|sed -e "s: :\n:g"|grep ${group}`
+               fi
+               if [ ${arg} ]; then
+                       # avoid ${arg}="db" from pulling in every installed package
+                       temp="/var/db/pkg/.*${arg}"     
+                       ipak=`echo ${ipak}|sed -e "s: :\n:g"|grep ${temp}`
+               fi
+               if [ -n "${mask}" ]; then
+                   ipak=`echo ${ipak}|xargs -r egrep ${grepmask} "^KEYWORDS=.*[[:space:]\"\'](${mask})[[:space:]\"\']"`
+               fi
+       fi
+       # not installed packages (yet:-)
+       if [ ! "${inst}" ]; then
+               upak=`find /usr/portage/ -iname "*.ebuild" 2>/dev/null|grep -v --regex="/usr/portage/[^/]*\.ebuild"`
+               if [[ ${group} != "*" ]]; then
+                   upak=`echo ${upak}|sed -e "s: :\n:g"|grep ${group}`
+               fi
+               if [ ${arg} ]; then
+                   upak=`echo ${upak}|sed -e "s: :\n:g"|grep ${arg}`
+               fi
+               if [ -n "${mask}" ]; then
+                   upak=`echo ${upak}|xargs -r egrep ${grepmask} "^KEYWORDS=.*[[:space:]\"\'](${mask})[[:space:]\"\']"`
+               fi
+       fi
+fi
+
+X="\([^/]*\)"
+
+for p in ${ipak} ${upak} -;do
+       [ "${p}" = "-" ] && break
+
+       # cut common prefix from ebuild name and mark installed/uninstalled packages
+       # Note: iii/uuu will be replaced by the pipe at the end
+       n=${p%.ebuild}
+       var_db_pkg="/var/db/pkg/"
+       n=${n/${var_db_pkg}/iii }
+       usr_portage="/usr/portage/"
+       n=${n/${usr_portage}/uuu }
+       n=${n/\/*\//\/}
+
+       d=${p%\/*.ebuild} # faster d=`dirname ${p}`
+       echo ${n}
+       
+       # if we have no passed parameters then 
+       # we can skip the extra conditional checks
+       [[ ${params} == 0 ]] && continue;
+
+       if [ "${mask}" ]; then
+               keywords=`grep KEYWORDS ${p}| cut -d\" -f2`
+               echo -e "${T}Keywords: ${BL}${keywords}${NO}"
+       fi
+       
+       if [ ${verb} -gt 1 ];then
+               echo "vvv    ${p}"
+       fi
+       
+       if [ "${info}" ]; then
+               home=`grep HOMEPAGE ${p}| cut -d\" -f2`
+               desc=`grep DESCRIPTION ${p}| cut -d\" -f2`
+               echo -e "${T}${BL}${desc}${NO} [ ${YL}${home}${NO} ]"
+       fi
+       
+       if [ "${query}" ]; then
+               echo -e "${BL}DEPENDED ON BY:${NO}"
+               package="`echo ${n}|sed -e 's:-r[0-9]\+$::' \
+                                       -e 's:-[0-9].*$::' \
+                                       -e 's:^iii ::' \
+                                       -e 's:^uuu ::'`"
+               place="`echo ${n}|cut -f1 -d' '`"
+               [[ "${place}" == "iii" ]] && color="${GR}" || color="${RD}"
+               grep -R "${package}" /var/db/pkg/*/*/RDEPEND | \
+               cut -f5,6 -d"/" | sed -e "s:^:\t${color}:;s:$:${NO}:" | sort | uniq
+#              gawk -F "/" '{printf("${place}\n\t%s/%s${NO}",$5,$6)}' | sort | uniq
+       fi
+
+       # cat package content, remove obj/sym/dir, md5 and mtime when not verbose
+       # display only match in file-find mode unless extra verbose
+       if [ "${list}" ]; then
+               echo -e ${BL}CONTENTS:${NO}
+
+               if [ ${verb} -gt 1 ]; then
+                       cat ${d}/CONTENTS
+               else
+                       if [ "${ffind}" ]; then
+                               if [ "${fpat}" ]; then
+                                       grep "${arg}" $d/CONTENTS
+                               else
+                                       grep " ${arg}\( .*\)*$" $d/CONTENTS
+                               fi
+                       else
+                               cat $d/CONTENTS
+                       fi |
+                       if [ ${verb} -gt 0 ]; then
+                               cat
+                       else
+                               sed -e "s:\(^obj \)\([^ ]*\)\(.*$\):\1${BR}\2${NO}:;
+                                       s:\(^sym \)\([^ ]*\)\( -> \)\([^ ]*\)\(.*$\):\1${CY}\2${NO}\3\4:;
+                                       s:\(^dir \)\([^ ]*\)\(.*$\):\1${YL}\2${NO}:"
+                       fi
+               fi
+
+               echo
+               
+       # check files mtime and md5, display summary at the end
+       elif [ "${tcheck}" -o "${mcheck}" ]; then
+               # counters
+               fe=0
+               fs=0
+               # read the CONTENTS file and check md5 and mtime if needed
+               # process only matching files in find-file mode unless extra verbose
+               cat ${d}/CONTENTS | 
+                       if [ "${ffind}" -a ${verb} -lt 2 ];then 
+                               if [ "${fpat}" ]; then
+                                       grep "${arg}"
+                               else
+                                       grep " ${arg} "
+                               fi
+                       else
+                               cat
+                       fi |
+               (
+               while read -a line
+               do
+                       fs=$((fs + 1))
+                       
+                       unset md5
+                       unset _md5
+                       unset mtime
+                       unset _mtime
+                       unset err
+
+                       name=${line[1]}
+                       
+                       missing=
+                       [ ! -e ${name} ] && missing=1
+                       
+                       # colorize name and compute mtime/md5
+                       if [ "obj" = ${line[0]} ]; then
+                               [ -e ${name} ] && {
+                                       [ "${tcheck}" ] && mtime=${line[3]}
+                                       [ "${tcheck}" ] && _mtime=`date -r ${name} +%s`
+
+                                       [ "${mcheck}" ] && md5=${line[2]}
+                                       [ "${mcheck}" ] && _md5=`md5sum ${name}|cut -f1 -d" "`
+                               }
+
+                               name=${BR}${name}${NO}
+
+                       elif [ "sym" = ${line[0]} ]; then
+                               name=${CY}${name}${NO}
+
+                       elif [ "dir" = ${line[0]} ]; then
+                               name=${YL}${name}${NO}
+                       fi
+                       
+                       # compare
+                       if [ "$missing" ]; then
+                               err=1
+                               name="${name} ${RD}!not exist!${NO}"
+                       fi
+                       if [ "${md5}" != "${_md5}" ]; then
+                               #If the md5 fails the first time check it with
+                               #everything changed to lowercase :-D
+                               md5=`echo "${md5}"|tr A-Z a-z`
+                               if [ "${md5}" != "${_md5}" ]; then
+                                       err=1
+                                       name="${name} ${RD}!md5!${NO}"
+                               fi
+                       fi
+                       if [ "${mtime}" != "${_mtime}" ]; then
+                               err=1
+                               name="${name} ${RD}!mtime!${NO}"
+                       fi
+
+                       [ ${verb} -gt 1 ] && echo -e ${name}
+                       [[ ${verb} -eq 1 ]] && [[ $err -eq 1 ]] && echo -e ${name}
+
+                       fe=$((fe + err))
+               done
+               if [ "$fe" = "0" ]; then
+                       echo -e ${YL}$fe${CY}/$fs${NO}
+               else
+                       echo -e ${RD}$fe${CY}/$fs${NO}
+               fi
+               echo
+               )
+       fi
+       
+done | (
+       if [ ! \( "${tcheck}" -o "${mcheck}" -o "${info}" -o "${list}" -o "${query}" -o "${mask}" -o ${verb} -gt 0 \) ]; then
+               sed -e "s:-r[0-9]\+$::" -e "s:-[0-9][^-]*$::"|sort -k2|uniq -f1
+       elif [ ! \( "${tcheck}" -o "${mcheck}" -o "${info}" -o "${list}" -o "${query}" -o "${mask}" -o ${verb} -lt 2 \) ]; then
+               sort -k2|uniq -f1
+       else
+               cat
+       fi | sed \
+               -e "s:^iii ${X}/${X}:${BR}\1/${CY}\2${STAR}${NO}:" \
+               -e "s:^uuu ${X}/${X}:${BR}\1/${YL}\2${NO}:" \
+               -e "s:^vvv \(.*\)$:${BL}\1${NO}:" \
+               -e "s:^obj ::;s:^sym ::;s:^dir ::"
+
+)