]> git.donarmstrong.com Git - debbugs.git/blob - Debbugs/DBase.pm
[project @ 2000-05-01 09:24:56 by doogie]
[debbugs.git] / Debbugs / DBase.pm
1 # TODO: Implement 'stale' checks, so that there is no need to explicitly
2 #       write out a record, before closing.
3
4 package Debbugs::DBase;  # assumes Some/Module.pm
5
6 use strict;
7
8 BEGIN {
9         use Exporter   ();
10         use vars       qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
11
12         # set the version for version checking
13         $VERSION     = 1.00;
14
15         @ISA         = qw(Exporter);
16         @EXPORT      = qw( %Record );
17         %EXPORT_TAGS = ( );     # eg: TAG => [ qw!name1 name2! ],
18
19         # your exported package globals go here,
20         # as well as any optionally exported functions
21         @EXPORT_OK   = qw( %Record );
22 }
23
24 use vars      @EXPORT_OK;
25 use Fcntl ':flock';
26 use Debbugs::Config;
27 use Debbugs::Email;
28 use Debbugs::Common;
29 use FileHandle;
30 use File::Basename qw(&dirname);
31 use File::Path;
32
33 %Record = ();
34
35 my $LoadedRecord = 0;
36 my $OpenedRecord = 0;
37 my $OpenedLog = 0;
38 my $FileLocked = 0;
39 my $FileHandle = new FileHandle;
40 my $LogfileHandle = new FileHandle;
41
42 sub ParseVersion1Record
43 {
44     my @data = @_;
45     my @fields = ( "originator", "date", "subject", "msgid", "package",
46                 "keywords", "done", "forwarded", "mergedwith", "severity" );
47     my $i = 0;
48     my $tag;
49
50     print "D2: (DBase) Record Fields:\n" if $Globals{ 'debug' } > 1;
51     foreach my $line ( @data )
52     {
53         chop( $line );
54         $tag = $fields[$i];
55         $Record{ $tag } = $line;
56         print "\t $tag = $line\n" if $Globals{ 'debug' } > 1;
57         $i++;
58         $GTags{ "BUG_$tag" } = $line;
59     }
60 }
61
62 sub ParseVersion2Record
63 {
64     # I envision the next round of records being totally different in
65     # meaning.  In order to maintain compatability, version tagging will be
66     # implemented in thenext go around and different versions will be sent
67     # off to different functions to be parsed and interpreted into a format
68     # that the rest of the system will understand.  All data will be saved
69     # in whatever 'new" format ixists.  The difference will be a "Version: x"
70     # at the top of the file.
71
72     print "No version 2 records are understood at this time\n";
73     exit 1;
74 }
75
76 sub ReadRecord
77 {
78     my $record = $_[0];
79     print "V: Reading status $record\n" if $Globals{ 'verbose' };
80     if ( $record ne $LoadedRecord )
81     {
82         my @data;
83
84         seek( $FileHandle, 0, 0 );
85         @data = <$FileHandle>;
86         if ( scalar( @data ) =~ /Version: (\d*)/ )
87         {
88             if ( $1 == 2 )
89             { &ParseVersion2Record( @data ); }
90             else
91             { &fail( "Unknown record version: $1\n"); }
92         }
93         else { &ParseVersion1Record( @data ); }
94         $LoadedRecord = $record;
95     }
96     else { print "D1: (DBase) $record is already loaded\n" if $Globals{ 'debug' }; }
97
98 }
99
100 sub WriteRecord
101 {
102     my @fields = ( "originator", "date", "subject", "msgid", "package",
103                 "keywords", "done", "forwarded", "mergedwith", "severity" );
104     print "V: Writing status $LoadedRecord\n" if $Globals{ 'verbose' };
105     seek( $FileHandle, 0, 0 );
106     for( my $i = 0; $i < $#fields; $i++ )
107     {
108         if ( defined( $fields[$i] ) )
109         { print $FileHandle $Record{ $fields[$i] } . "\n"; }
110         else { print $FileHandle "\n"; }
111     }
112 }
113
114 sub OpenFile
115 {
116     my ($prePaths, $stub, $postPath, $desc, $new) = (shift, shift, shift, shift, shift);
117     foreach my $prePath (@$prePaths) {
118         my $path = "/" . $prePath . "/" . $stub . $postPath, my $handle = new FileHandle;
119         print "V: Opening $desc $stub\n" if $Globals{ 'verbose' };
120         print "D2: (DBase) trying $path\n" if $Globals{ 'debug' } > 1;
121         if( ! -r $Globals{ "work-dir" } . $path ) {
122             $path = "/" . $prePath . "/" . &NameToPathHash($stub) . $postPath;
123             print "D2: (DBase) trying $path\n" if $Globals{ 'debug' } > 1;
124             if( ! -r $Globals{ "work-dir" } . $path ) {
125                 next if( !$new =~ "new" );
126             }
127         }
128         open( $handle, $Globals{ "work-dir" } . $path ) && return $handle;
129         if($new =~ "new") {
130             my $dir = dirname( $path );
131             if ( ! -d $Globals{ "work-dir" } . $dir ) {
132                 mkpath($Globals{ "work-dir" } . $dir);
133             }
134             open( $handle, ">" . $Globals{ "work-dir" } . $path ) && return $handle;
135         }
136     }
137     return;
138 }
139 sub OpenRecord
140 {
141     my $record = $_[0];
142     if ( $record ne $OpenedRecord )
143     {
144         $FileHandle = OpenFile ["db", "archive"], $record, ".status", "status", $_[1];
145         flock( $FileHandle, LOCK_EX ) || &fail( "Unable to lock record $record\n" );
146         $OpenedRecord = $record;
147     }
148 }
149
150 sub CloseRecord
151 {
152     print "V: Closing status $LoadedRecord\n" if $Globals{ 'verbose' };
153     close $FileHandle;
154     $OpenedRecord = 0;
155 }
156
157 sub OpenLogfile
158 {
159     my $record = $_[0];
160     if ( $record ne $OpenedLog )
161     {
162         $LogfileHandle = OpenFile("db", $record, ".log", "log");
163         seek( $FileHandle, 0, 2 );
164         $OpenedLog = $record;
165     }
166 }
167
168 sub CloseLogfile
169 {
170     print "V: Closing log $OpenedLog\n" if $Globals{ 'verbose' };
171     close $LogfileHandle;
172     $OpenedLog = 0;
173 }
174 sub GetBugList
175 {
176 # TODO: This is ugly, but the easiest for me to implement.
177 #       If you have a better way, then please send a patch.
178 #
179     my $dir = new FileHandle;
180
181     my $prefix;
182     my $paths = shift;
183     my @paths;
184     if ( !defined($paths) ) {
185         @paths = ("db");
186     } else {
187         @paths = @$paths;
188     }
189     my @ret;
190     my $path;
191     foreach $path (@paths) {
192         $prefix = $Globals{ "work-dir" } . "/" . $path . "/";
193         opendir $dir, $prefix;
194         my @files = readdir($dir);
195         closedir $dir;
196         foreach (grep { /\d*\d\d.status/ } @files) {
197             next if ( ! -s $prefix . "/" . $_ );
198             s/.status$//;
199             push @ret, $_;
200 #           print "$_ -> $_\n";
201         }
202         foreach (grep { /^[s0-9]$/ } @files) {
203             my $_1 = $_;
204             opendir $dir, $prefix . $_1;
205             my @files = grep { /^\d$/ } readdir($dir);
206             closedir $dir;
207             foreach (@files) {
208                 my $_2 = $_;
209                 opendir $dir, "$prefix$_1/$_2";
210                 my @files = grep { /^\d$/ } readdir($dir);
211                 close $dir;
212                 foreach (@files) {
213                     my $_3 = $_;
214                     opendir $dir, "$prefix$_1/$_2/$_3";
215                     my @files = grep { /\d*\d\d.status/ } readdir($dir);
216                     close $dir;
217                     foreach (@files) {
218                         next if ( ! -s "$prefix$_1/$_2/$_3/$_" );
219                         s/.status$//;
220                         push @ret, $_;
221 #                       print "$_ -> $_1/$_2/$_3/$_\n";
222                     }
223                 }
224             }
225         }
226     }
227     return @ret;
228 }
229
230 1;
231
232 END { }       # module clean-up code here (global destructor)