Etcat updates, qpkg updates
authorkarltk <karltk@gentoo.org>
Wed, 6 Aug 2003 17:48:29 +0000 (17:48 -0000)
committerkarltk <karltk@gentoo.org>
Wed, 6 Aug 2003 17:48:29 +0000 (17:48 -0000)
svn path=/; revision=36

trunk/ChangeLog
trunk/TODO
trunk/src/dep-clean/AUTHORS
trunk/src/etcat/AUTHORS
trunk/src/etcat/etcat
trunk/src/gentoolkit/gentoolkit.py
trunk/src/pkg-clean/AUTHORS
trunk/src/qpkg/qpkg

index 99cf606fc7579625678a160174e04168e1a4c3f6..0f958397b10583bcea1ea577d78cfc8eda47522a 100644 (file)
@@ -1,4 +1,9 @@
        
+2003-06-31 Karl Trygve Kalleberg <karltk@gentoo.org>
+       * Rewrote more of etcat; many of the functions now employ
+       gentoolkit.
+       * Replaced qpkg with stubs of a reimplementation in python.
+
 2003-06-27 Karl Trygve Kalleberg <karltk@gentoo.org>
        * Added patch to echangelog to consider PORTDIR, fixes #23881.
        
index f85718a476939fdc74e6c47ad7930684675a2d58..24fbfe242228448e0ade193578548c11ea1f5878 100644 (file)
@@ -1,13 +1,15 @@
-- merge dep-clean and pkg-clean, use portage
-- rewrite ekeywords and echangelog to use portage
-- extract helper code from etcat
-- rewrite qpkg to use portage
-- rewrite epm to use portage
+- merge dep-clean and pkg-clean to use gentoolkit
+- rewrite ekeywords and echangelog to use gentoolkit
+- add deep depends to etcat
+- rewrite qpkg to use gentoolkit
+- rewrite epm to use gentoolkit
 - merge emerge-rsync and emerge-webrsync
 - drop pkg-size (callfwd to etcat size)
 - merge change and echangelog
 - merge useflag and euse
-- rewrite revdep-rebuild to use portage
-- rewrite distfiles-clean to use portage
-- rewrite etc-update to use portage, add UI
+- rewrite revdep-rebuild to use gentoolkit
+- rewrite distfiles-clean to use gentoolkit
+- rewrite etc-update to use gentoolkit, add UI
 - add genlop
+
++ extract helper code from etcat
index 6b6feade640390ccf8a3f7645107d35510ac572d..48bd6cfe7b0def1f123b58186dce62a5d336bf06 100644 (file)
@@ -1,7 +1,8 @@
 Maintainer:
-Brandon Low <lostlogic@gentoo.org>
+Karl Trygve Kalleberg <karltk@gentoo.org>
 
 Authors:
 Jerry Haltom <ssrit@larvalstage.net> (dep-clean)
 Brandon Low <lostlogic@gentoo.org> (dep-clean)
 Paul Belt <gaarde@users.sourceforge.net> (man page)
+Brandon Low <lostlogic@gentoo.org> (dep-clean)
index 13cd48a83baac2f95f4b794c5e137c792c0db85c..5da0b070e0647d4f2c9eba6b2746d0b3398bf435 100644 (file)
@@ -1 +1,5 @@
-* Alastair Tse <liquidx@gentoo.org>
+Maintainer:
+Karl Trygve Kalleberg <karltk@gentoo.org>
+
+Authors:
+Alastair Tse <liquidx@gentoo.org> (original author)
index d6345015c1127899cf51e6243aa6d8c90c1361af..433ff8c884b5b11dae2845399de3e21c5d0d129f 100755 (executable)
@@ -160,118 +160,7 @@ def wrap_print(string, indent=0, width=74):
     for line in lines:
        print " "*indent + line
 
