From e1518048e8abc4a6e118f409833e6f94dff97e0e Mon Sep 17 00:00:00 2001 From: idl0r Date: Wed, 9 Sep 2009 16:22:35 +0000 Subject: [PATCH] Bump imlate to 0.0.4, see ChangeLog for more details. svn path=/trunk/gentoolkit-dev/; revision=678 --- ChangeLog | 8 ++ src/imlate/imlate | 319 +++++++++++++++++++++++++++++++++------------- 2 files changed, 236 insertions(+), 91 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4ed50e1..b66b82b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2009-09-09: Christian Ruppert + * 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 * src/echangelog/echangelog: Fix regex, thanks to Magnus Granberg (zorry) . diff --git a/src/imlate/imlate b/src/imlate/imlate index 0e945c7..872af97 100755 --- a/src/imlate/imlate +++ b/src/imlate/imlate @@ -6,11 +6,16 @@ # author: Christian Ruppert -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 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 ) -- 2.26.2