]> git.decadent.org.uk Git - dak.git/blob - helena
sync
[dak.git] / helena
1 #!/usr/bin/env python
2
3 # Produces a report on NEW and BYHAND packages
4 # Copyright (C) 2001, 2002  James Troup <james@nocrew.org>
5 # $Id: helena,v 1.3 2002-12-08 17:25:47 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 plural (x):
48     if x > 1:
49         return "s";
50     else:
51         return "";
52
53 ################################################################################
54
55 def time_pp(x):
56     if x < 60:
57         unit="second";
58     elif x < 3600:
59         x /= 60;
60         unit="minute";
61     elif x < 86400:
62         x /= 3600;
63         unit="hour";
64     elif x < 604800:
65         x /= 86400;
66         unit="day";
67     elif x < 2419200:
68         x /= 604800;
69         unit="week";
70     elif x < 29030400:
71         x /= 2419200;
72         unit="month";
73     else:
74         x /= 29030400;
75         unit="years";
76     x = int(x);
77     return "%s %s%s" % (x, unit, plural(x));
78
79 ################################################################################
80
81 def sg_compare (a, b):
82     a = a[1];
83     b = b[1];
84     """Sort by have note, time of oldest upload."""
85     # Sort by have note
86     a_note_state = a["note_state"];
87     b_note_state = b["note_state"];
88     if a_note_state < b_note_state:
89         return -1;
90     elif a_note_state > b_note_state:
91         return 1;
92
93     # Sort by time of oldest upload
94     return cmp(a["oldest"], b["oldest"]);
95
96 ############################################################
97
98 def process_changes_files(changes_files, type):
99     msg = "";
100     cache = {};
101     # Read in all the .changes files
102     for filename in changes_files:
103         try:
104             Katie.pkg.changes_file = filename;
105             Katie.init_vars();
106             Katie.update_vars();
107             cache[filename] = copy.copy(Katie.pkg.changes);
108             cache[filename]["filename"] = filename;
109         except:
110             break;
111     # Divide the .changes into per-source groups
112     per_source = {};
113     for filename in cache.keys():
114         source = cache[filename]["source"];
115         if not per_source.has_key(source):
116             per_source[source] = {};
117             per_source[source]["list"] = [];
118         per_source[source]["list"].append(cache[filename]);
119     # Determine oldest time and have note status for each source group
120     for source in per_source.keys():
121         source_list = per_source[source]["list"];
122         first = source_list[0];
123         oldest = os.stat(first["filename"])[stat.ST_CTIME];
124         have_note = 0;
125         for d in per_source[source]["list"]:
126             ctime = os.stat(d["filename"])[stat.ST_CTIME];
127             if ctime < oldest:
128                 oldest = ctime;
129             have_note += (d.has_key("lisa note"));
130         per_source[source]["oldest"] = oldest;
131         if not have_note:
132             per_source[source]["note_state"] = 0; # none
133         elif have_note < len(source_list):
134             per_source[source]["note_state"] = 1; # some
135         else:
136             per_source[source]["note_state"] = 2; # all
137     per_source_items = per_source.items();
138     per_source_items.sort(sg_compare);
139
140     entries = [];
141     max_source_len = 0;
142     max_version_len = 0;
143     max_arch_len = 0;
144     for i in per_source_items:
145         last_modified = time.time()-i[1]["oldest"];
146         source = i[1]["list"][0]["source"];
147         if len(source) > max_source_len:
148             max_source_len = len(source);
149         arches = {};
150         versions = {};
151         for j in i[1]["list"]:
152             for arch in j["architecture"].keys():
153                 arches[arch] = "";
154             version = j["version"];
155             versions[version] = "";
156         arches_list = arches.keys();
157         arches_list.sort(utils.arch_compare_sw);
158         arch_list = " ".join(arches_list);
159         version_list = " ".join(versions.keys());
160         if len(version_list) > max_version_len:
161             max_version_len = len(version_list);
162         if len(arch_list) > max_arch_len:
163             max_arch_len = len(arch_list);
164         if i[1]["note_state"]:
165             note = " | [N]";
166         else:
167             note = "";
168         entries.append([source, version_list, arch_list, note, time_pp(last_modified)]);
169
170     format="%%-%ds | %%-%ds | %%-%ds%%s | %%s old\n" % (max_source_len, max_version_len, max_arch_len)
171     msg = "";
172     for entry in entries:
173         (source, version_list, arch_list, note, last_modified) = entry;
174         msg += format % (source, version_list, arch_list, note, last_modified);
175
176     if msg:
177         total_count = len(changes_files);
178         source_count = len(per_source_items);
179         print type.upper();
180         print "-"*len(type);
181         print
182         print msg;
183         print "%s %s source package%s / %s %s package%s in total." % (source_count, type, plural(source_count), total_count, type, plural(total_count));
184         print
185
186 ################################################################################
187
188 def main():
189     global Cnf, Katie;
190
191     Cnf = utils.get_conf();
192     apt_pkg.ParseCommandLine(Cnf,[],sys.argv);
193     Katie = katie.Katie(Cnf);
194
195     directories = Cnf.ValueList("Helena::Directories");
196     if not directories:
197         directories = [ "byhand", "new"]
198
199     for directory in directories:
200         changes_files = glob.glob("%s/*.changes" % (Cnf["Dir::Queue::%s" % (directory)]));
201         process_changes_files(changes_files, directory);
202
203 ################################################################################
204
205 if __name__ == '__main__':
206     main();