/[collab-qa]/udd/udd/bugs_gatherer.pl
ViewVC logotype

Contents of /udd/udd/bugs_gatherer.pl

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1694 - (show annotations) (download)
Sun Feb 21 11:09:22 2010 UTC (3 years, 2 months ago) by lucas
File MIME type: text/plain
File size: 12741 byte(s)
import bugs_blocks/blockedby info
1 #!/usr/bin/perl -w
2 # Last-Modified: <Mon Aug 18 14:29:47 2008>
3
4 use strict;
5 use warnings;
6
7 use FindBin '$Bin';
8
9 # We need our own copy of Debbugs::Status for now
10 use lib $Bin, qw{/org/udd.debian.net/mirrors/bugs.debian.org/perl}, qw{/org/udd.debian.org/bugs/bugs.debian.org/perl};
11
12 use DBI;
13 use DBI qw{:sql_types};
14 use YAML::Syck;
15 use Time::Local;
16
17 use Debbugs::Bugs qw{get_bugs};
18 use Debbugs::Status qw{read_bug get_bug_status bug_presence};
19 use Debbugs::Packages qw{getpkgsrc};
20 use Debbugs::Config qw{:globals %config};
21 use Debbugs::User;
22 use Mail::Address;
23 #use Debbugs::User qw{read_usertags};
24
25 $YAML::Syck::ImplicitTyping = 1;
26
27 #Used for measuring time
28 our $t;
29 our $timing = 0;
30 our @archs = grep { !/(^m68k$|^kfreebsd|^hurd)/ } @{$config{default_architectures}};
31
32 # Return the list of usernames
33 sub get_bugs_users {
34 my $topdir = "$gSpoolDir/user";
35 my @ret = ();
36 # see Debbugs::User::filefromemail for why 0...6
37 for(my $i = 0; $i < 7; $i++) {
38 my $dir = "$topdir/$i";
39 opendir DIR, $dir or die "Can't open dir $dir: $!";
40 # Replace all occurences of %dd with the corresponding
41 # character represented by dd, where dd is a hexadecimal
42 # number
43 push @ret, map { s/%(..)/chr(hex($1))/ge; $_ } readdir DIR;
44 }
45 return @ret;
46 }
47
48 sub parse_time {
49 if(shift =~ /(\d\d\d\d)-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d)/) {
50 return ($1, $2, $3, $4, $5, $6);
51 }
52 return undef;
53 }
54
55
56 sub get_db_max_last_modified {
57 my $dbh = shift or die "Argument required";
58 my $sth = $dbh->prepare("SELECT MAX (last_modified) FROM bugs");
59 $sth->execute() or die $!;
60 my $date = $sth->fetchrow_array();
61 if(defined $date) {
62 my ($year, $month, $day, $hour, $minute, $second) = parse_time($date);
63 return timelocal($second, $minute, $hour, $day, $month-1, $year);
64 } else {
65 return 0;
66 }
67 }
68
69 sub get_mtime {
70 return ((stat(shift))[9]);
71 }
72
73 sub get_modified_bugs {
74 my $prune_stamp = shift;
75 die "Argument required" unless defined $prune_stamp;
76 my $top_dir = $gSpoolDir;
77 my @result = ();
78 foreach my $sub (qw(archive db-h)) {
79 my $spool = "$top_dir/$sub";
80 foreach my $subsub (glob "$spool/*") {
81 if( -d $subsub and get_mtime($subsub) > $prune_stamp ) {
82 push @result,
83 map { s{.*/(.*)\.log}{$1}; $_ }
84 grep { get_mtime("$_") > $prune_stamp }
85 glob "$subsub/*.log";
86 }
87 }
88 }
89 return \@result;
90 }
91
92 sub without_duplicates {
93 my %h = ();
94 return (grep { ($h{$_}++ == 0) || 0 } @_);
95 }
96
97 sub run_usertags {
98 my ($config, $source, $dbh) = @_;
99 my %src_config = %{$config->{$source}};
100 my $table = $src_config{'usertags-table'} or die "usertags-table not specified for source $source";
101 our $timing;
102 our $t;
103
104
105 $t = time();
106 # Free usertags table
107 $dbh->do("DELETE FROM $table") or die
108 "Couldn't empty $table: $!";
109 print "Deleting usertags: ",(time() - $t),"s\n" if $timing;
110 $t = time();
111 # read and insert user tags
112 my @users = get_bugs_users();
113 foreach my $user (@users) {
114 #read_usertags(\%tags, $user);
115 my $u = Debbugs::User->new($user);
116 my %tags = %{$u->{tags}};
117 $user = $dbh->quote($user);
118 foreach my $tag (keys %tags) {
119 my $qtag = $dbh->quote($tag);
120 map { $dbh->do("INSERT INTO $table (email, tag, id) VALUES ($user, $qtag, $_)") or die $! } @{$tags{$tag}};
121 }
122 }
123 }
124
125 sub run {
126 my ($config, $source, $dbh) = @_;
127
128 our $t;
129 our $timing;
130 my %src_config = %{$config->{$source}};
131 my $table = $src_config{table};
132 my $archived_table = $src_config{'archived-table'};
133
134 if (!$src_config{debug}) {
135 run_usertags($config, $source, $dbh);
136 print "Inserting usertags: ",(time() - $t),"s\n" if $timing;
137 $t = time();
138 }
139
140
141 my %pkgsrc = %{getpkgsrc()};
142
143 my @modified_bugs;
144
145 if($src_config{archived}) {
146 # some bugs (the unarchived ones) are in both list. exclude them.
147 my %unarchived;
148 foreach my $b (get_bugs()) {
149 $unarchived{$b} = 1;
150 }
151 foreach my $b (get_bugs(archive => 1)) {
152 push(@modified_bugs, $b) if not $unarchived{$b};
153 }
154 } else {
155 @modified_bugs = get_bugs();
156 }
157 my @modified_bugs2;
158 if ($src_config{debug}) {
159 print "Running in debug mode with restricted bug list!!\n";
160 foreach my $b (@modified_bugs) {
161 push(@modified_bugs2, $b) if ($b =~ /58$/);
162 }
163 @modified_bugs = @modified_bugs2;
164 }
165
166 print "Fetching list of ",scalar(@modified_bugs), " bugs to insert: ",(time() - $t),"s\n" if $timing;
167 $t = time();
168
169 foreach my $prefix ($table, $archived_table) {
170 foreach my $postfix (qw{_packages _merged_with _found_in _fixed_in _tags _blocks _blockedby}, '') {
171 my $sth = $dbh->prepare("DELETE FROM $prefix$postfix WHERE id = \$1");
172 map {
173 $sth->execute($_) or die $!;
174 } @modified_bugs;
175 }
176 }
177 print "Deleting bugs: ",(time() - $t),"s\n" if $timing;
178 $t = time();
179
180 my $location = $src_config{archived} ? 'archive' : 'db_h';
181 $table = $src_config{archived} ? $archived_table : $table;
182 # Read all bugs
183 my $insert_bugs_handle = $dbh->prepare("INSERT INTO $table (id, package, source, arrival, status, severity, submitter, submitter_name, submitter_email, owner, owner_name, owner_email, done, done_name, done_email, title, forwarded, last_modified, affects_stable, affects_testing, affects_unstable, affects_experimental) VALUES (\$1, \$2, \$3, \$4::abstime, \$5, \$6, \$7, \$8, \$9, \$10, \$11, \$12, \$13, \$14, \$15, \$16, \$17, \$18::abstime, \$19, \$20, \$21, \$22)");
184 my $insert_bugs_packages_handle = $dbh->prepare("INSERT INTO ${table}_packages (id, package, source) VALUES (\$1, \$2, \$3)");
185 my $insert_bugs_found_handle = $dbh->prepare("INSERT INTO ${table}_found_in (id, version) VALUES (\$1, \$2)");
186 my $insert_bugs_fixed_handle = $dbh->prepare("INSERT INTO ${table}_fixed_in (id, version) VALUES (\$1, \$2)");
187 my $insert_bugs_merged_handle = $dbh->prepare("INSERT INTO ${table}_merged_with (id, merged_with) VALUES (\$1, \$2)");
188 my $insert_bugs_tags_handle = $dbh->prepare("INSERT INTO ${table}_tags (id, tag) VALUES (\$1, \$2)");
189 my $insert_bugs_blocks_handle = $dbh->prepare("INSERT INTO ${table}_blocks (id, blocked) VALUES (\$1, \$2)");
190 my $insert_bugs_blockedby_handle = $dbh->prepare("INSERT INTO ${table}_blockedby (id, blocker) VALUES (\$1, \$2)");
191 $insert_bugs_handle->bind_param(4, undef, SQL_INTEGER);
192 $insert_bugs_handle->bind_param(18, undef, SQL_INTEGER);
193
194 $t = time();
195 foreach my $bug_nr (@modified_bugs) {
196 # Fetch bug using Debbugs
197 # Bugs which were once archived and have been unarchived again will appear in get_bugs(archive => 1).
198 # However, those bugs are not to be found in location 'archive', so we detect them, and skip them
199 my $bug_ref = read_bug(bug => $bug_nr, location => $location) or (print STDERR "Could not read file for bug $bug_nr; skipping\n" and next);
200 # Yeah, great, why does get_bug_status not accept a location?
201 my %bug = %{get_bug_status(bug => $bug_nr, status => $bug_ref)};
202
203 # Convert data where necessary
204 my @found_versions = @{$bug{found_versions}};
205 my @fixed_versions = @{$bug{fixed_versions}};
206 my @tags = split / /, $bug{keywords};
207
208 # log_modified and date are not necessarily set. If they are not available, they
209 # are assumed to be epoch (i.e. bug #4170)
210 map {
211 if($bug{$_}) {
212 $bug{$_} = int($bug{$_});
213 } else {
214 $bug{$_} = 0;
215 }
216 } qw{date log_modified};
217
218 my $srcpkg;
219 if ($bug{package} =~ /^src:(.*)/)
220 {
221 $srcpkg = $1;
222 } else {
223 $srcpkg = exists($pkgsrc{$bug{package}}) ? $pkgsrc{$bug{package}} : $bug{package};
224 }
225
226 # split emails
227 my (@addr, $submitter_name, $submitter_email, $owner_name, $owner_email, $done_name, $done_email);
228 if ($bug{originator}) {
229 @addr = Mail::Address->parse($bug{originator});
230 $submitter_name = $addr[0]->phrase;
231 $submitter_email = $addr[0]->address;
232 } else {
233 $submitter_name = '';
234 $submitter_email = '';
235 }
236
237 if ($bug{owner}) {
238 @addr = Mail::Address->parse($bug{owner});
239 $owner_name = $addr[0]->phrase;
240 $owner_email = $addr[0]->address;
241 } else {
242 $owner_name = '';
243 $owner_email = '';
244 }
245
246 if ($bug{done}) {
247 @addr = Mail::Address->parse($bug{done});
248 $done_name = $addr[0]->phrase;
249 $done_email = $addr[0]->address;
250 } else {
251 $done_name = '';
252 $done_email = '';
253 }
254
255 #Calculate bug presence in distributions
256 my ($present_in_stable, $present_in_testing, $present_in_unstable, $present_in_experimental);
257 if($src_config{archived}) {
258 $present_in_stable = $present_in_testing = $present_in_unstable = $present_in_experimental = 'FALSE';
259 } else {
260 $present_in_stable =
261 bug_presence(bug => $bug_nr, status => \%bug,
262 dist => 'stable',
263 arch => \@archs);
264 $present_in_testing =
265 bug_presence(bug => $bug_nr, status => \%bug,
266 dist => 'testing',
267 arch => \@archs);
268 $present_in_unstable =
269 bug_presence(bug => $bug_nr, status => \%bug,
270 dist => 'unstable',
271 arch => \@archs);
272 $present_in_experimental =
273 bug_presence(bug => $bug_nr, status => \%bug,
274 dist => 'experimental',
275 arch => \@archs);
276
277 if(!defined($present_in_stable) or !defined($present_in_unstable) or !defined($present_in_testing) or !defined($present_in_experimental)) {
278 print "NUMBER: $bug_nr\n";
279 }
280
281 if(defined($present_in_stable) and ($present_in_stable eq 'absent' or $present_in_stable eq 'fixed')) {
282 $present_in_stable = 'FALSE';
283 } else {
284 $present_in_stable = 'TRUE';
285 }
286 if(defined($present_in_testing) and ($present_in_testing eq 'absent' or $present_in_testing eq 'fixed')) {
287 $present_in_testing = 'FALSE';
288 } else {
289 $present_in_testing = 'TRUE';
290 }
291 if(defined($present_in_unstable) and ($present_in_unstable eq 'absent' or $present_in_unstable eq 'fixed')) {
292 $present_in_unstable = 'FALSE';
293 } else {
294 $present_in_unstable = 'TRUE';
295 }
296 if(defined($present_in_experimental) and ($present_in_experimental eq 'absent' or $present_in_experimental eq 'fixed')) {
297 $present_in_experimental = 'FALSE';
298 } else {
299 $present_in_experimental = 'TRUE';
300 }
301 }
302
303 # Insert data into bugs table
304 $insert_bugs_handle->execute($bug_nr, $bug{package}, $srcpkg, $bug{date}, $bug{pending},
305 $bug{severity}, $bug{originator}, $submitter_name, $submitter_email, $bug{owner},
306 $owner_name, $owner_email, $bug{done}, $done_name, $done_email, $bug{subject},
307 $bug{forwarded}, $bug{log_modified},
308 $present_in_stable, $present_in_testing, $present_in_unstable, $present_in_experimental) or die $!;
309
310 my $src;
311 foreach my $pkg (keys %{{ map { $_ => 1 } split(/\s*[, ]\s*/, $bug{package})}}) {
312 if ($pkg =~ /^src:(.*)/)
313 {
314 $src = $1;
315 } else {
316 $src = exists($pkgsrc{$pkg}) ? $pkgsrc{$pkg} : $pkg;
317 }
318 $insert_bugs_packages_handle->execute($bug_nr, $pkg, $src) or die $!;
319 }
320
321 # insert data into bug_fixed_in and bug_found_in tables
322 foreach my $version (without_duplicates(@found_versions)) {
323 $insert_bugs_found_handle->execute($bug_nr, $version) or die $!;
324 }
325 foreach my $version (without_duplicates(@fixed_versions)) {
326 $insert_bugs_fixed_handle->execute($bug_nr, $version) or die $!;
327 }
328 foreach my $mergee (without_duplicates(split / /, $bug{mergedwith})) {
329 $insert_bugs_merged_handle->execute($bug_nr, $mergee) or die $!;
330 }
331 foreach my $blocked (without_duplicates(split / /, $bug{blocks})) {
332 $insert_bugs_blocks_handle->execute($bug_nr, $blocked) or die $!;
333 }
334 foreach my $blocker (without_duplicates(split / /, $bug{blockedby})) {
335 $insert_bugs_blockedby_handle->execute($bug_nr, $blocker) or die $!;
336 }
337 foreach my $tag (without_duplicates(@tags)) {
338 $insert_bugs_tags_handle->execute($bug_nr, $tag) or die $!;
339 }
340 }
341 print "Inserting bugs: ",(time() - $t),"s\n" if $timing;
342
343 foreach my $postfix (qw{_packages _merged_with _found_in _fixed_in _tags}, '') {
344 my $sth = $dbh->prepare("ANALYZE $table$postfix");
345 $sth->execute() or die $!;
346 }
347
348 my $sth = $dbh->prepare("ANALYZE ".$src_config{'usertags-table'});
349 $sth->execute() or die $!;
350
351 print "Analyzing bugs: ",(time() - $t),"s\n" if $timing;
352
353 $dbh->commit();
354 print "Committing bugs: ",(time() - $t),"s\n" if $timing;
355 }
356
357 sub main {
358 if(@ARGV != 3) {
359 print STDERR "Usage: $0 <config> <command> <source>\n";
360 exit 1;
361 }
362
363 our $t = time();
364 our $timing;
365
366 my $config = LoadFile($ARGV[0]) or die "Could not load configuration: $!";
367 my $command = $ARGV[1];
368 my $source = $ARGV[2];
369
370 my $dbname = $config->{general}->{dbname};
371 my $dbport;
372 if ($config->{general}->{dbport} ne '') {
373 $dbport = ";port=".$config->{general}->{dbport};
374 } else {
375 $dbport = "";
376 }
377 # Connection to DB
378 my $dbh = DBI->connect("dbi:Pg:dbname=$dbname".$dbport);
379 # We want to commit the transaction as a hole at the end
380 $dbh->{AutoCommit} = 0;
381 $dbh->do('SET CONSTRAINTS ALL DEFERRED');
382
383 if($command eq 'run') {
384 run($config, $source, $dbh);
385 } else {
386 print STDERR "<command> has to be one of run, drop and setup\n";
387 exit(1)
388 }
389
390 }
391
392 main();

  ViewVC Help
Powered by ViewVC 1.1.5