Bump imlate to 0.0.4, see ChangeLog for more details.
authoridl0r <idl0r@gentoo.org>
Wed, 9 Sep 2009 16:22:35 +0000 (16:22 -0000)
committeridl0r <idl0r@gentoo.org>
Wed, 9 Sep 2009 16:22:35 +0000 (16:22 -0000)
svn path=/trunk/gentoolkit-dev/; revision=678

ChangeLog
src/imlate/imlate

index 4ed50e11ba8a87982a50bc6e146af0f0b3113166..b66b82bab5a4bb59ddaaabbc259c88c614cdbc09 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2009-09-09: Christian Ruppert <idl0r@gentoo.org>
+       * src/imlate/imlate: Bump to 0.0.4.
+               Add SLOT support.
+               Add option to specify the minimum mtime for the mtime check.
+               Add search by herd or maintainer.
+               Add single package mode.
+               Automatic detection of TARGET/MAIN-_ARCH.
+
 2009-09-06: Christian Ruppert <idl0r@gentoo.org>
        * src/echangelog/echangelog: Fix regex, thanks to Magnus Granberg (zorry) <zorry@ume.nu>.
 
index 0e945c77d8ac53f18ee3a1104199b4e469849d57..872af97dd8a9697b1ddd6df6c72a3dbcde649328 100755 (executable)
@@ -6,11 +6,16 @@
 
 # author: Christian Ruppert <idl0r@gentoo.org>
 
-VERSION = "0.0.3"
+VERSION = "0.0.4"
 
 # works just with stable keywords!
-MAIN_ARCH = "amd64" # can be overridden by -m ARCH
-TARGET_ARCH = "x86" # can be overridden by -t ARCH
+MAIN_ARCH = "auto" # can be overridden by -m ARCH
+TARGET_ARCH = "auto" # can be overridden by -t ARCH
+# auto means e.g.:
+# MAIN_ARCH = amd64
+# TARGET_ARCH = ~amd64
+# That will show you general stable candidates for amd64.
+# The arch will be taken from your portage settings (e.g. make.conf).
 
 ################################
 # do not change anything below #
@@ -20,6 +25,8 @@ from os.path import join, basename
 from sys import stderr, stdout
 from os import stat
 from time import time
+from xml.dom import minidom, NotFoundErr
+from xml.parsers.expat import ExpatError
 # TODO: just import needed stuff to safe memory and maybe use "as foo"
 import portage
 
@@ -71,7 +78,7 @@ def show_result( conf, pkgs ):
        col2 = 20
 
        _header = "%s candidates for 'gentoo' on '%s'"
-       _helper = "category/package                        our version         best version"
+       _helper = "category/package[:SLOT]                 our version         best version"
        _cand = ""
        header = ""
 
@@ -111,6 +118,85 @@ def show_result( conf, pkgs ):
        if conf["FILE"] != "stdout":
                out.close()
 
+def _get_metadata(metadata, element, tag):
+       values = []
+
+       try:
+               metadatadom = minidom.parse(metadata)
+       except ExpatError, e:
+               raise ExpatError("%s: %s" % (metadata, e,))
+
+       try:
+               elements = metadatadom.getElementsByTagName(element)
+               if not elements:
+                       return values
+       except NotFoundErr:
+               return values
+
+       try:
+               for _element in elements:
+                       node = _element.getElementsByTagName(tag)
+
+                       if tag == "herd" and (not node or not node[0].childNodes):
+                               print >> stderr, "'%s' is missing a <herd> tag or it is empty," % metadata
+                               print >> stderr, "please file a bug at https://bugs.gentoo.org and refer to http://www.gentoo.org/proj/en/devrel/handbook/handbook.xml?part=2&chap=4"
+                               values.append("no-herd")
+                               continue
+
+                       values.append(node[0].childNodes[0].data)
+       except NotFoundErr:
+               raise NotFoundErr("%s: Malformed input: missing 'flag' tag(s)" % (metadata))
+
+       metadatadom.unlink()
+       return values
+
+def is_maintainer(maintainer, metadata):
+       data = []
+
+       if maintainer == None:
+               return True
+
+       mtainer = maintainer.split(",")
+
+       data = _get_metadata(metadata, "maintainer", "email")
+
+       if not data and len(maintainer) == 0:
+               return True
+       elif not data and len(maintainer) > 0:
+               return False
+       else:
+               for addy in data:
+                       for foo in mtainer:
+                               if addy == foo:
+                                       return True
+                               if addy.startswith(foo):
+                                       return True
+       return False
+
+def is_herd(herd, metadata):
+       data = []
+
+       if herd == None:
+               return True
+
+       hrd = herd.split(",")
+       data = _get_metadata(metadata, "pkgmetadata", "herd")
+
+       if not data and len(herd) == 0:
+               return True
+       elif not data and len(herd) > 0:
+               return False
+       else:
+               for hd in data:
+                       for hd2 in hrd:
+                               if hd == hd2:
+                                       return True
+                               if hd.startswith(hd2):
+                                       return True
+       
+       return False
+
+
 # fetch a list of arch (just stable) packages
 # -* is important to be sure that just arch is used
 def get_packages( conf ):
