]> git.decadent.org.uk Git - dak.git/blob - helena
* vars: external-overrides variable added* cron.daily: Update testing/unstable Task...
[dak.git] / helena
1 #!/usr/bin/env python
2
3 # Produces a report on NEW and BYHAND packages
4 # Copyright (C) 2001, 2002, 2003  James Troup <james@nocrew.org>
5 # $Id: helena,v 1.5 2003-07-15 17:29:26 troup Exp $
6
7 # This program is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 2 of the License, or
10 # (at your option) any later version.
11
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 # GNU General Public License for more details.
16
17 # You should have received a copy of the GNU General Public License
18 # along with this program; if not, write to the Free Software
19 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20
21 ################################################################################
22
23 # <o-o> XP runs GCC, XFREE86, SSH etc etc,.,, I feel almost like linux....
24 # <o-o> I am very confident that I can replicate any Linux application on XP
25 # <willy> o-o: *boggle*
26 # <o-o> building from source.
27 # <o-o> Viiru: I already run GIMP under XP
28 # <willy> o-o: why do you capitalise the names of all pieces of software?
29 # <o-o> willy: because I want the EMPHASIZE them....
30 # <o-o> grr s/the/to/
31 # <willy> o-o: it makes you look like ZIPPY the PINHEAD
32 # <o-o> willy: no idea what you are talking about.
33 # <willy> o-o: do some research
34 # <o-o> willy: for what reason?
35
36 ################################################################################
37
38 import copy, glob, os, stat, sys, time;
39 import apt_pkg;
40 import katie, utils;
41
42 Cnf = None;
43 Katie = None;
44
45 ################################################################################
46
47 def usage(exit_code=0):
48     print """Usage: helena
49 Prints a report of packages in queue directories (usually new and byhand).
50
51   -h, --help                show this help and exit."""
52     sys.exit(exit_code)
53
54 ################################################################################
55
56 def plural(x):
57     if x > 1:
58         return "s";
59     else:
60         return "";
61
62 ################################################################################
63
64 def time_pp(x):
65     if x < 60:
66         unit="second";
67     elif x < 3600:
68         x /= 60;
69         unit="minute";
70     elif x < 86400:
71         x /= 3600;
72         unit="hour";
73     elif x < 604800:
74         x /= 86400;
75         unit="day";
76     elif x < 2419200:
77         x /= 604800;
78         unit="week";
79     elif x < 29030400:
80         x /= 2419200;
81         unit="month";
82     else:
83         x /= 29030400;
84         unit="year";
85     x = int(x);
86     return "%s %s%s" % (x, unit, plural(x));
87
88 ################################################################################
89
90 def sg_compare (a, b):
91     a = a[1];
92     b = b[1];
93     """Sort by have note, time of oldest upload."""
94     # Sort by have note
95     a_note_state = a["note_state"];
96     b_note_state = b["note_state"];
97     if a_note_state < b_note_state:
98         return -1;
99     elif a_note_state > b_note_state:
100         return 1;
101
102     # Sort by time of oldest upload
103     return cmp(a["oldest"], b["oldest"]);
104
105 ############################################################
106
107 def process_changes_files(changes_files, type):
108     msg = "";
109     cache = {};
110     # Read in all the .changes files
111     for filename in changes_files:
112         try:
113             Katie.pkg.changes_file = filename;
114             Katie.init_vars();
115             Katie.update_vars();
116             cache[filename] = copy.copy(Katie.pkg.changes);
117             cache[filename]["filename"] = filename;
118         except:
119             break;
120     # Divide the .changes into per-source groups
121     per_source = {};
122     for filename in cache.keys():
123         source = cache[filename]["source"];
124         if not per_source.has_key(source):
125             per_source[source] = {};
126             per_source[source]["list"] = [];
127         per_source[source]["list"].append(cache[filename]);
128     # Determine oldest time and have note status for each source group
129     for source in per_source.keys():
130         source_list = per_source[source]["list"];
131         first = source_list[0];
132         oldest = os.stat(first["filename"])[stat.ST_CTIME];
133         have_note = 0;
134         for d in per_source[source]["list"]:
135             ctime = os.stat(d["filename"])[stat.ST_CTIME];
136             if ctime < oldest:
137                 oldest = ctime;
138             have_note += (d.has_key("lisa note"));
139         per_source[source]["oldest"] = oldest;
140         if not have_note:
141             per_source[source]["note_state"] = 0; # none
142         elif have_note < len(source_list):
143             per_source[source]["note_state"] = 1; # some
144         else:
145             per_source[source]["note_state"] = 2; # all
146     per_source_items = per_source.items();
147     per_source_items.sort(sg_compare);
148
149     entries = [];
150     max_source_len = 0;
151     max_version_len = 0;
152     max_arch_len = 0;
153     for i in per_source_items:
154         last_modified = time.time()-i[1]["oldest"];
155         source = i[1]["list"][0]["source"];
156         if len(source) > max_source_len:
157             max_source_len = len(source);
158         arches = {};
159         versions = {};
160         for j in i[1]["list"]:
161             for arch in j["architecture"].keys():
162                 arches[arch] = "";
163             version = j["version"];
164             versions[version] = "";
165         arches_list = arches.keys();
166         arches_list.sort(utils.arch_compare_sw);
167         arch_list = " ".join(arches_list);
168         version_list = " ".join(versions.keys());
169         if len(version_list) > max_version_len:
170             max_version_len = len(version_list);
171         if len(arch_list) > max_arch_len:
172             max_arch_len = len(arch_list);
173         if i[1]["note_state"]:
174             note = " | [N]";
175         else:
176             note = "";
177         entries.append([source, version_list, arch_list, note, time_pp(last_modified)]);
178
179     format="%%-%ds | %%-%ds | %%-%ds%%s | %%s old\n" % (max_source_len, max_version_len, max_arch_len)
180     msg = "";
181     for entry in entries:
182         (source, version_list, arch_list, note, last_modified) = entry;
183         msg += format % (source, version_list, arch_list, note, last_modified);
184
185     if msg:
186         total_count = len(changes_files);
187         source_count = len(per_source_items);
188         print type.upper();
189         print "-"*len(type);
190         print
191         print msg;
192         print "%s %s source package%s / %s %s package%s in total." % (source_count, type, plural(source_count), total_count, type, plural(total_count));
193         print
194
195 ################################################################################
196
197 def main():
198     global Cnf, Katie;
199
200     Cnf = utils.get_conf();
201     Arguments = [('h',"help","Helena::Options::Help")];
202     for i in [ "help" ]:
203         if not Cnf.has_key("Helena::Options::%s" % (i)):
204             Cnf["Helena::Options::%s" % (i)] = "";
205
206     apt_pkg.ParseCommandLine(Cnf, Arguments, sys.argv);
207
208     Options = Cnf.SubTree("Helena::Options")
209     if Options["Help"]:
210         usage();
211
212     Katie = katie.Katie(Cnf);
213
214     directories = Cnf.ValueList("Helena::Directories");
215     if not directories:
216         directories = [ "byhand", "new" ];
217
218     for directory in directories:
219         changes_files = glob.glob("%s/*.changes" % (Cnf["Dir::Queue::%s" % (directory)]));
220         process_changes_files(changes_files, directory);
221
222 ################################################################################
223
224 if __name__ == '__main__':
225     main();