/[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 1118 - (hide annotations) (download)
Mon Aug 18 14:29:39 2008 UTC (4 years, 9 months ago) by neronus-guest
Original Path: udd/src/udd/bugs_gatherer.pl
File MIME type: text/plain
File size: 11245 byte(s)
We don't need no timing - so we switch it off
1 neronus-guest 1070 #!/usr/bin/perl -w
2 neronus-guest 1118 # Last-Modified: <Mon Aug 18 14:29:47 2008>
3 neronus-guest 919
4     use strict;
5     use warnings;
6    
7 neronus-guest 946 use FindBin '$Bin';
8 neronus-guest 919
9 neronus-guest 946 # We need our own copy of Debbugs::Status for now
10     use lib $Bin, qw{/org/udd.debian.net/mirrors/bugs.debian.org/perl};
11    
12 neronus-guest 919 use DBI;
13 neronus-guest 1068 use DBI qw{:sql_types};
14 neronus-guest 919 use YAML::Syck;
15 neronus-guest 973 use Time::Local;
16 neronus-guest 919
17     use Debbugs::Bugs qw{get_bugs};
18 neronus-guest 942 use Debbugs::Status qw{read_bug get_bug_status bug_presence};
19 neronus-guest 971 use Debbugs::Packages qw{binarytosource};
20 neronus-guest 968 use Debbugs::Config qw{:globals};
21 neronus-guest 1053 use Debbugs::User;
22     #use Debbugs::User qw{read_usertags};
23 neronus-guest 919
24     $YAML::Syck::ImplicitTyping = 1;
25    
26 neronus-guest 1068 #Used for measuring time
27 neronus-guest 1071 our $t;
28 neronus-guest 1118 our $timing = 0;
29 neronus-guest 1068
30 neronus-guest 968 # Return the list of usernames
31     sub get_bugs_users {
32     my $topdir = "$gSpoolDir/user";
33     my @ret = ();
34     # see Debbugs::User::filefromemail for why 0...6
35     for(my $i = 0; $i < 7; $i++) {
36     my $dir = "$topdir/$i";
37     opendir DIR, $dir or die "Can't open dir $dir: $!";
38     # Replace all occurences of %dd with the corresponding
39     # character represented by dd, where dd is a hexadecimal
40     # number
41     push @ret, map { s/%(..)/chr(hex($1))/ge; $_ } readdir DIR;
42     }
43     return @ret;
44     }
45    
46 neronus-guest 973 sub parse_time {
47     if(shift =~ /(\d\d\d\d)-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d)/) {
48     return ($1, $2, $3, $4, $5, $6);
49     }
50     return undef;
51     }
52    
53    
54     sub get_db_max_last_modified {
55     my $dbh = shift or die "Argument required";
56     my $sth = $dbh->prepare("SELECT MAX (last_modified) FROM bugs");
57     $sth->execute() or die $!;
58     my $date = $sth->fetchrow_array();
59     if(defined $date) {
60     my ($year, $month, $day, $hour, $minute, $second) = parse_time($date);
61     return timelocal($second, $minute, $hour, $day, $month-1, $year);
62     } else {
63     return 0;
64     }
65     }
66    
67     sub get_mtime {
68     return ((stat(shift))[9]);
69     }
70    
71     sub get_modified_bugs {
72     my $prune_stamp = shift;
73     die "Argument required" unless defined $prune_stamp;
74     my $top_dir = $gSpoolDir;
75     my @result = ();
76     foreach my $sub (qw(archive db-h)) {
77     my $spool = "$top_dir/$sub";
78     foreach my $subsub (glob "$spool/*") {
79     if( -d $subsub and get_mtime($subsub) > $prune_stamp ) {
80     push @result,
81     map { s{.*/(.*)\.log}{$1}; $_ }
82     grep { get_mtime("$_") > $prune_stamp }
83     glob "$subsub/*.log";
84     }
85     }
86     }
87     return \@result;
88     }
89    
90     sub without_duplicates {
91     my %h = ();
92     return (grep { ($h{$_}++ == 0) || 0 } @_);
93     }
94    
95 neronus-guest 1068 sub setup {
96     my ($config, $source, $dbh) = @_;
97     my $schema = $config->{general}->{'schema-dir'} . '/' . $config->{$source}->{schema};
98     open SQL, "<", $schema or die $!;
99     my $command = join "", <SQL>;
100     close SQL;
101     $command =~ s/%\(([^)]+)\)s/$config->{$source}->{$1}/g;
102     $dbh->prepare($command)->execute() or die $!;
103     }
104    
105 neronus-guest 1106 sub tables {
106     my ($config, $source, $dbh) = @_;
107     my @ret = ();
108     foreach my $prefix ($config->{$source}->{table}, $config->{$source}->{'archived-table'}) {
109     foreach my $postfix (qw{_merged_with _found_in _fixed_in _tags}, '') {
110     push @ret, "$prefix$postfix";
111     }
112     }
113     unshift @ret, $config->{$source}->{'usertags-table'};
114     return @ret;
115     }
116    
117    
118 neronus-guest 1068 sub drop {
119     my ($config, $source, $dbh) = @_;
120     map {
121     $dbh->prepare("DROP VIEW $_")->execute() or die $!;
122 neronus-guest 919 }
123 neronus-guest 1068 qw{bugs_rt_affects_stable bugs_rt_affects_testing_and_unstable bugs_rt_affects_unstable bugs_rt_affects_testing};
124 neronus-guest 919
125 neronus-guest 1106 foreach my $table (tables($config, $source, $dbh)) {
126     $dbh->prepare("DROP TABLE $table")->execute() or die $!;
127 neronus-guest 1068 }
128     }
129    
130     sub run_usertags {
131     my ($config, $source, $dbh) = @_;
132 neronus-guest 945 my %src_config = %{$config->{$source}};
133 neronus-guest 1068 my $table = $src_config{'usertags-table'} or die "usertags-table not specified for source $source";
134     our $timing;
135     our $t;
136 neronus-guest 919
137    
138 lucas 1055 $t = time();
139 neronus-guest 968 # Free usertags table
140 neronus-guest 1068 $dbh->do("DELETE FROM $table") or die
141     "Couldn't empty $table: $!";
142 lucas 1055 print "Deleting usertags: ",(time() - $t),"s\n" if $timing;
143     $t = time();
144 neronus-guest 971 # read and insert user tags
145 neronus-guest 968 my @users = get_bugs_users();
146     foreach my $user (@users) {
147 neronus-guest 1053 #read_usertags(\%tags, $user);
148     my $u = Debbugs::User->new($user);
149     my %tags = %{$u->{tags}};
150 neronus-guest 968 $user = $dbh->quote($user);
151     foreach my $tag (keys %tags) {
152     my $qtag = $dbh->quote($tag);
153 neronus-guest 1068 map { $dbh->do("INSERT INTO $table VALUES ($user, $qtag, $_)") or die $! } @{$tags{$tag}};
154 neronus-guest 968 }
155     }
156 neronus-guest 1068 }
157    
158     sub run {
159     my ($config, $source, $dbh) = @_;
160    
161     our $t;
162     our $timing;
163 lucas 1055 print "Inserting usertags: ",(time() - $t),"s\n" if $timing;
164     $t = time();
165 neronus-guest 1068 run_usertags($config, $source, $dbh);
166    
167     my %src_config = %{$config->{$source}};
168     my $table = $src_config{table};
169     my $archived_table = $src_config{'archived-table'};
170    
171 neronus-guest 973 my @modified_bugs;
172 neronus-guest 1068 ####### XXX EXPERIMENT
173     ####### XXX What to do with bugs both archived and unarchived
174     #my $max_last_modified = get_db_max_last_modified($dbh);
175     #my @modified_bugs;
176     #if($max_last_modified) {
177     # @modified_bugs = @{get_modified_bugs($max_last_modified)};
178     # Delete modified bugs
179     # for my $bug (@modified_bugs) {
180     # map {
181     # $dbh->prepare("DELETE FROM $_ WHERE id = $bug")->execute()
182     # } qw{bugs bug_merged_with bug_found_in bug_fixed_in};
183     # }
184     #} else {
185     # @modified_bugs = get_bugs(archive => 'both');
186     #}
187     #@modified_bugs = without_duplicates(@modified_bugs);
188 neronus-guest 973 if($src_config{archived}) {
189     @modified_bugs = get_bugs(archive => 1);
190     } else {
191     @modified_bugs = get_bugs();
192     }
193 neronus-guest 971
194 lucas 1059 my @modified_bugs2;
195     if ($src_config{debug}) {
196     foreach $b (@modified_bugs) {
197     push(@modified_bugs2, $b) if ($b =~ /0$/);
198     }
199     @modified_bugs = @modified_bugs2;
200     }
201    
202 lucas 1055 print "Fetching list of ",scalar(@modified_bugs), " bugs to insert: ",(time() - $t),"s\n" if $timing;
203     $t = time();
204 neronus-guest 973
205 neronus-guest 1068 foreach my $prefix ($table, $archived_table) {
206     foreach my $postfix ('', qw{_merged_with _found_in _fixed_in _tags}) {
207     my $sth = $dbh->prepare("DELETE FROM $prefix$postfix WHERE id = \$1");
208     map {
209     $sth->execute($_) or die $!;
210     } @modified_bugs;
211     }
212 neronus-guest 973 }
213 lucas 1055 print "Deleting bugs: ",(time() - $t),"s\n" if $timing;
214     $t = time();
215 neronus-guest 919
216 neronus-guest 971 # Used to chache binary to source mappings
217 neronus-guest 939 my %binarytosource = ();
218 neronus-guest 971 # XXX What if a bug is in location 'db' (which currently doesn't exist)
219 neronus-guest 945 my $location = $src_config{archived} ? 'archive' : 'db_h';
220 neronus-guest 1068 #my $table = $src_config{archived} ? 'bugs_archived' : 'bugs';
221     $table = $src_config{archived} ? $archived_table : $table;
222 neronus-guest 919 # Read all bugs
223 neronus-guest 1068 my $insert_bugs_handle = $dbh->prepare("INSERT INTO $table VALUES (\$1, \$2, \$3, \$4::abstime, \$5, \$6, \$7, \$8, \$9, \$10::abstime, \$11, \$12, \$13)");
224     my $insert_bugs_found_handle = $dbh->prepare("INSERT INTO ${table}_found_in VALUES (\$1, \$2)");
225     my $insert_bugs_fixed_handle = $dbh->prepare("INSERT INTO ${table}_fixed_in VALUES (\$1, \$2)");
226     my $insert_bugs_merged_handle = $dbh->prepare("INSERT INTO ${table}_merged_with VALUES (\$1, \$2)");
227     my $insert_bugs_tags_handle = $dbh->prepare("INSERT INTO ${table}_tags VALUES (\$1, \$2)");
228     $insert_bugs_handle->bind_param(4, undef, SQL_INTEGER);
229     $insert_bugs_handle->bind_param(10, undef, SQL_INTEGER);
230    
231     print "Inserting bugs: ",(time() - $t),"s\n" if $timing;
232     $t = time();
233 neronus-guest 973 foreach my $bug_nr (@modified_bugs) {
234 neronus-guest 930 # Fetch bug using Debbugs
235 neronus-guest 946 # Bugs which were once archived and have been unarchived again will appear in get_bugs(archive => 1).
236     # However, those bugs are not to be found in location 'archive', so we detect them, and skip them
237 neronus-guest 973 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);
238 neronus-guest 942 # Yeah, great, why does get_bug_status not accept a location?
239 neronus-guest 945 my %bug = %{get_bug_status(bug => $bug_nr, status => $bug_ref)};
240 neronus-guest 936
241 neronus-guest 930 # Convert data where necessary
242 neronus-guest 1077 my @found_versions = @{$bug{found_versions}};
243     my @fixed_versions = @{$bug{fixed_versions}};
244     my @tags = split / /, $bug{keywords};
245 neronus-guest 939
246 neronus-guest 945 # log_modified and date are not necessarily set. If they are not available, they
247     # are assumed to be epoch (i.e. bug #4170)
248     map {
249     if($bug{$_}) {
250 neronus-guest 1068 #$bug{$_} = "$bug{$_}::abstime";
251     $bug{$_} = int($bug{$_});
252 neronus-guest 945 } else {
253 neronus-guest 1068 $bug{$_} = 0;
254 neronus-guest 945 }
255     } qw{date log_modified};
256 neronus-guest 939
257 neronus-guest 945
258 neronus-guest 939 if(not exists $binarytosource{$bug{package}}) {
259 neronus-guest 982 $binarytosource{$bug{package}} = (binarytosource($bug{package}))[0];
260 neronus-guest 939 }
261     my $source = $binarytosource{$bug{package}};
262    
263 neronus-guest 929 if(not defined $source) {
264 lucas 1029 # if source is not defined, then we $bug{package} is likely to
265     # be a source package name (or the source package has the same
266     # name as the binary package). See #480818 for ex.
267 neronus-guest 1077 $source = $bug{package};
268 neronus-guest 1078 }
269 neronus-guest 929
270 neronus-guest 922 #Calculate bug presence in distributions
271 neronus-guest 1068 my ($present_in_stable, $present_in_testing, $present_in_unstable);
272     if($src_config{archived}) {
273     $present_in_stable = $present_in_testing = $present_in_unstable = 'FALSE';
274 neronus-guest 922 } else {
275 neronus-guest 1068 $present_in_stable =
276     bug_presence(bug => $bug_nr, status => \%bug,
277     dist => 'stable');
278     $present_in_testing =
279     bug_presence(bug => $bug_nr, status => \%bug,
280     dist => 'testing');
281     $present_in_unstable =
282     bug_presence(bug => $bug_nr, status => \%bug,
283     dist => 'unstable');
284     if(!defined($present_in_stable) or !defined($present_in_unstable) or !defined($present_in_testing)) {
285     print "NUMBER: $bug_nr\n";
286     }
287    
288     if(defined($present_in_stable) and ($present_in_stable eq 'absent' or $present_in_stable eq 'fixed')) {
289     $present_in_stable = 'FALSE';
290     } else {
291     $present_in_stable = 'TRUE';
292     }
293     if(defined($present_in_testing) and ($present_in_testing eq 'absent' or $present_in_testing eq 'fixed')) {
294     $present_in_testing = 'FALSE';
295     } else {
296     $present_in_testing = 'TRUE';
297     }
298     if(defined($present_in_unstable) and ($present_in_unstable eq 'absent' or $present_in_unstable eq 'fixed')) {
299     $present_in_unstable = 'FALSE';
300     } else {
301     $present_in_unstable = 'TRUE';
302     }
303 neronus-guest 922 }
304    
305 neronus-guest 920 # Insert data into bugs table
306 neronus-guest 1068 $insert_bugs_handle->execute($bug_nr, $bug{package}, $source, $bug{date}, $bug{pending},
307     $bug{severity}, $bug{originator}, $bug{owner}, $bug{subject}, $bug{log_modified},
308     $present_in_stable, $present_in_testing, $present_in_unstable) or die $!;
309 neronus-guest 920
310     # insert data into bug_fixed_in and bug_found_in tables
311 neronus-guest 973 foreach my $version (without_duplicates(@found_versions)) {
312 neronus-guest 1068 $insert_bugs_found_handle->execute($bug_nr, $version) or die $!;
313 neronus-guest 920 }
314 neronus-guest 973 foreach my $version (without_duplicates(@fixed_versions)) {
315 neronus-guest 1068 $insert_bugs_fixed_handle->execute($bug_nr, $version) or die $!;
316 neronus-guest 920 }
317 neronus-guest 973 foreach my $mergee (without_duplicates(split / /, $bug{mergedwith})) {
318 neronus-guest 1068 $insert_bugs_merged_handle->execute($bug_nr, $mergee) or die $!;
319 neronus-guest 921 }
320 neronus-guest 983 foreach my $tag (without_duplicates(@tags)) {
321 neronus-guest 1068 $insert_bugs_tags_handle->execute($bug_nr, $tag) or die $!;
322 neronus-guest 983 }
323 neronus-guest 919 }
324 neronus-guest 1068 }
325 neronus-guest 919
326 neronus-guest 1068 sub main {
327     if(@ARGV != 3) {
328     print STDERR "Usage: $0 <config> <command> <source>\n";
329     exit 1;
330     }
331    
332 neronus-guest 1077 our $t = time();
333 neronus-guest 1070 our $timing;
334    
335 neronus-guest 1068 my $config = LoadFile($ARGV[0]) or die "Could not load configuration: $!";
336     my $command = $ARGV[1];
337     my $source = $ARGV[2];
338    
339     my $dbname = $config->{general}->{dbname};
340     # Connection to DB
341     my $dbh = DBI->connect("dbi:Pg:dbname=$dbname");
342     # We want to commit the transaction as a hole at the end
343     $dbh->{AutoCommit} = 0;
344    
345     if($command eq 'run') {
346     run($config, $source, $dbh);
347     } elsif ($command eq 'setup') {
348     setup($config, $source, $dbh);
349     } elsif ($command eq 'drop') {
350     drop($config, $source, $dbh);
351 neronus-guest 1106 } elsif ($command eq 'tables') {
352     print join "\n", tables($config, $source, $dbh)
353 neronus-guest 1068 } else {
354     print STDERR "<command> has to be one of run, drop and setup\n";
355     exit(1)
356     }
357    
358 neronus-guest 919 $dbh->commit();
359 lucas 1055 print "Committing bugs: ",(time() - $t),"s\n" if $timing;
360 neronus-guest 919 }
361    
362     main();

  ViewVC Help
Powered by ViewVC 1.1.5