/[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 1243 - (show annotations) (download)
Mon Sep 8 09:18:54 2008 UTC (4 years, 8 months ago) by lucas
File MIME type: text/plain
File size: 9501 byte(s)
added foreign keys, adapted import scripts to allow to use them. DB udd on udd.debian.net was updated manually.
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};
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{binarytosource};
20 use Debbugs::Config qw{:globals};
21 use Debbugs::User;
22 #use Debbugs::User qw{read_usertags};
23
24 $YAML::Syck::ImplicitTyping = 1;
25
26 #Used for measuring time
27 our $t;
28 our $timing = 0;
29
30 # 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 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 sub run_usertags {
96 my ($config, $source, $dbh) = @_;
97 my %src_config = %{$config->{$source}};
98 my $table = $src_config{'usertags-table'} or die "usertags-table not specified for source $source";
99 our $timing;
100 our $t;
101
102
103 $t = time();
104 # Free usertags table
105 $dbh->do("DELETE FROM $table") or die
106 "Couldn't empty $table: $!";
107 print "Deleting usertags: ",(time() - $t),"s\n" if $timing;
108 $t = time();
109 # read and insert user tags
110 my @users = get_bugs_users();
111 foreach my $user (@users) {
112 #read_usertags(\%tags, $user);
113 my $u = Debbugs::User->new($user);
114 my %tags = %{$u->{tags}};
115 $user = $dbh->quote($user);
116 foreach my $tag (keys %tags) {
117 my $qtag = $dbh->quote($tag);
118 map { $dbh->do("INSERT INTO $table VALUES ($user, $qtag, $_)") or die $! } @{$tags{$tag}};
119 }
120 }
121 }
122
123 sub run {
124 my ($config, $source, $dbh) = @_;
125
126 our $t;
127 our $timing;
128 print "Inserting usertags: ",(time() - $t),"s\n" if $timing;
129 $t = time();
130
131 my %src_config = %{$config->{$source}};
132 my $table = $src_config{table};
133 my $archived_table = $src_config{'archived-table'};
134
135 my @modified_bugs;
136
137 if($src_config{archived}) {
138 @modified_bugs = get_bugs(archive => 1);
139 } else {
140 @modified_bugs = get_bugs();
141 }
142 my @modified_bugs2;
143 if ($src_config{debug}) {
144 foreach $b (@modified_bugs) {
145 push(@modified_bugs2, $b) if ($b =~ /0$/);
146 }
147 @modified_bugs = @modified_bugs2;
148 }
149
150 print "Fetching list of ",scalar(@modified_bugs), " bugs to insert: ",(time() - $t),"s\n" if $timing;
151 $t = time();
152
153 foreach my $prefix ($table, $archived_table) {
154 foreach my $postfix (qw{_merged_with _found_in _fixed_in _tags}, '') {
155 my $sth = $dbh->prepare("DELETE FROM $prefix$postfix WHERE id = \$1");
156 map {
157 $sth->execute($_) or die $!;
158 } @modified_bugs;
159 }
160 }
161 print "Deleting bugs: ",(time() - $t),"s\n" if $timing;
162 $t = time();
163
164 # Used to chache binary to source mappings
165 my %binarytosource = ();
166 # XXX What if a bug is in location 'db' (which currently
167 my $location = $src_config{archived} ? 'archive' : 'db_h';
168 #my $table = $src_config{archived} ? 'bugs_archived' : 'bugs';
169 $table = $src_config{archived} ? $archived_table : $table;
170 # Read all bugs
171 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)");
172 my $insert_bugs_found_handle = $dbh->prepare("INSERT INTO ${table}_found_in VALUES (\$1, \$2)");
173 my $insert_bugs_fixed_handle = $dbh->prepare("INSERT INTO ${table}_fixed_in VALUES (\$1, \$2)");
174 my $insert_bugs_merged_handle = $dbh->prepare("INSERT INTO ${table}_merged_with VALUES (\$1, \$2)");
175 my $insert_bugs_tags_handle = $dbh->prepare("INSERT INTO ${table}_tags VALUES (\$1, \$2)");
176 $insert_bugs_handle->bind_param(4, undef, SQL_INTEGER);
177 $insert_bugs_handle->bind_param(10, undef, SQL_INTEGER);
178
179 print "Inserting bugs: ",(time() - $t),"s\n" if $timing;
180 $t = time();
181 foreach my $bug_nr (@modified_bugs) {
182 # Fetch bug using Debbugs
183 # Bugs which were once archived and have been unarchived again will appear in get_bugs(archive => 1).
184 # However, those bugs are not to be found in location 'archive', so we detect them, and skip them
185 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);
186 # Yeah, great, why does get_bug_status not accept a location?
187 my %bug = %{get_bug_status(bug => $bug_nr, status => $bug_ref)};
188
189 # Convert data where necessary
190 my @found_versions = @{$bug{found_versions}};
191 my @fixed_versions = @{$bug{fixed_versions}};
192 my @tags = split / /, $bug{keywords};
193
194 # log_modified and date are not necessarily set. If they are not available, they
195 # are assumed to be epoch (i.e. bug #4170)
196 map {
197 if($bug{$_}) {
198 #$bug{$_} = "$bug{$_}::abstime";
199 $bug{$_} = int($bug{$_});
200 } else {
201 $bug{$_} = 0;
202 }
203 } qw{date log_modified};
204
205
206 if(not exists $binarytosource{$bug{package}}) {
207 $binarytosource{$bug{package}} = (binarytosource($bug{package}))[0];
208 }
209 my $source = $binarytosource{$bug{package}};
210
211 if(not defined $source) {
212 # if source is not defined, then we $bug{package} is likely to
213 # be a source package name (or the source package has the same
214 # name as the binary package). See #480818 for ex.
215 $source = $bug{package};
216 }
217
218 #Calculate bug presence in distributions
219 my ($present_in_stable, $present_in_testing, $present_in_unstable);
220 if($src_config{archived}) {
221 $present_in_stable = $present_in_testing = $present_in_unstable = 'FALSE';
222 } else {
223 $present_in_stable =
224 bug_presence(bug => $bug_nr, status => \%bug,
225 dist => 'stable');
226 $present_in_testing =
227 bug_presence(bug => $bug_nr, status => \%bug,
228 dist => 'testing');
229 $present_in_unstable =
230 bug_presence(bug => $bug_nr, status => \%bug,
231 dist => 'unstable');
232 if(!defined($present_in_stable) or !defined($present_in_unstable) or !defined($present_in_testing)) {
233 print "NUMBER: $bug_nr\n";
234 }
235
236 if(defined($present_in_stable) and ($present_in_stable eq 'absent' or $present_in_stable eq 'fixed')) {
237 $present_in_stable = 'FALSE';
238 } else {
239 $present_in_stable = 'TRUE';
240 }
241 if(defined($present_in_testing) and ($present_in_testing eq 'absent' or $present_in_testing eq 'fixed')) {
242 $present_in_testing = 'FALSE';
243 } else {
244 $present_in_testing = 'TRUE';
245 }
246 if(defined($present_in_unstable) and ($present_in_unstable eq 'absent' or $present_in_unstable eq 'fixed')) {
247 $present_in_unstable = 'FALSE';
248 } else {
249 $present_in_unstable = 'TRUE';
250 }
251 }
252
253 # Insert data into bugs table
254 $insert_bugs_handle->execute($bug_nr, $bug{package}, $source, $bug{date}, $bug{pending},
255 $bug{severity}, $bug{originator}, $bug{owner}, $bug{subject}, $bug{log_modified},
256 $present_in_stable, $present_in_testing, $present_in_unstable) or die $!;
257
258 # insert data into bug_fixed_in and bug_found_in tables
259 foreach my $version (without_duplicates(@found_versions)) {
260 $insert_bugs_found_handle->execute($bug_nr, $version) or die $!;
261 }
262 foreach my $version (without_duplicates(@fixed_versions)) {
263 $insert_bugs_fixed_handle->execute($bug_nr, $version) or die $!;
264 }
265 foreach my $mergee (without_duplicates(split / /, $bug{mergedwith})) {
266 $insert_bugs_merged_handle->execute($bug_nr, $mergee) or die $!;
267 }
268 foreach my $tag (without_duplicates(@tags)) {
269 $insert_bugs_tags_handle->execute($bug_nr, $tag) or die $!;
270 }
271 }
272
273 # Also import usertags
274 run_usertags($config, $source, $dbh);
275 }
276
277 sub main {
278 if(@ARGV != 3) {
279 print STDERR "Usage: $0 <config> <command> <source>\n";
280 exit 1;
281 }
282
283 our $t = time();
284 our $timing;
285
286 my $config = LoadFile($ARGV[0]) or die "Could not load configuration: $!";
287 my $command = $ARGV[1];
288 my $source = $ARGV[2];
289
290 my $dbname = $config->{general}->{dbname};
291 # Connection to DB
292 my $dbh = DBI->connect("dbi:Pg:dbname=$dbname");
293 # We want to commit the transaction as a hole at the end
294 $dbh->{AutoCommit} = 0;
295 $dbh->do('SET CONSTRAINTS ALL DEFERRED');
296
297 if($command eq 'run') {
298 run($config, $source, $dbh);
299 } else {
300 print STDERR "<command> has to be one of run, drop and setup\n";
301 exit(1)
302 }
303
304 $dbh->commit();
305 print "Committing bugs: ",(time() - $t),"s\n" if $timing;
306 }
307
308 main();

  ViewVC Help
Powered by ViewVC 1.1.5