]> git.donarmstrong.com Git - debbugs.git/blobdiff - scripts/errorlib.in
[project @ 2003-06-06 17:56:05 by cjwatson]
[debbugs.git] / scripts / errorlib.in
index fc775643d0f38e8ae58a881a2405dce0878dfed2..062e864046312905f9c0ba1217680fba612b82e2 100755 (executable)
@@ -1,9 +1,14 @@
 # -*- perl -*-
-# $Id: errorlib.in,v 1.3 1999/12/01 18:04:01 gecko Exp $
+# $Id: errorlib.in,v 1.29 2003/06/06 17:56:05 cjwatson Exp $
 
 sub F_SETLK { 6; } sub F_WRLCK{ 1; }
 $flockstruct= 'sslll'; # And there ought to be something for this too.
 
+sub get_hashname {
+    return "" if ( $_[ 0 ] < 0 );
+    return sprintf "%02d", $_[ 0 ] % 100;
+}
+
 sub unlockreadbugmerge {
     local ($rv) = @_;
     &unfilelock if $rv >= 2;
@@ -11,32 +16,126 @@ sub unlockreadbugmerge {
 }
 
 sub lockreadbugmerge {
-    local ($lref) = @_;
-    if (!&lockreadbug($lref)) { return 0; }
-    if (!length($s_mergedwith)) { return 1; }
+    local ($lref, $location) = @_;
+    local $data;
+    if (!($data = &lockreadbug($lref, $location))) { return ( 0, undef ); }
+    if (!length($data{mergedwith})) { return ( 1, $data ); }
     &unfilelock;
     &filelock('lock/merge');
-    if (!&lockreadbug($lref)) { &unfilelock; return 0; }
-    return 2;
+    if (!&lockreadbug($lref, $location)) { &unfilelock; return ( 0, undef ); }
+    return ( 2, $data );
+}
+
+sub getbuglocation {
+    my ( $bugnum, $ext ) = @_;
+    my $archdir = sprintf "%02d", $bugnum % 100;
+    return 'archive' if ( -r "$gSpoolDir/archive/$archdir/$bugnum.$ext" );
+    return 'db-h' if ( -r "$gSpoolDir/db-h/$archdir/$bugnum.$ext" );
+    return 'db' if ( -r "$gSpoolDir/db/$bugnum.$ext" );
+    return undef;
+}
+
+sub getlocationpath {
+    my ($location) = @_;
+    if ($location eq 'archive') {
+        return "$gSpoolDir/archive";
+    } elsif ($location eq 'db') {
+        return "$gSpoolDir/db";
+    } else {
+        return "$gSpoolDir/db-h";
+    }
+}
+
+sub getbugcomponent {
+    my ($bugnum, $ext, $location) = @_;
+
+    $location = getbuglocation($bugnum, $ext) unless defined $location;
+    my $dir = getlocationpath($location);
+    return undef unless $dir;
+    if ($location eq 'db') {
+       return "$dir/$bugnum.$ext";
+    } else {
+       my $hash = get_hashname($bugnum);
+       return "$dir/$hash/$bugnum.$ext";
+    }
+}
+
+sub readbug {
+    local ($lref, $location) = @_;
+    my $status = getbugcomponent($lref, 'status', $location);
+    return undef unless defined $status;
+    if (!open(S,$status)) { return undef; }
+    my %data;
+    chop($data{originator}= <S>);
+    chop($data{date}= <S>);
+    chop($data{subject}= <S>);
+    chop($data{msgid}= <S>);
+    chop($data{package}= <S>);
+    chop($data{keywords}= <S>);
+    chop($data{done}= <S>);
+    chop($data{forwarded}= <S>);
+    chop($data{mergedwith}= <S>);
+    chop($data{severity}= <S>);
+    chop($data{versions}= <S>);
+    chop($data{fixed_versions}= <S>);
+    close(S);
+       $data{severity} = 'normal' if $data{severity} eq '';
+    return \%data;
 }
 
 sub lockreadbug {
-    local ($lref) = @_;
+    local ($lref, $location) = @_;
     &filelock("lock/$lref");
-    if (!open(S,"db/$lref.status")) { &unfilelock; return 0; }
-    chop($s_originator= <S>);
-    chop($s_date= <S>);
-    chop($s_subject= <S>);
-    chop($s_msgid= <S>);
-    chop($s_package= <S>);
-    chop($s_keywords= <S>);
-    chop($s_done= <S>);
-    chop($s_forwarded= <S>);
-    chop($s_mergedwith= <S>);
-    chop($s_severity= <S>);
-    close(S);
-       $s_severity = 'normal' if $s_severity eq '';
-    return 1;
+    my $data = readbug($lref, $location);
+    &unfilelock unless defined $data;
+    return $data;
+}
+
+sub writebug {
+    local ($ref, $data, $location) = @_;
+    my $change;
+    my $status = getbugcomponent($ref, 'status', $location);
+    &quit("can't find location for $ref") unless defined $status;
+    open(S,"> $status.new") || &quit("opening $status.new: $!");
+    print(S
+          "$data->{originator}\n".
+          "$data->{date}\n".
+          "$data->{subject}\n".
+          "$data->{msgid}\n".
+          "$data->{package}\n".
+          "$data->{keywords}\n".
+          "$data->{done}\n".
+          "$data->{forwarded}\n".
+          "$data->{mergedwith}\n".
+          "$data->{severity}\n".
+          "$data->{versions}\n".
+          "$data->{fixed_versions}\n") || &quit("writing $status.new: $!");
+    close(S) || &quit("closing $status.new: $!");
+    if (-e $status) {
+        $change = 'change';
+    } else {
+        $change = 'new';
+    }
+    rename("$status.new",$status) ||
+        &quit("installing new $status: $!");
+        &bughook($change,$ref,
+          "$data->{originator}\n".
+          "$data->{date}\n".
+          "$data->{subject}\n".
+          "$data->{msgid}\n".
+          "$data->{package}\n".
+          "$data->{keywords}\n".
+          "$data->{done}\n".
+          "$data->{forwarded}\n".
+          "$data->{mergedwith}\n".
+          "$data->{severity}\n".
+          "$data->{versions}\n".
+          "$data->{fixed_versions}\n");
+}
+
+sub unlockwritebug {
+    writebug(@_);
+    &unfilelock;
 }
 
 sub filelock {
@@ -71,10 +170,14 @@ sub filelock {
 }
 
 sub unfilelock {
+    if (@filelocks == 0) {
+        warn "unfilelock called with no active filelocks!\n";
+        return;
+    }
     local ($lockfile) = pop(@filelocks);
     pop(@cleanups);
-    eval 'close(FLOCK'.($#filelocks+1).');' || warn "failed to close lock file: $!";
-    unlink($lockfile) || warn "failed to remove lock file: $!";
+    eval 'close(FLOCK'.($#filelocks+1).');' || warn "failed to close lock file $lockfile: $!";
+    unlink($lockfile) || warn "failed to remove lock file $lockfile: $!";
 }
 
 sub quit {
@@ -97,7 +200,127 @@ sub sani {
     $out;
 }
 
-@severities= @gSeverityList;
+sub update_realtime {
+       my ($file, $bug, $new) = @_;
+
+       # update realtime index.db
+
+       open(IDXDB, "<$file") or die "Couldn't open $file";
+       open(IDXNEW, ">$file.new");
+
+       my $line;
+       my @line;
+       while($line = <IDXDB>) {
+               @line = split /\s/, $line;
+               last if ($line[1] >= $bug);
+               print IDXNEW $line;
+               $line = "";
+       }
+
+       if ($new eq "NOCHANGE") {
+               print IDXNEW $line if ($line ne "" && $line[1] == $ref);
+       } elsif ($new eq "REMOVE") {
+               0;
+       } else {
+               print IDXNEW $new;
+       }
+       if ($line ne "" && $line[1] > $bug) {
+               print IDXNEW $line;
+               $line = "";
+       }
+
+       print IDXNEW while(<IDXDB>);
+
+       close(IDXNEW);
+       close(IDXDB);
+
+       rename("$file.new", $file);
+
+       return $line;
+}
+
+sub bughook_archive {
+       my $ref = shift;
+       &filelock("debbugs.trace.lock");
+       &appendfile("debbugs.trace","archive $ref\n");
+       my $line = update_realtime(
+               "$gSpoolDir/index.db.realtime", 
+               $ref,
+               "REMOVE");
+       update_realtime("$gSpoolDir/index.archive.realtime",
+               $ref, $line);
+       &unfilelock;
+}      
+
+sub bughook {
+       my ( $type, $ref ) = ( shift, shift );
+       &filelock("debbugs.trace.lock");
+
+       &appendfile("debbugs.trace","$type $ref\n",@_);
+
+       my @stuff=split /\n/, "$_[0]\n\n\n\n\n\n\n";
+
+       my $whendone = "open";
+       my $severity = $gDefaultSeverity;
+       (my $pkglist = $stuff[4]) =~ s/[,\s]+/,/g;
+       $pkglist =~ s/^,+//;
+       $pkglist =~ s/,+$//;
+       $whendone = "forwarded" if length $stuff[7];
+       $whendone = "done" if length $stuff[6];
+       $severity = $stuff[9] if length $stuff[9];
+
+       my $k = sprintf "%s %d %d %s [%s] %s %s\n",
+                       $pkglist, $ref, $stuff[1], $whendone, $stuff[0],
+                       $severity, $stuff[5];
+
+       update_realtime("$gSpoolDir/index.db.realtime", $ref, $k);
+
+       &unfilelock;
+}
+
+sub appendfile {
+       my $file = shift;
+       if (!open(AP,">>$file")) {
+               print DEBUG "failed open log<\n";
+               print DEBUG "failed open log err $!<\n";
+               &quit("opening $file (appendfile): $!");
+       }
+       print(AP @_) || &quit("writing $file (appendfile): $!");
+       close(AP) || &quit("closing $file (appendfile): $!");
+}
+
+sub getmailbody {
+       my $entity = shift;
+       my $type = $entity->effective_type;
+       if ($type eq 'text/plain' or
+           ($type =~ m#text/# and $type ne 'text/html') or
+           $type eq 'application/pgp') {
+               return $entity->bodyhandle;
+       } elsif ($type eq 'multipart/alternative') {
+               # RFC 2046 says we should use the last part we recognize.
+               for my $part (reverse $entity->parts) {
+                       my $ret = getmailbody($part);
+                       return $ret if $ret;
+               }
+       } else {
+               # For other multipart types, we just pretend they're
+               # multipart/mixed and run through in order.
+               for my $part ($entity->parts) {
+                       my $ret = getmailbody($part);
+                       return $ret if $ret;
+               }
+       }
+       return undef;
+}
+
+sub escapelog {
+       my @log = @_;
+       map { s/^([\01-\07\030])/\030$1/gm } @log;
+       return \@log;
+}
+
+
+@severities= grep { not exists $gObsoleteSeverities{$_} } @gSeverityList;
 @showseverities= @severities;
 grep ($_= $_ eq '' ? $gDefaultSeverity : $_, @showseverities);
 @strongseverities= @gStrongSeverities;