-def pkgcmp(a,b):
-    raise "This is not present"
-    # strips out package name and returns the result of vercmp
-    awords = a.split("-")
-    bwords = b.split("-")
-    apkg = [awords[0]]
-    bpkg = [bwords[0]]
-    DIGITS = ['0','1','2','3','4','5','6','7','8','9']
-    
-    for w in awords[1:]:
-       if w[0] in DIGITS:
-           break
-       else:
-           apkg.append(w)
-    aver = awords[len(apkg):]
-    apkg_str = string.join(apkg, "-")
-    aver_str = string.join(aver, "-")
-    
-    for w in bwords[1:]:
-       if w[0] in DIGITS:
-           break
-       else:
-           bpkg.append(w)
-    bver = bwords[len(bpkg):]
-    bpkg_str = string.join(bpkg, "-")
-    bver_str = string.join(bver, "-")    
-    
-    if apkg_str > bpkg_str:
-       return 1
-    elif bpkg_str > apkg_str:
-       return -1
-    else:
-       return gentoolkit.compare_versions(aver_str, bver_str)
-    
-# .-------------------------------------------------------.
-# | Simple Package Search Function                        |
-# +-------------------------------------------------------+
-# | Given a search key, returns a list of packages that   |
-# | satisfy the regex.                                    |
-# | Results are in the form ["net-www/mozilla"]           |
-# `-------------------------------------------------------'
-def search(search_key):
-    matches = []    
-    for package in portage.portdb.cp_all():
-       package_parts=package.split("/")
-       if re.search(search_key.lower(), package_parts[1].lower()):
-           matches.append(package)
-    return matches
-
-# .-------------------------------------------------------.
-# | Package Name Guesser                                  |
-# +-------------------------------------------------------+
-# | A smart (eg. dodgy) version of portage.catpkgsplit()  |
-# | that determines the category, package, version and    |
-# | revision given a string. If it doesn't know, it'll    |
-# | leave the field blank.                                |
-# |                                                       |
-# | Returns a list like :                                 |
-# |  [ "net-www", "mozilla", "1.1", "r1"]                 |
-# `-------------------------------------------------------'    
-
-def smart_pkgsplit(query):
-    raise "Use something else"
-    cat = ''
-    pkg = ''
-    ver = ''
-    rev = ''
-    
-    if len(query.split('/')) == 2:
-       cat = query.split('/')[0]
-       query = query.split('/')[1]
-    
-    components = query.split('-')
-    name_components = []
-    ver_components = []
-       
-    # seperate pkg-ver-rev
-    for c in components:
-       if ver_components:
-           ver_components.append(c)
-       elif ord(c[0]) > 47 and ord(c[0]) < 58:
-           ver_components.append(c)
-       else:
-           name_components.append(c)
-    pkg = '-'.join(name_components)
-       
-    # check if there is a revision number
-    if len(ver_components) > 0 and ver_components[-1][0] == 'r':
-       rev = ver_components[-1]
-       ver_components = ver_components[:-1]
-       
-    # check for version number
-    if len(ver_components) > 0:
-       ver = '-'.join(ver_components)
-    
-    return [cat, pkg, ver, rev]
-
-# .-------------------------------------------------------.
-# | Return the Location of the Ebuild                     |
 # +-------------------------------------------------------+
-# | Guesses the version that you want. Eg. if one is      |
-# | specified, then we use it, otherwise, the latest one  |
-# `-------------------------------------------------------'
-
-def smart_ebuild(query):
-    pkg = gentoolkit.find_packages(query)
-    if len(pkg)>1:
-        raise "Too many packages to handle"
-    return pkg[0].get_ebuild_path()
-    
-
-# .-------------------------------------------------------.
 # | Pretty Print Log                                      |
 # +-------------------------------------------------------+
 # | Extracts and prints out the log entry corresponding   |
@@ -312,7 +201,7 @@ def output_log(lines, package_ver=""):
 
 def changes(query):
     matches=gentoolkit.find_packages(query)
-    if not report_matches(query,matches):
+    if not report_matches(query,matches,installed_only=0):
         return
 
     for pkg in matches:
@@ -380,26 +269,21 @@ def versions(query):
         print
 
 # .-------------------------------------------------------.
