]> git.donarmstrong.com Git - debbugs.git/blob - bin/add_bug_to_estraier
381b7d7b4612efc574670eb2ea57ccb74802fd35
[debbugs.git] / bin / add_bug_to_estraier
1 #!/usr/bin/perl
2 # add_bug_to_estraier adds a log for a bug to the estaier db, and is
3 # released under the terms of the GPL version 2, or any later version,
4 # at your option. See the file README and COPYING for more
5 # information.
6 # Copyright 2006 by Don Armstrong <don@debian.org>.
7
8
9
10 use warnings;
11 use strict;
12
13
14 use Getopt::Long;
15 use Pod::Usage;
16
17 =head1 NAME
18
19 add_bug_to_estraier -- add a bug log to an estraier database
20
21 =head1 SYNOPSIS
22
23 add_bug_to_estraier [options] < list_of_bugs_to_add
24
25  Options:
26   --debug, -d debugging level (Default 0)
27   --help, -h display this help
28   --man, -m display manual
29
30 =head1 OPTIONS
31
32 =over
33
34 =item B<--url, -u>
35
36 Url to the estraier node
37
38 =item B<--user,-U>
39
40 User to log onto the estraier node
41
42 =item B<--pass,-P>
43
44 Password to log onto the estraier node
45
46 =item B<--spool,-s>
47
48 Spool location; if not set defaults to /etc/debbugs/config
49
50 =item B<--conf,-C>
51
52 Configuration file; a set of key = value pairs separated by newlines;
53 the long name of any option is the name that the configuration file
54 takes
55
56 =item B<--cron>
57
58 Descend through the spool and add all of the bugs to estraier
59
60 =item B<--timestamp>
61
62 Use the timestamp file to only add new bugs; will lock the timestamp
63 file to avoid racing with other invocations
64
65 =item B<--debug, -d>
66
67 Debug verbosity. (Default 0)
68
69 =item B<--help, -h>
70
71 Display brief useage information.
72
73 =item B<--man, -m>
74
75 Display this manual.
76
77 =back
78
79
80 =head1 EXAMPLES
81
82   test_bts --bug 7 --host donbugs.donarmstrong.com
83
84 =head1 DATABASE CREATION
85
86 estcmd create -si -xh3 -attr status str -attr subject str \
87     -attr date num -attr submitter str -attr package str \
88     -attr severity str -attr tags str bts
89
90
91 =cut
92
93
94 use Debbugs::Config qw(:globals);
95 use Debbugs::Mail qw(send_mail_message);
96 use Debbugs::MIME qw(create_mime_message);
97
98 use Search::Estraier;
99 use Debbugs::Estraier qw(:add);
100 use File::Find;
101 use File::stat;
102
103 use vars qw($DEBUG $VERBOSE);
104
105 # XXX parse config file
106
107 my %options = (debug           => 0,
108                help            => 0,
109                man             => 0,
110                url             => undef,
111                user            => undef,
112                passwd          => undef,
113                spool           => undef,
114                conf            => undef,
115                cron            => 0,
116                timestamp       => undef,
117               );
118
119 GetOptions(\%options,'url|u=s','user|U=s','passwd|P=s',
120            'spool|s=s','conf|C=s','cron!','timestamp=s',
121            'debug|d+','help|h|?','man|m');
122
123 my $ERRORS = '';
124
125 if (not defined $options{conf}) {
126      $ERRORS .= "--url must be set\n" if not defined $options{url};
127      $ERRORS .= "--user must be set\n" if not defined $options{user};
128      $ERRORS .= "--passwd must be set\n" if not defined $options{passwd};
129 }
130 else {
131      # Read the conf file
132      my $conf_fh = new IO::File $options{conf},'r'
133           or die "Unable to open $options{conf} for reading";
134      while (<$conf_fh>) {
135           chomp;
136           next if /^\s*\#/;
137           my ($key,$value) = split /\s*[:=]\s*/,$_,2;
138           $options{$key} = $value if defined $key and not defined $options{$key};
139      }
140      $ERRORS .= "url must be set\n" if not defined $options{url};
141      $ERRORS .= "user must be set\n" if not defined $options{user};
142      $ERRORS .= "passwd must be set\n" if not defined $options{passwd};
143 }
144 $ERRORS .= "--spool must be set if --cron is used\n" if
145      not defined $options{spool} and $options{cron};
146 pod2usage($ERRORS) if length $ERRORS;
147
148 pod2usage() if $options{help};
149 pod2usage({verbose=>2}) if $options{man};
150
151
152 $DEBUG = $options{debug};
153
154 $Debbugs::Estraier::DEBUG = $DEBUG;
155 $VERBOSE = 0;
156
157 my $node =  new Search::Estraier::Node (url    => $options{url},
158                                         user   => $options{user},
159                                         passwd => $options{passwd},
160                                        );
161 $gSpoolDir = $options{spool} if defined $options{spool};
162
163 if ($options{cron}) {
164      my %timestamps;
165      my $start_time = time;
166      my $unlink = 0;
167      my %seen_dirs;
168      check_pid($options{timestamp});
169      # read timestamp file
170      if (defined $options{timestamp}) {
171           my $timestamp_fh = new IO::File $options{timestamp},'r' or
172                die "Unable to open timestamp $options{timestamp}: $!";
173           while (<$timestamp_fh>) {
174                chomp;
175                my ($key,$value) = split /\s+/,$_,2;
176                $timestamps{$key} = $value;
177           }
178      }
179      for my $hash (map {sprintf '%02d',$_ } 0..99) {
180           find(sub {
181                     print STDERR "Examining $_\n" if $DEBUG > 1;
182                     return if not /^(\d+)\.log$/;
183                     my $bug_num = $1;
184                     my $stat = stat $_ or next;
185                     return unless -f _;
186                     return if exists $timestamps{$File::Find::dir} and
187                          ($timestamps{$File::Find::dir} > $stat->mtime);
188                     $seen_dirs{$File::Find::dir} = $start_time;
189                     print STDERR "Adding $bug_num\n" if $DEBUG;
190                     my $max_message = 0;
191                     eval{
192                          $max_message = add_bug_log($node,$bug_num);
193                     };
194                     if ($@) {
195                          print STDERR "Adding $bug_num failed with $@\n";
196                     }
197                },
198                map {(-d "$options{spool}/$_/$hash")?
199                          "$options{spool}/$_/$hash":()}
200                qw(db-h archive),
201               );
202           # write timestamp file
203           if (defined $options{timestamp}) {
204                %timestamps = (%timestamps,%seen_dirs);
205                my $timestamp_fh = new IO::File $options{timestamp},'w' or
206                     die "Unable to open timestamp $options{timestamp}: $!";
207                foreach my $key (keys %timestamps) {
208                     print {$timestamp_fh} $key,' ',
209                          $timestamps{$key}||'',qq(\n);
210                }
211           }
212      }
213      unlink("$options{timestamp}.pid");
214 }
215 else {
216      while (my $bug_num = <STDIN>) {
217           chomp $bug_num;
218           add_bug_log($node,$bug_num);
219      }
220 }
221
222
223 sub check_pid{
224      my ($timestamp) = @_;
225      if (-e "${timestamp}.pid") {
226           my $time_fh = new IO::File  "${timestamp}.pid", 'r' or die "Unable to read pidfile";
227           local $/;
228           my $pid = <$time_fh>;
229           if (kill(0,$pid)) {
230                print STDERR "Another cron is running" and exit 0;
231           }
232      }
233      my $time_fh = new IO::File  "${timestamp}.pid", 'w' or
234           die "Unable to read pidfile";
235      print {$time_fh} $$;
236 }
237
238
239 __END__