@@ -120,19 +206,44 @@ def get_packages( conf ):
                                        conf["portdb"].settings )
 
        for cp in conf["portdb"].dbapi.cp_all():
-               cpvr = portage.best( conf["portdb"].dbapi.match( cp ) )
-               if cpvr:
-                       ( cat, pkg, ver, rev ) = portage.catpkgsplit( cpvr )
+               cpvrs = []
+               slots = {}
 
-                       if not cat in _pkgs.keys():
-                               _pkgs[cat] = {}
-                       if not pkg in _pkgs[cat].keys():
-                               _pkgs[cat][pkg] = []
+               if conf["USER_PKGS"]:
+                       if not cp in conf["USER_PKGS"]:
+                               continue
 
-                       if rev != "r0":
-                               ver = "%s-%s" % ( ver, rev )
+               # None is important to match also on empty string
+               if conf["MAINTAINER"] != None:
+                       if not is_maintainer(conf["MAINTAINER"], join(conf["PORTDIR"], cp, "metadata.xml")):
+                               continue
+               if conf["HERD"] != None:
+                       if not is_herd(conf["HERD"], join(conf["PORTDIR"], cp, "metadata.xml")):
+                               continue
+
+               cpvrs = conf["portdb"].dbapi.match( cp )
+
+               for cpvr in cpvrs:
+                       slot = conf["portdb"].dbapi.aux_get( cpvr, ["SLOT"] )[0]
+                       if not slot in slots:
+                               slots[slot] = []
+                       slots[slot].append(cpvr)
+               
+               for slot in sorted(slots):
+                       cpvr = portage.best( slots[slot] )
+
+                       if cpvr:
+                               ( cat, pkg, ver, rev ) = portage.catpkgsplit( cpvr )
+
+                               if not cat in _pkgs.keys():
+                                       _pkgs[cat] = {}
+                               if not pkg in _pkgs[cat].keys():
+                                       _pkgs[cat][pkg] = []
 
-                       _pkgs[cat][pkg].append( ver )
+                               if rev != "r0":
+                                       ver = "%s-%s" % ( ver, rev )
+
+                               _pkgs[cat][pkg].append( ver )
 
        return _pkgs
 
@@ -150,81 +261,88 @@ def get_imlate( conf, pkgs ):
 
        for cat in sorted( pkgs.keys() ):
                for pkg in sorted( pkgs[cat].keys() ):
-                       cpvr = ""
-                       abs_pkg = ""
-                       kwds = ""
-                       our = ""
-                       our_ver = ""
-                       mtime = 0
-
-                       # 0 = none(default), 1 = testing(~arch), 2 = stable(arch),
-                       # 3 = exclude(-arch), 4 = exclude_all(-*)
-                       # -* would be overridden by ~arch or arch
-                       kwd_type = 0
-
-                       cpvr = "%s/%s-%s" % ( cat, pkg, pkgs[cat][pkg][0] )
-
-                       # absolute ebuild path for mtime check
-                       abs_pkg = join( conf["PORTDIR"], cat, pkg, basename( cpvr ) )
-                       abs_pkg = "%s.ebuild" % str( abs_pkg )
-
-                       kwds = conf["portdb"].dbapi.aux_get( cpvr, ["KEYWORDS"] )[0]
-
-                       # sorted() to keep the right order
-                       # e.g. -* first, -arch second, arch third and ~arch fourth
-                       # -* -foo ~arch
-                       # example: -* would be overridden by ~arch
-                       for kwd in sorted( kwds.split() ):
-                               if kwd == stable:
-                                       kwd_type = 2
-                                       break
-                               elif kwd == exclude:
-                                       kwd_type = 3
-                                       break
-                               # EXPERIMENTAL
-                               elif kwd == exclude_all and conf["EXPERIMENTAL"]:
-                                       kwd_type = 4
-                               elif kwd == testing:
-                                       kwd_type = 1
-                                       break
-
-                       # ignore -arch and already stabilized packages
-                       if kwd_type == 3 or kwd_type == 2:
-                               continue
-                       # EXPERIMENTAL
-                       # drop packages without ~arch or arch but -*
-                       # even if there is another version which includes arch or ~arch
-                       if kwd_type == 4 and conf["EXPERIMENTAL"]:
-                               continue
-                       # drop "stable candidates" with mtime < 30 days
-                       # Shall we use gmtime/UTC here?
-                       if kwd_type == 1:
-                               mtime = int( ( time() - stat( abs_pkg ).st_mtime ) / 60 / 60 / 24 )
-                               if mtime < 30:
-                                       continue
-
-                       # look for an existing stable version
-                       our = portage.best( conf["portdb"].dbapi.match( "%s/%s" % ( cat, pkg ) ) )
-                       if our:
-                               _foo = portage.pkgsplit( our )
-                               our_ver = _foo[1]
-                               if _foo[2] != "r0":
-                                       our_ver = "%s-%s" % ( our_ver, _foo[2] )
-                       else:
+                       for vr in pkgs[cat][pkg]:
+                               cpvr = ""
+                               abs_pkg = ""
+                               kwds = ""
+                               our = ""
                                our_ver = ""