-# | List USE flags for a single ebuild                    |
+# | List USE flags for a single ebuild, if it's installed |
 # +-------------------------------------------------------+
 # | Just uses the new IUSE parameter in ebuilds           |
 # `-------------------------------------------------------' 
-def uses(query): # FIXME: Use gentoolkit
+def uses(query):
     
-    tup = smart_pkgsplit(query)
-    if tup[0] and tup[1]:
-       matches = [ tup[0] + "/" + tup[1] ]
-    elif tup[1]:
-       matches = gentoolkit.find_packages(tup[1])
+    matches = gentoolkit.find_packages(query)
        
-    useflags = portage.config()["USE"].split()    
+    useflags = gentoolkit.settings["USE"].split()    
     usedesc = {}
     uselocaldesc = {}
-    # open up use.desc
-    
+
+    # Load global USE flag descriptions
     try:
-       # TODO: use portage settings
-       fd = open("/usr/portage/profiles/use.desc")
+       fd = open(gentoolkit.settings["PORTDIR"]+"/profiles/use.desc")
        usedesc = {}
        for line in fd.readlines():
            if line[0] == "#":
@@ -409,10 +293,10 @@ def uses(query): # FIXME: Use gentoolkit
                usedesc[fields[0].strip()] = fields[1].strip()
     except IOError:
        pass
-               
+
+    # Load local USE flag descriptions
     try:
-       # TODO: use portage.settings
-       fd = open("/usr/portage/profiles/use.local.desc")
+       fd = open(gentoolkit.settings["PORTDIR"]+"/profiles/use.local.desc")
        for line in fd.readlines():
            if line[0] == "#":
                continue
@@ -430,37 +314,24 @@ def uses(query): # FIXME: Use gentoolkit
     print "[ Colour Code : " + green("set") + " " + red("unset") + " ]"
     print "[ Legend      : (U) Col 1 - Current USE flags        ]"
     print "[             : (I) Col 2 - Installed With USE flags ]"
-    
+
+    # Iterate through matches, printing a report for each package
     for p in matches:
-       curver = portage.db["/"]["porttree"].dbapi.match(p)
-       bestver = portage.best(curver)
-       if bestver:
-           try:
-               iuse = portage.db["/"]["porttree"].dbapi.aux_get(bestver,["IUSE"])
-           except KeyError:
-               print "[ Error Occured. Ebuild not found for :", white(p), "]"
-               continue
-       else:
-           print "[ * No USE flags found for :", white(p), "]"
-           continue
+        if not p.is_installed():
+            continue
+    
+       bestver = p.get_cpv()
+        iuse = p.get_env_var("IUSE")
        
-       if iuse: usevar = iuse[0].split()
+       if iuse: usevar = iuse.split()
        else: usevar = []
        
-       # find flags in use for this package if installed
        inuse = []
-       installed = glob.glob("/var/db/pkg/" + p + "-*")
-       if installed:
-           try:
-               used = open(installed[-1] + "/USE").read().split()
-           except IOError:
-               used = []
-       else:
-           used = []
+        used = p.get_use_vars().split()
 
        # store (inuse, inused, flag, desc)
        output = []
-       
+
        for u in usevar:
            inuse = 0
            inused = 0
@@ -502,209 +373,77 @@ def uses(query): # FIXME: Use gentoolkit
                else:
                    print ": unknown"
        else:
-           print "[ No USE flags found for :", white(p), "]"       
+           print "[ No USE flags found for :", white(p.get_cpv()), "]"     
 
     return
 
