1 # TODO: Implement 'stale' checks, so that there is no need to explicitly
2 # write out a record, before closing.
4 package Debbugs::DBase; # assumes Some/Module.pm
10 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
12 # set the version for version checking
17 %EXPORT_TAGS = ( ); # eg: TAG => [ qw!name1 name2! ],
19 # your exported package globals go here,
20 # as well as any optionally exported functions
29 use Debbugs::DBase::Log;
30 use Debbugs::DBase::Log::Html;
31 use Debbugs::DBase::Log::Message;
32 use Debbugs::DBase::Log::Mail;
35 use File::Basename qw(&dirname);
41 my $LogfileHandle = new FileHandle;
43 sub ParseVersion1Record
46 my @fields = ( "originator", "date", "subject", "msgid", "package",
47 "keywords", "done", "forwarded", "mergedwith", "severity" );
52 print "D2: (DBase) Record Fields:\n" if $Globals{ 'debug' } > 1;
53 foreach my $line ( @data )
57 $record{ $tag } = $line;
58 print "\t $tag = $line\n" if $Globals{ 'debug' } > 1;
60 $btags{ "BUG_$tag" } = $line;
62 return ( \%record, \%btags );
65 sub ParseVersion2Record
67 # I envision the next round of records being totally different in
68 # meaning. In order to maintain compatability, version tagging will be
69 # implemented in the next go around and different versions will be sent
70 # off to different functions to be parsed and interpreted into a format
71 # that the rest of the system will understand. All data will be saved
72 # in whatever 'new" format exists. The difference will be a "Version: x"
73 # at the top of the file.
75 print "No version 2 records are understood at this time\n";
81 my ($recordnum, $with_log, $new) = (shift, shift, shift);
87 print "V: Reading status $recordnum\n" if $Globals{ 'verbose' };
88 if( $OpenedRecord != $recordnum )
90 if( defined( $FileHandle ) )
92 print "D1: Closing status $recordnum\n" if $Globals{ 'debug' };
97 print "D1: Opening status $recordnum\n" if $Globals{ 'debug' };
98 $FileHandle = &OpenFile( ["db", "archive"], $recordnum, ".status", "status", $new );
99 if( !defined( $FileHandle ) ) { return undef; }
101 else { print "D1: Reusing status $recordnum\n" if $Globals{ 'debug' }; }
104 print "D1: Locking status $recordnum\n" if $Globals{ 'debug' };
105 flock( $FileHandle, LOCK_EX ) || &fail( "Unable to lock record $recordnum\n" );
107 #Read in status file contents
108 print "D1: Loading status $recordnum\n" if $Globals{ 'debug' };
109 seek( $FileHandle, 0, 0 );
110 @data = <$FileHandle>;
112 #Parse Status File Contents
113 if ( scalar( @data ) =~ /Version: (\d*)/ )
116 { &ParseVersion2Record( @data ); }
118 { &fail( "Unknown record version: $1\n"); }
120 else { ($record, $btags) = &ParseVersion1Record( @data ); }
123 #DO READ IN LOG RECORD DATA STUFF
125 return ($record, $btags);
130 my ($recordnum, %record) = @_;
131 my @fields = ( "originator", "date", "subject", "msgid", "package",
132 "keywords", "done", "forwarded", "mergedwith", "severity" );
135 print "V: Writing status $recordnum\n" if $Globals{ 'verbose' };
136 if( $OpenedRecord != $recordnum )
138 if( defined( $FileHandle ) )
140 print "D1: Closing status $recordnum\n" if $Globals{ 'debug' };
145 print "D1: Opening status $recordnum\n" if $Globals{ 'debug' };
146 $FileHandle = &OpenFile( ["db", "archive"], $recordnum, ".status", "status", "old" );
147 if( !defined( $FileHandle ) ) { return undef; }
149 else { print "D1: Reusing status $recordnum\n" if $Globals{ 'debug' }; }
152 print "D1: Locking status $recordnum\n" if $Globals{ 'debug' };
153 flock( $FileHandle, LOCK_EX ) || &fail( "Unable to lock record $recordnum\n" );
155 #Read in status file contents
156 print "D1: Saving status $recordnum\n" if $Globals{ 'debug' };
157 seek( $FileHandle, 0, 0 );
158 for( my $i = 0; $i < $#fields; $i++ )
160 if ( defined( $record{ $fields[$i] } ) )
161 { print $FileHandle $record{ $fields[$i] } . "\n"; }
162 else { print $FileHandle "\n"; }
168 my ($prePaths, $stub, $postPath, $desc, $new) = (shift, shift, shift, shift, shift);
170 foreach my $prePath (@$prePaths) {
171 $path = "/" . $prePath . "/" . $stub . $postPath;
172 print "V: Opening $desc $stub\n" if $Globals{ 'verbose' };
173 print "D2: (DBase) trying $path\n" if $Globals{ 'debug' } > 1;
174 if( ! -r $Globals{ "work-dir" } . $path ) {
175 $path = "/" . $prePath . "/" . &NameToPathHash($stub) . $postPath;
176 print "D2: (DBase) trying $path\n" if $Globals{ 'debug' } > 1;
177 if( ! -r $Globals{ "work-dir" } . $path ) {
178 next if( !$new =~ "new" );
181 if( -r $Globals{ "work-dir" } . $path ) {
184 if( ( ! -r $Globals{ "work-dir" } . $path ) && defined($new) && $new =~ "new") {
185 my $dir = dirname( $path );
186 if ( ! -d $Globals{ "work-dir" } . $dir ) {
187 mkpath($Globals{ "work-dir" } . $dir);
197 my ($prePaths, $stub, $postPath, $desc, $new) = (shift, shift, shift, shift, shift);
198 my $fileName = GetFileName($prePaths, $stub, $postPath, $desc, $new);
199 my $handle = new FileHandle;
200 open( $handle, $Globals{ "work-dir" } . $fileName ) && return $handle;
207 if ( $record ne $OpenedLog )
209 $LogfileHandle = OpenFile(["db", "archive"], $record, ".log", "log");
210 $OpenedLog = $record;
217 if ( $record eq $OpenedLog )
219 seek( $LogfileHandle, 0, 0 );
220 my $log = new Debbugs::DBase::Log;
221 $log->Load($LogfileHandle);
227 print "V: Closing log $OpenedLog\n" if $Globals{ 'verbose' };
228 close $LogfileHandle;
233 # TODO: This is ugly, but the easiest for me to implement.
234 # If you have a better way, then please send a patch.
236 my $dir = new FileHandle;
241 if ( !defined($paths) ) {
248 foreach $path (@paths) {
249 $prefix = $Globals{ "work-dir" } . "/" . $path . "/";
250 opendir $dir, $prefix;
251 my @files = readdir($dir);
253 foreach (grep { /\d*\d\d.status/ } @files) {
254 next if ( ! -s $prefix . "/" . $_ );
257 # print "$_ -> $_\n";
259 foreach (grep { /^[s0-9]$/ } @files) {
261 opendir $dir, $prefix . $_1;
262 my @files = grep { /^\d$/ } readdir($dir);
266 opendir $dir, "$prefix$_1/$_2";
267 my @files = grep { /^\d$/ } readdir($dir);
271 opendir $dir, "$prefix$_1/$_2/$_3";
272 my @files = grep { /\d*\d\d.status/ } readdir($dir);
275 next if ( ! -s "$prefix$_1/$_2/$_3/$_" );
278 # print "$_ -> $_1/$_2/$_3/$_\n";
289 END { } # module clean-up code here (global destructor)