2 # Extract version information from an existing non-versioned database by
3 # guesswork, based on Version: pseudo-headers and closing mails that look
4 # like Debian changelogs. The latter in particular is somewhat heuristic.
12 Usage: $0 db-directory versions-directory
22 open LOG, "< $log" or die "Can't open $log: $!";
23 my @records = read_log_records(*LOG);
26 my (@found_versions, @fixed_versions);
27 my (%found_versions, %fixed_versions);
29 for my $record (@records) {
30 if ($record->{type} eq 'html') {
31 # Reassigns zap the found and fixed version list. Reopens will
32 # zap the fixed list too in the full deployment, but doing that
33 # here causes problems in case of accidental reopens and
35 if ($record->{text} =~ /assigned/) {
44 next unless $record->{type} eq 'autocheck' or
45 $record->{type} eq 'incoming-recv';
46 my $decoded = Debbugs::MIME::parse($record->{text});
47 next unless defined $decoded;
49 # Was it sent to -done or -close?
51 my $firstreceived = $decoded->{header}[0];
52 if ($firstreceived =~ /\(at [^)]*-(?:done|close)\)/) {
56 # Get Version: pseudo-headers.
58 my ($source, $sourcever, $ver);
59 for ($i = 0; $i < @{$decoded->{body}}; ++$i) {
60 last if $decoded->{body}[$i] !~ /^(\S+):\s*(.*)/;
61 my ($fn, $fv) = (lc $1, $2);
62 if ($fn eq 'source') {
64 } elsif ($fn eq 'source-version' and
65 $fv =~ /^(\d[^,\s]*(?:[,\s]+|$))+/) {
67 } elsif ($fn eq 'version' and $fv =~ /^(\d[^,\s]*(?:[,\s]+|$))+/) {
68 # Deal with reportbug brain-damage.
69 next if $fv =~ /^unavailable/i;
78 push @parsedvers, split /[,\s]+/, $ver;
79 } elsif (defined $source and defined $sourcever) {
80 push @parsedvers, map "$source/$_", split /[,\s]+/, $sourcever;
84 for my $v (@parsedvers) {
85 push @fixed_versions, $v
86 unless exists $fixed_versions{$v};
87 $fixed_versions{$v} = 1;
88 @found_versions = grep { $_ ne $v } @found_versions;
89 delete $found_versions{$v};
92 for my $v (@parsedvers) {
93 push @found_versions, $v
94 unless exists $found_versions{$v};
95 $found_versions{$v} = 1;
96 @fixed_versions = grep { $_ ne $v } @fixed_versions;
97 delete $fixed_versions{$v};
102 # Look for Debian changelogs.
103 for (; $i < @{$decoded->{body}}; ++$i) {
104 if ($decoded->{body}[$i] =~
105 /(\w[-+0-9a-z.]+) \(([^\(\) \t]+)\) \S+; urgency=\S+/i) {
106 my ($p, $v) = ($1, $2);
107 push @fixed_versions, "$p/$v"
108 unless exists $fixed_versions{"$p/$v"};
109 $fixed_versions{"$p/$v"} = 1;
110 @found_versions = grep { $_ ne "$p/$v" } @found_versions;
111 delete $found_versions{"$p/$v"};
118 return (\@found_versions, \@fixed_versions);
123 my ($target, $source) = @_;
124 my %seen = map { $_ => 1 } @$target;
125 for my $v (@$source) {
126 next if exists $seen{$v};
132 my ($db, $verdb) = @ARGV[0, 1];
133 opendir DB, $db or die "Can't opendir $db: $!";
135 mkdir $verdb or die "Can't mkdir $verdb: $!";
138 while (defined(my $dir = readdir DB)) {
139 next if $dir =~ /^\.\.?$/ or not -d "$db/$dir";
140 opendir HASH, "$db/$dir" or die "Can't opendir $db/$dir: $!";
142 while (defined(my $file = readdir HASH)) {
143 next unless $file =~ /\.log$/;
144 next if -z "$db/$dir/$file";
145 (my $bug = $file) =~ s/\..*//;
149 # For incremental updates.
150 #next if -e "$verdb/$bughash/$bug.versions" and
151 # (stat "$verdb/$bughash/$bug.versions")[9] >=
152 # (stat "$db/$dir/$file")[9];
154 print "Processing $bug ...\n" if $ENV{DEBBUGS_VERBOSE};
156 open STATUS, "$db/$dir/$bug.status" or next;
157 <STATUS> for 1 .. 6; # done is field 7
158 chomp (my $done = <STATUS>);
159 <STATUS>; # mergedwith is field 9
160 chomp (my $mergedwith = <STATUS>);
163 my ($found_versions, $fixed_versions) = getbuginfo("$db/$dir/$file");
165 if (length $mergedwith) {
166 for my $merge (split ' ', $mergedwith) {
169 my ($mfound, $mfixed) =
170 getbuginfo("$db/$mergehash/$merge.log");
171 mergeinto($found_versions, $mfound);
172 mergeinto($fixed_versions, $mfixed);
176 @$fixed_versions = () unless length $done;
178 for my $out ($bug, (split ' ', $mergedwith)) {
182 unless (-d "$verdb/$outhash") {
183 mkdir "$verdb/$outhash" or die "Can't mkdir $verdb/$outhash: $!";
186 open VERSIONS, "> $verdb/$outhash/$out.versions"
187 or die "Can't open $verdb/$outhash/$out.versions: $!";
188 print VERSIONS "Found-in: @$found_versions\n";
189 print VERSIONS "Fixed-in: @$fixed_versions\n";