-    # deprecated - this was a hack anyway
-    #print "[ Can't find IUSE variable in : " + white(os.path.basename(ebuild)[:-7]) + " ]"
-    #print turquoise("*") + " Applying search manually .."
-    #old_uses(query)
-    
-# .-------------------------------------------------------.
-# | Uses a general rules that has all use's with either   |
-# |  `use alsa` or in the DEPENDS/RDEPENDS field of the   |
-# | ebuild suffixed by a "?"                              |
-# `-------------------------------------------------------' 
-
-def old_uses(query):
-    ebuild = smart_ebuild(query)
-    useflags = portage.config()["USE"].split()
-    uses = {}
-    # TODO : can't handle 2 or more 'use blah' in one line
-    re_use_sh = re.compile('`use ([a-zA-Z0-9]*)`')
-    re_depend = re.compile('[R]?DEPEND="')
-    re_use_dep = re.compile('([a-zA-Z0-9]+)\?')
-    is_depend = 0
-    
-    for line in open(ebuild).readlines():
-       if len(line.strip()) and line.strip()[0] == "#":
-           continue
-       
-       # find uses in DEPEND and RDEPEND variables
-       if is_depend:
-           if re.search('"[\s]*$',line): is_depend = 0 # end of depend     
-           is_use = re_use_dep.search(line)
-           if is_use: uses[is_use.group(1)] = 1
-           continue
-           
-       if re_depend.search(line):
-           is_depend = 1 # start of depend
-           is_use = re_use_dep.search(line)
-           if is_use: uses[is_use.group(1)] = 1
-           continue
-       
-       # find uses in other places like if [ -n "`use blah`" ]
-       is_use = re_use_sh.search(line)
-       if is_use:
-           uses[is_use.group(1)] = 1
-    if uses:
-       iuse = uses.keys()
-       iuse.sort()
-       for u in iuse:
-           if u in useflags:
-               print "+", green(u)
-           else:
-               print "-", red(u)
-    else:
-       print red("*") + " Unable to find any USE variables."
-
 # .-------------------------------------------------------.
 # | Graphs the Dependency Tree for a package              |
 # +-------------------------------------------------------+
 # | Naive graphing of dependencies
 # `-------------------------------------------------------'
-graphcache = []
-
-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, [])
-
-# return string of deps that are valid
-def depuseparse(depstring):
-    raw_deps = depstring.strip().split()
-    out_deps = []
-    uselist = portage.config()["USE"].split()
-    
-    dep_len = len(raw_deps)
-    i = 0
-    uselevel = 0
-    orlevel = 0
-    ordone = 0
-    
-    while i < dep_len:
-       #---- if we encounter a use? ( ) 
-       if raw_deps[i][-1] == "?":
-           if raw_deps[i][:-1] in uselist:
-               uselevel += 1
-           else:
-               # read until we find a ")"
-               i += 1
-               while i < dep_len:
-                   if raw_deps[i] == ")":
-                       break
-                   else:
-                       i += 1
-       #---- if we encounter a || or use?
-        elif raw_deps[i] == "||":
-           orlevel += 1
-       elif orlevel > 0 or uselevel > 0:
-           if raw_deps[i] == "(":
-               pass
-           elif raw_deps[i] == ")":
-               if uselevel > 0:
-                   uselevel -= 1
-               elif orlevel > 0:
-                   orlevel -= 1
-                   ordone = 0
-           else:
-               if orlevel and ordone == 0:
-                   ordone += 1
-                   out_deps.append(raw_deps[i])
-               elif uselevel > 0:
-                   out_deps.append(raw_deps[i])
-       #---- good 'ole plain deps
-        elif raw_deps not in [")","("]:
-           out_deps.append(raw_deps[i])
-       # increment counter
-       i+=1
-       
-    return out_deps
-           
-def graph_node_print(path, dep):
-    indent = len(path)-1
-    if path == []:
-       print dep
-    else:
-       print "  " + "  "*indent + "`-- " + dep
 
-def rgraph(dep, path):
-    global graphcache
-    
-    # stop circular deps
-    if dep in path:
-       return "  "*len(path) + "!! circular dependency"
-    
-    # find in portage
-    matches = portage.db["/"]["porttree"].dbapi.match(dep)
-    x = portage.best(matches)
-    
-    # skip if we've already included this in the tree
-    if x in graphcache:
-       return []
-    else:
-       graphcache.append(x)
+def graph(query):
+    matches = gentoolkit.find_packages(query)
+    if not report_matches(query, matches):
+        return
 