-
-                       # we just need the version if > our_ver
-                       if our_ver:
-                               if portage.vercmp( our_ver, pkgs[cat][pkg][0] ) >= 0:
+                               mtime = 0
+                               slot = 0
+       
+                               # 0 = none(default), 1 = testing(~arch), 2 = stable(arch),
+                               # 3 = exclude(-arch), 4 = exclude_all(-*)
+                               # -* would be overridden by ~arch or arch
+                               kwd_type = 0
+
+                               cpvr = "%s/%s-%s" % ( cat, pkg, vr )
+       
+                               # absolute ebuild path for mtime check
+                               abs_pkg = join( conf["PORTDIR"], cat, pkg, basename( cpvr ) )
+                               abs_pkg = "%s.ebuild" % str( abs_pkg )
+       
+                               kwds = conf["portdb"].dbapi.aux_get( cpvr, ["KEYWORDS"] )[0]
+       
+                               # FIXME: %s is bad.. maybe even cast it, else there are issues because its unicode
+                               slot = ":%s" % conf["portdb"].dbapi.aux_get( cpvr, ["SLOT"] )[0]
+                               if slot == ":0":
+                                       slot = ""
+       
+                               # sorted() to keep the right order
+                               # e.g. -* first, -arch second, arch third and ~arch fourth
+                               # -* -foo ~arch
+                               # example: -* would be overridden by ~arch
+                               for kwd in sorted( kwds.split() ):
+                                       if kwd == stable:
+                                               kwd_type = 2
+                                               break
+                                       elif kwd == exclude:
+                                               kwd_type = 3
+                                               break
+                                       # EXPERIMENTAL
+                                       elif kwd == exclude_all and conf["EXPERIMENTAL"]:
+                                               kwd_type = 4
+                                       elif kwd == testing:
+                                               kwd_type = 1
+                                               break
+       
+                               # ignore -arch and already stabilized packages
+                               if kwd_type == 3 or kwd_type == 2:
                                        continue
-
-                       if kwd_type == 1 and conf["STABLE"]:
-                               imlate = _add_ent( imlate, cat, pkg, pkgs[cat][pkg][0], our_ver )
-                               conf["STABLE_SUM"] += 1
-                       elif kwd_type == 0 and conf["KEYWORD"]:
-                               conf["KEYWORD_SUM"] += 1
-                               imlate = _add_ent( imlate, cat, ( "~%s" % str( pkg ) ),
-                                                               pkgs[cat][pkg][0], our_ver )
+                               # EXPERIMENTAL
+                               # drop packages without ~arch or arch but -*
+                               # even if there is another version which includes arch or ~arch
+                               if kwd_type == 4 and conf["EXPERIMENTAL"]:
+                                       continue
+                               # drop "stable candidates" with mtime < 30 days
+                               # Shall we use gmtime/UTC here?
+                               if kwd_type == 1:
+                                       mtime = int( ( time() - stat( abs_pkg ).st_mtime ) / 60 / 60 / 24 )
+                                       if mtime < conf["MTIME"]:
+                                               continue
+       
+                               # look for an existing stable version
+                               our = portage.best( conf["portdb"].dbapi.match( "%s/%s%s" % ( cat, pkg, slot ) ) )
+                               if our:
+                                       _foo = portage.pkgsplit( our )
+                                       our_ver = _foo[1]
+                                       if _foo[2] != "r0":
+                                               our_ver = "%s-%s" % ( our_ver, _foo[2] )
+                               else:
+                                       our_ver = ""
+       
+                               # we just need the version if > our_ver
+                               if our_ver:
+                                       if portage.vercmp( our_ver, vr ) >= 0:
+                                               continue
+       
+                               if kwd_type == 1 and conf["STABLE"]:
+                                       imlate = _add_ent( imlate, cat, ("%s%s" % (pkg, slot)), vr, our_ver )
+                                       conf["STABLE_SUM"] += 1
+                               elif kwd_type == 0 and conf["KEYWORD"]:
+                                       conf["KEYWORD_SUM"] += 1
+                                       imlate = _add_ent( imlate, cat, ( "~%s%s" % (pkg, slot) ),
+                                                                       vr, our_ver )
 
        return imlate
 
