X-Git-Url: https://git.decadent.org.uk/gitweb/?a=blobdiff_plain;f=helena;h=d33b19e385f3176e005accc27f71cccc073ce2c7;hb=dd0ee5b67c650470139ffa8a50ae6b83a92ca76a;hp=7337461013320e5e370a2169ea7735be131111f4;hpb=9e78deadeefb78533360179077669f763f0f483c;p=dak.git diff --git a/helena b/helena index 73374610..d33b19e3 100755 --- a/helena +++ b/helena @@ -1,8 +1,8 @@ #!/usr/bin/env python # Produces a report on NEW and BYHAND packages -# Copyright (C) 2001, 2002, 2003 James Troup -# $Id: helena,v 1.5 2003-07-15 17:29:26 troup Exp $ +# Copyright (C) 2001, 2002, 2003, 2005 James Troup +# $Id: helena,v 1.6 2005-11-15 09:50:32 ajt Exp $ # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -38,9 +38,12 @@ import copy, glob, os, stat, sys, time; import apt_pkg; import katie, utils; +import encodings.utf_8, encodings.latin_1, string; Cnf = None; Katie = None; +direction = []; +row_number = 0; ################################################################################ @@ -48,7 +51,19 @@ def usage(exit_code=0): print """Usage: helena Prints a report of packages in queue directories (usually new and byhand). - -h, --help show this help and exit.""" + -h, --help show this help and exit. + -n, --new produce html-output + -s, --sort=key sort output according to key, see below. + -a, --age=key if using sort by age, how should time be treated? + If not given a default of hours will be used. + + Sorting Keys: ao=age, oldest first. an=age, newest first. + na=name, ascending nd=name, descending + nf=notes, first nl=notes, last + + Age Keys: m=minutes, h=hours, d=days, w=weeks, o=months, y=years + +""" sys.exit(exit_code) ################################################################################ @@ -104,6 +119,149 @@ def sg_compare (a, b): ############################################################ +def sortfunc(a,b): + for sorting in direction: + (sortkey, way, time) = sorting; + ret = 0 + if time == "m": + x=int(a[sortkey]/60) + y=int(b[sortkey]/60) + elif time == "h": + x=int(a[sortkey]/3600) + y=int(b[sortkey]/3600) + elif time == "d": + x=int(a[sortkey]/86400) + y=int(b[sortkey]/86400) + elif time == "w": + x=int(a[sortkey]/604800) + y=int(b[sortkey]/604800) + elif time == "o": + x=int(a[sortkey]/2419200) + y=int(b[sortkey]/2419200) + elif time == "y": + x=int(a[sortkey]/29030400) + y=int(b[sortkey]/29030400) + else: + x=a[sortkey] + y=b[sortkey] + if x < y: + ret = -1 + elif x > y: + ret = 1 + if ret != 0: + if way < 0: + ret = ret*-1 + return ret + return 0 + +############################################################ + +def header(): + print """ + + Debian NEW and BYHAND Packages + + + + +
+ + + + Debian Project +
+
+ + + + + + + + + + +
+ Debian NEW and BYHAND Packages +
+ +
+ """ + +def footer(): + print "

Timestamp: %s (UTC)

" % (time.strftime("%d.%m.%Y / %H:%M:%S", time.gmtime())) + print "

Hint: Age is the youngest upload of the package, if there is more than one version.

" + print "

You may want to look at the REJECT-FAQ for possible reasons why one of the above packages may get rejected.

" + print """ + Valid HTML 4.01! + + Valid CSS! + """ + print "" + +def table_header(type): + print "

Summary for: %s

" % (type) + print """
+ + + + + + + + + + """ + +def table_footer(type, source_count, total_count): + print "
PackageVersionArchDistributionAgeMaintainerCloses

\n" + print "

Package count in %s: %s\n" % (type, source_count) + print "
Total Package count: %s

\n" % (total_count) + +def force_to_latin(s): + """Forces a string to Latin-1.""" + latin1_s = unicode(s,'utf-8'); + return latin1_s.encode('iso8859-1', 'replace'); + + +def table_row(source, version, arch, last_mod, maint, distribution, closes): + + global row_number; + + if row_number % 2 != 0: + print "" + else: + print "" + + tdclass = "sid" + for dist in distribution: + if dist == "experimental": + tdclass = "exp"; + print "%s" % (tdclass, source); + print "" % (tdclass) + for vers in version.split(): + print "%s
" % (vers); + print "%s" % (tdclass, arch, tdclass); + for dist in distribution: + print "%s
" % (dist); + print "%s" % (tdclass, last_mod); + (name, mail) = maint.split(":"); + name = force_to_latin(name); + + print "%s" % (tdclass, mail, name); + print "" % (tdclass) + for close in closes: + print "#%s
" % (close, close); + print ""; + row_number+=1; + +############################################################ + def process_changes_files(changes_files, type): msg = ""; cache = {}; @@ -129,12 +287,16 @@ def process_changes_files(changes_files, type): for source in per_source.keys(): source_list = per_source[source]["list"]; first = source_list[0]; - oldest = os.stat(first["filename"])[stat.ST_CTIME]; + oldest = os.stat(first["filename"])[stat.ST_MTIME]; have_note = 0; for d in per_source[source]["list"]: - ctime = os.stat(d["filename"])[stat.ST_CTIME]; - if ctime < oldest: - oldest = ctime; + mtime = os.stat(d["filename"])[stat.ST_MTIME]; + if Cnf.has_key("Helena::Options::New"): + if mtime > oldest: + oldest = mtime; + else: + if mtime < oldest: + oldest = mtime; have_note += (d.has_key("lisa note")); per_source[source]["oldest"] = oldest; if not have_note: @@ -150,6 +312,11 @@ def process_changes_files(changes_files, type): max_source_len = 0; max_version_len = 0; max_arch_len = 0; + maintainer = {}; + maint=""; + distribution=""; + closes=""; + source_exists=""; for i in per_source_items: last_modified = time.time()-i[1]["oldest"]; source = i[1]["list"][0]["source"]; @@ -158,6 +325,18 @@ def process_changes_files(changes_files, type): arches = {}; versions = {}; for j in i[1]["list"]: + if Cnf.has_key("Helena::Options::New"): + try: + (maintainer["maintainer822"], maintainer["maintainer2047"], + maintainer["maintainername"], maintainer["maintaineremail"]) = \ + utils.fix_maintainer (j["maintainer"]); + except utils.ParseMaintError, msg: + print "Problems while parsing maintainer address\n"; + maintainer["maintainername"] = "Unknown"; + maintainer["maintaineremail"] = "Unknown"; + maint="%s:%s" % (maintainer["maintainername"], maintainer["maintaineremail"]); + distribution=j["distribution"].keys(); + closes=j["closes"].keys(); for arch in j["architecture"].keys(): arches[arch] = ""; version = j["version"]; @@ -174,23 +353,77 @@ def process_changes_files(changes_files, type): note = " | [N]"; else: note = ""; - entries.append([source, version_list, arch_list, note, time_pp(last_modified)]); + entries.append([source, version_list, arch_list, note, last_modified, maint, distribution, closes]); + + # direction entry consists of "Which field, which direction, time-consider" where + # time-consider says how we should treat last_modified. Thats all. + + # Look for the options for sort and then do the sort. + age = "h" + if Cnf.has_key("Helena::Options::Age"): + age = Cnf["Helena::Options::Age"] + if Cnf.has_key("Helena::Options::New"): + # If we produce html we always have oldest first. + direction.append([4,-1,"ao"]); + else: + if Cnf.has_key("Helena::Options::Sort"): + for i in Cnf["Helena::Options::Sort"].split(","): + if i == "ao": + # Age, oldest first. + direction.append([4,-1,age]); + elif i == "an": + # Age, newest first. + direction.append([4,1,age]); + elif i == "na": + # Name, Ascending. + direction.append([0,1,0]); + elif i == "nd": + # Name, Descending. + direction.append([0,-1,0]); + elif i == "nl": + # Notes last. + direction.append([3,1,0]); + elif i == "nf": + # Notes first. + direction.append([3,-1,0]); + entries.sort(lambda x, y: sortfunc(x, y)) + # Yes, in theory you can add several sort options at the commandline with. But my mind is to small + # at the moment to come up with a real good sorting function that considers all the sidesteps you + # have with it. (If you combine options it will simply take the last one at the moment). + # Will be enhanced in the future. + + if Cnf.has_key("Helena::Options::New"): + direction.append([4,1,"ao"]); + entries.sort(lambda x, y: sortfunc(x, y)) + # Output for a html file. First table header. then table_footer. + # Any line between them is then a printed from subroutine table_row. + if len(entries) > 0: + table_header(type.upper()); + for entry in entries: + (source, version_list, arch_list, note, last_modified, maint, distribution, closes) = entry; + table_row(source, version_list, arch_list, time_pp(last_modified), maint, distribution, closes); + total_count = len(changes_files); + source_count = len(per_source_items); + table_footer(type.upper(), source_count, total_count); + else: + # The "normal" output without any formatting. + format="%%-%ds | %%-%ds | %%-%ds%%s | %%s old\n" % (max_source_len, max_version_len, max_arch_len) + + msg = ""; + for entry in entries: + (source, version_list, arch_list, note, last_modified, undef, undef, undef) = entry; + msg += format % (source, version_list, arch_list, note, time_pp(last_modified)); + + if msg: + total_count = len(changes_files); + source_count = len(per_source_items); + print type.upper(); + print "-"*len(type); + print + print msg; + print "%s %s source package%s / %s %s package%s in total." % (source_count, type, plural(source_count), total_count, type, plural(total_count)); + print - format="%%-%ds | %%-%ds | %%-%ds%%s | %%s old\n" % (max_source_len, max_version_len, max_arch_len) - msg = ""; - for entry in entries: - (source, version_list, arch_list, note, last_modified) = entry; - msg += format % (source, version_list, arch_list, note, last_modified); - - if msg: - total_count = len(changes_files); - source_count = len(per_source_items); - print type.upper(); - print "-"*len(type); - print - print msg; - print "%s %s source package%s / %s %s package%s in total." % (source_count, type, plural(source_count), total_count, type, plural(total_count)); - print ################################################################################ @@ -198,7 +431,10 @@ def main(): global Cnf, Katie; Cnf = utils.get_conf(); - Arguments = [('h',"help","Helena::Options::Help")]; + Arguments = [('h',"help","Helena::Options::Help"), + ('n',"new","Helena::Options::New"), + ('s',"sort","Helena::Options::Sort", "HasArg"), + ('a',"age","Helena::Options::Age", "HasArg")]; for i in [ "help" ]: if not Cnf.has_key("Helena::Options::%s" % (i)): Cnf["Helena::Options::%s" % (i)] = ""; @@ -211,6 +447,9 @@ def main(): Katie = katie.Katie(Cnf); + if Cnf.has_key("Helena::Options::New"): + header(); + directories = Cnf.ValueList("Helena::Directories"); if not directories: directories = [ "byhand", "new" ]; @@ -219,6 +458,9 @@ def main(): changes_files = glob.glob("%s/*.changes" % (Cnf["Dir::Queue::%s" % (directory)])); process_changes_files(changes_files, directory); + if Cnf.has_key("Helena::Options::New"): + footer(); + ################################################################################ if __name__ == '__main__':