-    # try open up this package's deps
-    try:
-       f = open("/var/cache/edb/dep/%s" % x)
-       f.readline() # read RDEPENDS
-       depends = depuseparse(f.readline())
-       graph_node_print(path, x)
-       for d in depends:
-           if d in graphcache:
-               continue
-           if d in portage.db["/"]["virtuals"].keys():
-               virtual = portage.db["/"]["virtuals"][d]
-               graphcache += rgraph(virtual, path + [dep])
-           else:
-               graphcache += rgraph(d, path + [dep])
-    except IOError:
-       # silent this for the moment
-       #print "! Error findind deps."
-       return []
+    for pkg in matches:
+        if not pkg.is_installed():
+            continue
+        rgraph(pkg)
+
+def rgraph(pkg,level=0,pkgtbl=[],suffix=""):
+
+    cpv=pkg.get_cpv()
+
+    print level*" " + "`-- " + cpv + suffix
+    pkgtbl.append(cpv)
+    
+    for x in pkg.get_runtime_deps():
+        suffix=""
+        cpv=x[2]
+        pkg=gentoolkit.find_best_match(x[0] + cpv)
+        if not pkg:
+            continue
+        if pkg.get_cpv() in pkgtbl:
+            continue
+        if cpv.find("virtual")==0:
+            suffix+=" (" + cpv + ")"
+        if len(x[1]):
+            suffix+=" [ " + string.join(x[1]) + " ]"
+        pkgtbl=rgraph(pkg,level+1,pkgtbl,suffix)
+    return pkgtbl
 
-    return depends
-       
 # .-------------------------------------------------------.
 # | Required By Function                                  |
 # +-------------------------------------------------------+
 # | Find what packages require a given package name       |
 # `-------------------------------------------------------'
 
-def depends(query): # FIXME: Use gentoolkit
+def depends(query):
     
     print "[ Results for search key : " + white(query) + " ]"
 
-    isdepend = re.compile(r'([^\s]*' + query + '[^\s]*)')
-    
-    match_depend = {}
-    match_rdepend = {}
-
-#    for x in gentoolkit.find_all_packages():
-        
-    # get all installed packages
-    for x in os.listdir(portage.root + "var/cache/edb/dep"):
-        # for each category, we just grep for the deps, slowly
-        for dep in os.listdir(portage.root + "var/cache/edb/dep/" + x):
-            f = open("%s/var/cache/edb/dep/%s/%s" % (portage.root, x, dep))
-           depend = f.readline()
-            rdepend = f.readline()
-           f.close()
-           match = isdepend.search(rdepend)
-           if match:
-               match_rdepend[x+"/"+dep] = match.groups()
-           match = isdepend.search(depend)
-            if match:
-               match_depend[x+"/"+dep] = match.groups()
-               
-           if match_depend.has_key(x+"/"+dep):
-               print turquoise("*"), white(x+"/"+dep)
-               for line in match_depend[x+"/"+dep]:
-                   print "  " + line
-    
+    isdepend = gentoolkit.split_package_name(query)
     
+    for pkg in gentoolkit.find_all_packages():
+        if pkg.is_installed():
+            deps = pkg.get_runtime_deps()
+            for x in deps:
+                cpvs=gentoolkit.split_package_name(x[2])
+                cat_match=0
+                ver_match=0
+                name_match=0
+                if not isdepend[0] or isdepend[0] == cpvs[0]:
+                    cat_match=1
+                if not isdepend[2] or \
+                   (isdepend[2] == cpvs[2] and isdepend[3] == cpvs[3]):
+                    ver_match=1
+                if isdepend[1] == cpvs[1]:
+                    name_match=1
+                if cat_match and ver_match and name_match:
+                    print turquoise("*"), white(pkg.get_cpv()), white("[ ") + string.join(x[1]), white("]")
 
 # .-------------------------------------------------------.
 # | Belongs to which package                              |
@@ -712,7 +451,7 @@ def depends(query): # FIXME: Use gentoolkit
 # | Finds what package a file belongs to                  |
 # `-------------------------------------------------------'        
            