@@ -238,6 +356,11 @@ def get_settings( conf = None ):
        # TODO: maybe we should improve it a bit ;)
        mysettings = portage.config( config_incrementals = portage.const.INCREMENTALS, local_config = False )
 
+       if conf["MAIN_ARCH"] == "auto":
+               conf["MAIN_ARCH"] = "%s" % mysettings["ACCEPT_KEYWORDS"].split(" ")[0].lstrip("~")
+       if conf["TARGET_ARCH"] == "auto":
+               conf["TARGET_ARCH"] = "~%s" % mysettings["ACCEPT_KEYWORDS"].split(" ")[0].lstrip("~")
+
        # TODO: exclude overlay categories from check
        if conf["CATEGORIES"]:
                _mycats = []
@@ -271,6 +394,7 @@ def main():
        pkgs = {}
 
        parser = OptionParser( version = "%prog " + VERSION )
+       parser.usage = "%prog [options] [category/package] ..."
        parser.disable_interspersed_args()
 
        parser.add_option( "-f", "--file", dest = "filename", action = "store", type = "string",
@@ -279,6 +403,8 @@ def main():
                                        help = "set main ARCH (e.g. your arch) [default: %default]", metavar = "ARCH", default = MAIN_ARCH )
        parser.add_option( "-t", "--target", dest = "target_arch", action = "store", type = "string",
                                        help = "set target ARCH (e.g. x86) [default: %default]", metavar = "ARCH", default = TARGET_ARCH )
+       parser.add_option( "--mtime", dest = "mtime", action = "store", type = "int",
+                       help = "set minimum MTIME in days [default: %default]", metavar = "MTIME", default = 30 )
 
        # TODO: leave a good comment here (about True/False) :)
        parser.add_option( "-s", "--stable", dest = "stable", action = "store_true", default = False,
@@ -286,6 +412,12 @@ def main():
        parser.add_option( "-k", "--keyword", dest = "keyword", action = "store_true", default = False,
                                        help = "just show keyword candidates (e.g. -s and -k is the default result) [default: True]" )
 
+       parser.add_option( "-M", "--maintainer", dest = "maintainer", action = "store", type = "string",
+                       help = "Show only packages from the specified maintainer", metavar = "MAINTAINER", default = None)
+
+       parser.add_option( "-H", "--herd", dest = "herd", action = "store", type = "string",
+                       help = "Show only packages from the specified herd", metavar = "HERD", default = None)
+
        # EXPERIMENTAL
        parser.add_option( "-e", "--experimental", dest = "experimental", action = "store_true", default = False,
                                        help = "enables experimental functions/features (have a look for # EXPERIMENTAL comments in the source) [default: %default]" )
@@ -297,8 +429,9 @@ def main():
        ( options, args ) = parser.parse_args()
 
        if len( args ) > 0:
-               parser.print_help()
-               parser.error( "unknown arg(s)" )
+               conf["USER_PKGS"] = args
+       else:
+               conf["USER_PKGS"] = []
 
        # cleanup optparse
        try:
@@ -316,15 +449,16 @@ def main():
        conf["KEYWORD_SUM"] = 0
        conf["STABLE_SUM"] = 0
 
-       if not options.main_arch in portage.archlist:
+       if not options.main_arch in portage.archlist and options.main_arch != "auto":
                raise ValueError, "invalid MAIN ARCH defined!"
-       if not options.target_arch in portage.archlist:
+       if not options.target_arch in portage.archlist and options.target_arch != "auto":
                raise ValueError, "invalid TARGET ARCH defined!"
 
        conf["MAIN_ARCH"] = options.main_arch
        conf["TARGET_ARCH"] = options.target_arch
 
        conf["FILE"] = options.filename
+       conf["MTIME"] = options.mtime
 
        if not options.stable and not options.keyword:
                conf["STABLE"] = True
@@ -336,6 +470,9 @@ def main():
        conf["EXPERIMENTAL"] = options.experimental
        conf["CATEGORIES"] = options.categories
 
+       conf["MAINTAINER"] = options.maintainer
+       conf["HERD"] = options.herd
+
        # append to our existing
        conf = get_settings( conf )
        pkgs = get_packages( conf )