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.
6 my $config_path = '/etc/debbugs';
7 my $lib_path = '/usr/lib/debbugs';
9 require "$config_path/config";
10 require "$lib_path/errorlib";
27 open LOG, "< $log" or die "Can't open $log: $!";
28 my @records = read_log_records(*LOG);
31 my (@found_versions, @fixed_versions);
32 my (%found_versions, %fixed_versions);
34 for my $record (@records) {
35 if ($record->{type} eq 'html') {
36 # Reassigns zap the found and fixed version list. Reopens will
37 # zap the fixed list too in the full deployment, but doing that
38 # here causes problems in case of accidental reopens and
40 if ($record->{text} =~ /assigned/) {
49 next unless $record->{type} eq 'autocheck' or
50 $record->{type} eq 'incoming-recv';
51 my $decoded = Debbugs::MIME::parse($record->{text});
52 next unless defined $decoded;
54 # Was it sent to -done or -close?
56 my $firstreceived = $decoded->{header}[0];
57 if ($firstreceived =~ /\(at [^)]*-(?:done|close)\)/) {
61 # Get Version: pseudo-headers.
63 my ($source, $sourcever, $ver);
64 for ($i = 0; $i < @{$decoded->{body}}; ++$i) {
65 last if $decoded->{body}[$i] !~ /^(\S+):\s*(.*)/;
66 my ($fn, $fv) = (lc $1, $2);
67 if ($fn eq 'source') {
69 } elsif ($fn eq 'source-version' and
70 $fv =~ /^(\d[^,\s]*(?:[,\s]+|$))+/) {
72 } elsif ($fn eq 'version' and $fv =~ /^(\d[^,\s]*(?:[,\s]+|$))+/) {
73 # Deal with reportbug brain-damage.
74 next if $fv =~ /^unavailable/i;
77 # Strip off other random junk at the end of a version.
78 $fv =~ s/ *[A-Za-z].*//;
85 push @parsedvers, split /[,\s]+/, $ver;
86 } elsif (defined $source and defined $sourcever) {
87 push @parsedvers, map "$source/$_", split /[,\s]+/, $sourcever;
91 for my $v (@parsedvers) {
92 push @fixed_versions, $v
93 unless exists $fixed_versions{$v};
94 $fixed_versions{$v} = 1;
95 @found_versions = grep { $_ ne $v } @found_versions;
96 delete $found_versions{$v};
99 for my $v (@parsedvers) {
100 push @found_versions, $v
101 unless exists $found_versions{$v};
102 $found_versions{$v} = 1;
103 @fixed_versions = grep { $_ ne $v } @fixed_versions;
104 delete $fixed_versions{$v};
109 # Look for Debian changelogs.
110 for (; $i < @{$decoded->{body}}; ++$i) {
111 if ($decoded->{body}[$i] =~
112 /(\w[-+0-9a-z.]+) \(([^\(\) \t]+)\) \S+; urgency=\S+/i) {
113 my ($p, $v) = ($1, $2);
114 push @fixed_versions, "$p/$v"
115 unless exists $fixed_versions{"$p/$v"};
116 $fixed_versions{"$p/$v"} = 1;
117 @found_versions = grep { $_ ne "$p/$v" } @found_versions;
118 delete $found_versions{"$p/$v"};
125 return (\@found_versions, \@fixed_versions);
130 my ($target, $source) = @_;
131 my %seen = map { $_ => 1 } @$target;
132 for my $v (@$source) {
133 next if exists $seen{$v};
139 chdir $gSpoolDir or die "Can't chdir $gSpoolDir: $!";
142 opendir DB, $db or die "Can't opendir $db: $!";
144 while (defined(my $dir = readdir DB)) {
145 next if $dir =~ /^\.\.?$/ or not -d "$db/$dir";
146 opendir HASH, "$db/$dir" or die "Can't opendir $db/$dir: $!";
148 while (defined(my $file = readdir HASH)) {
149 next unless $file =~ /\.log$/;
150 next if -z "$db/$dir/$file";
151 (my $bug = $file) =~ s/\..*//;
156 print "Processing $bug ...\n" if $ENV{DEBBUGS_VERBOSE};
158 my ($locks, $status) = lockreadbugmerge($bug, $db);
159 unless (defined $status) {
160 unlockreadbugmerge($locks);
164 my ($found_versions, $fixed_versions) = getbuginfo("$db/$dir/$file");
166 if (length $status->{mergedwith}) {
167 @merges = sort { $a <=> $b } split ' ', $status->{mergedwith};
168 if ($merges[0] < $bug) {
170 unlockreadbugmerge($locks);
173 for my $merge (@merges) {
176 my ($mfound, $mfixed) =
177 getbuginfo("$db/$mergehash/$merge.log");
178 mergeinto($found_versions, $mfound);
179 mergeinto($fixed_versions, $mfixed);
183 @$fixed_versions = () unless length $status->{done};
185 for my $out ($bug, (split ' ', $status->{mergedwith})) {
187 filelock("lock/$out");
189 my $outstatus = readbug($out, $db);
190 $outstatus->{found_versions} = [@$found_versions];
191 $outstatus->{fixed_versions} = [@$fixed_versions];
192 writebug($out, $mergestatus);
198 unlockreadbugmerge($locks);