-def belongs(query): # FIXME: use gentoolkit
+def belongs(query):
 
     q = query.split()
 
@@ -727,43 +466,14 @@ def belongs(query): # FIXME: use gentoolkit
 
     print "Searching for " + item + " in " + cat + " ..."
 
-    matches = gentoolkit.find_all_packages(fn)
+    matches = gentoolkit.find_all_installed_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"
-
-    q_regex = re.sub(r'\.',r'\.',query[0])
-    q_regex = re.sub(r'\*',r'\[^\s]*', q_regex)
-    
-    reobj = re.compile(r'^[a-zA-Z]{3}[\s](' + q_regex + r')[\s]', re.M)
-    
-    if len(query) >= 2:
-       category = query[1]
-    else:
-       category = "*"
-       
-    print "Searching for", query[0], "in", category, "..."
-       
-    for catdir in glob.glob(dbdir + "/" + category):
-       cat =  catdir.split("/")[-1]
-       for pkg in os.listdir(catdir):
-           try:
-               contents = open(catdir + "/" + pkg + "/CONTENTS").read()
-               matches = reobj.search(contents)
-               if matches:
-                   print cat + "/" + pkg
-           except IOError:
-               pass
+                break # We know this pkg matches, look for any more matches
     return
        
 # .-------------------------------------------------------.
@@ -775,14 +485,14 @@ def size(query):
     packages = gentoolkit.find_packages(query)
     if not report_matches(query, packages):
         return
+
     for pkg in packages:
         if not pkg.is_installed():
             continue
         x=pkg.size()
-        cpv=x[0]
-        size=x[1]
-        files=x[2]
-        uncounted=x[3]
+        size=x[0]
+        files=x[1]
+        uncounted=x[2]
         print turquoise("*") + " " + white(pkg.get_cpv())
         print string.rjust(" Total Files : ",25) + str(files)
         if uncounted:
@@ -790,17 +500,20 @@ def size(query):
         print string.rjust(" Total Size : ",25) + "%.2f KB" % (size/1024.0)
 
 
-def report_matches(query, matches):
-    print "[ Results for search key : " + white(query) + " ]"
-    print "[ Applications found : " + white(str(len(matches))) + " ]"
+def report_matches(query, matches, installed_only=1):
+    print "[ Results for search key       : " + white(query) + " ]"
+    print "[ Candidate applications found : " + white(str(len(matches))) + " ]"
     print
-    
-    if matches:
-#      print " Only printing found installed programs."
+
+    if installed_only and matches:
+       print " Only printing found installed programs."
        print
+    elif installed_only:
+       print "No packages found."
+
+    if matches:
         return 1
     else:
-       print "No packages found."
         return 0
 
 
@@ -810,9 +523,7 @@ def report_matches(query, matches):
 # | Lists all the files in a package                      |
 # `-------------------------------------------------------'        
 def files(query):
-
     matches = gentoolkit.find_packages(query)
-
     if not report_matches(query, matches):
         return
     
@@ -904,3 +615,5 @@ if __name__ == "__main__":
        main()
     except KeyboardInterrupt:
        print "Operation Aborted!"
+
+
index fab5b865da273be87e4363e50459218e8d1b5df7..b299e5a2424bb908b32606b5e13de36c4de30014 100644 (file)
@@ -23,6 +23,7 @@ import string
 settings = portage.settings
 porttree = portage.db[portage.root]["porttree"]
 vartree  = portage.db[portage.root]["vartree"]
+virtuals = portage.db[portage.root]["virtuals"]
 
 # Nomenclature:
 #
@@ -51,15 +52,49 @@ class Package:
     def get_cpv(self):
         """Returns full Category/Package-Version string"""
         return self._cpv
+    def get_provides(self):
+        """Return a list of provides, if any"""
+        return vartree.get_provides(self._cpv)
     def get_dependants(self):
         """Retrieves a list of CPVs for all packages depending on this one"""
-        raise "Not implemented!"
-    def get_compiletime_dependencies(self):
-        """Returns a list of first-level compile time dependencies for this package"""
-        raise "Not implemented!"
-    def get_runtime_dependencies(self):
-        """Returns a list of first-level run time dependencies for this package"""
-        raise "Not implemented!"
+        raise "Not implemented yet!"
+    def get_runtime_deps(self):
+        """Returns a linearised list of first-level compile time dependencies for this package, on
+        the form [(comparator, [use flags], cpv), ...]"""
+        cd=self.get_env_var("RDEPEND").split()
+        r,i=self._parse_deps(cd)
+        return r
+    def get_compiletime_deps(self):
+        """Returns a linearised list of first-level compile time dependencies for this package, on
+        the form [(comparator, [use flags], cpv), ...]"""
+        rd=self.get_env_var("DEPEND").split()
+        r,i=self._parse_deps(rd)
+        return r
+    def _parse_deps(self,deps,curuse=[],level=0):
+        # store (comparator, [use predicates], cpv)
+        r=[]
+        comparators=["~","<",">","=","<=",">="]
+        end=len(deps)
+        i=0
+        while i < end:
+            tok=deps[i]
+            if tok == ')':
+                return r,i
+            if tok[-1] == "?" or tok[0] == "!":
+                tok=tok.replace("?","")
+                sr,l = self._parse_deps(deps[i+2:],curuse=curuse+[tok],level=level+1)
+                r += sr
+                i+=l+3
+                continue
+            # pick out comparator, if any
+            cmp=""
+            for c in comparators:
+                if tok.find(c) == 0:
+                    cmp=c
+            tok=tok[len(cmp):]
+            r.append((cmp,curuse,tok))
+            i+=1
+        return r,i
     def is_installed(self):
         """Returns true if this package is installed (merged)"""
         self._initdb()
@@ -72,9 +107,12 @@ class Package:
         the package actually exists on disk somewhere."""
         unmasked = portage.portdb.xmatch("match-visible", "=" + self._cpv)
         return self._cpv not in unmasked
-    def get_ebuild_path(self):
+    def get_ebuild_path(self,in_vartree=0):
         """Returns the complete path to the .ebuild file"""
-        return portage.portdb.findname(self._cpv)
+        if in_vartree:
+            return vartree.getebuildpath(self._cpv)
+        else:
+            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()
@@ -83,10 +121,18 @@ class Package:
             return string.join(sp[:-1],"/")
     def get_env_var(self, var):
         """Returns one of the predefined env vars DEPEND, RDEPEND, SRC_URI,...."""
-        r=porttree.dbapi.aux_get(self._cpv,[var])
+        r=vartree.dbapi.aux_get(self._cpv,[var])
+        if not r:
+            raise "WTF??"
         if len(r)!=1:
             raise "Should only get one element!"
         return r[0]
+    def get_use_vars(self):
+        """Returns the USE flags active at time of installation"""
+        self._initdb()
+        if self.is_installed():
+            return self._db.getfile("USE")
+        return ""
     def get_contents(self):
         """Returns the full contents, as a dictionary, on the form
         [ '/bin/foo' : [ 'obj', '1052505381', '45ca8b8975d5094cd75bdc61e9933691' ], ... ]"""
@@ -102,6 +148,8 @@ class Package:
             return None
         return portage.pkgcmp(v1[1:],v2[1:])
     def size(self):
+        """Estimates the installed size of the contents of this package, if possible.
+        Returns [size, number of files in total, number of uncounted files]"""
         contents = self.get_contents()
         size=0
         uncounted = 0
@@ -112,7 +160,7 @@ class Package:
                 files += 1
             except OSError:
                 uncounted += 1
-        return [self.get_cpv(), size, files, uncounted]
+        return [size, files, uncounted]
 
     def _initdb(self):
         """Internal helper function; loads package information from disk,
@@ -121,9 +169,9 @@ class Package:
             cat=self.get_category()
             pnv=self.get_name()+"-"+self.get_version()
             self._db=portage.dblink(cat,pnv,"")
+
 #
-# Should we add stuff like size, depends, files, here?
-#
+# Global helper functions
 #
 
 def find_packages(search_key):
@@ -132,8 +180,32 @@ def find_packages(search_key):
     t=portage.portdb.match(search_key)
     return map(lambda x: Package(x), t)
 
+def find_best_match(search_key):
+    """Returns a Package object for the best available installed candidate that
+    matched the search key. Doesn't handle virtuals perfectly"""
+    # FIXME: How should we handled versioned virtuals??
+    cat,pkg,ver,rev=split_package_name(search_key)
+    if cat == "virtual":
+        t=vartree.dep_bestmatch(cat+"/"+pkg)
+    else:
+        t=vartree.dep_bestmatch(search_key)
+    if t:
+        return Package(t)
+    return None
+
+def find_all_installed_packages(prefilter=None):
+    """Returns a list of all installed packages, after applying the prefilter
+    function"""
+    t=vartree.getallcpv()
+    if prefilter:
+        t=filter(prefilter,t)
+    return map(lambda x: Package(x), t)
+    
+    return find_all_packages(prefilter,1)
+
 def find_all_packages(prefilter=None):
-    """Returns a list of all known packages, installed or not."""
+    """Returns a list of all known packages, installed or not, after applying
+    the prefilter function"""
     t=portage.portdb.cp_all()
     if prefilter:
         t=filter(prefilter,t)
@@ -142,6 +214,21 @@ def find_all_packages(prefilter=None):
         t2 += portage.portdb.cp_list(x)
     return map(lambda x: Package(x), t2)
 
+def split_package_name(name):
+    """Returns a list on the form [category, name, version, revision]. Revision will
+    be 'r0' if none can be inferred. Category and version will be empty, if none can
+    be inferred."""
+    r=portage.catpkgsplit(name)
+    if not r:
+        r=name.split("/")
+        if len(r) == 1:
+            return ["",name,"","r0"]
+        else:
+            return r + ["","r0"]
+    if r[0] == 'null':
+        r[0] = ''
+    return r
+
 if __name__ == "__main__":
     print "This module is for import only"
 
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..f126a3609b010b28e519ffb5bd81e953f1bea74a 100644 (file)
@@ -0,0 +1,5 @@
+Maintainer:
+Karl Trygve Kalleberg <karltk@gentoo.org>
+
+Authors:
+Leo Lipelis <aeoo@gentoo.org> (original author)
index 37366906514f8ae68e6934780e93cd0bfd3081fb..e1f477a11f09af33675bc88b3c482721b49935dd 100644 (file)
@@ -10,7 +10,7 @@
 #
 # qpkg - query portage package system for various information
 #
-# This is a reimplementation of the qpkg written in bash, by 
+# This is a reimplementation of the previous qpkg, written in bash, by 
 # Vitaly Kushneriuk <vitaly_kushneriuk@yahoo.com>,
 # Brandon Low <lostlogic@gentoo.org>,
 # Josh Goebel <dreamer@firesedge.org>
@@ -49,20 +49,21 @@ def showUsage():
     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 "\n" + white("Package selection:")
     print blue("-f,   --find-file") + "\tfinds package that owns file <file>"
     print blue("-fp,  --find-pattern") + "\tfinds package that owns file matching *<pattern>*"
+    print blue("-m,   --masked") + "\tinclude " + yellow("only") + " masked packages"
+    print blue("-n,   --non-masked") + "\tinclude " + yellow("only") + " installed packages"
+    print blue("-U,   --uninstalled") + "\tinclude " + yellow("only") + " uninstalled packages"
+    print blue("-g,   --group") + "\t\tfind by group (can be combined with other searches"
+
+    print "\n" + white("Information selection:")
+    print blue("-l,   --list") + "\t\tlist package content"
+    print blue("-i,   --info") + "\t\tget package description and home page")
+    print blue("-ct,  --check-time")
+    print blue("-tc,  --time-check") + "\tverify package files' time stamps"
+    
     """
-
-${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.