1 # This module is part of debbugs, and is released
2 # under the terms of the GPL version 2, or any later version at your option.
3 # See the file README and COPYING for more information.
4 # Copyright 2007 by Don Armstrong <don@donarmstrong.com>.
26 use vars qw($DEBUG %EXPORT_TAGS @EXPORT_OK @EXPORT);
27 use base qw(Exporter SOAP::Server::Parameters);
30 $DEBUG = 0 unless defined $DEBUG;
36 Exporter::export_ok_tags();
37 $EXPORT_TAGS{all} = [@EXPORT_OK];
43 use Debbugs::Status qw(get_bug_status);
44 use Debbugs::Common qw(make_list getbuglocation getbugcomponent);
45 use Storable qw(nstore retrieve);
46 use Scalar::Util qw(looks_like_number);
49 our $CURRENT_VERSION = 1;
53 my %ut = get_usertag('don@donarmstrong.com','this-bug-sucks','eat-this-bug');
54 my %ut = get_usertag('don@donarmstrong.com');
56 Returns a hashref of bugs which have the specified usertags for the
59 In the second case, returns all of the usertags for the user passed.
63 use Debbugs::User qw(read_usertags);
66 my $VERSION = __populate_version(pop);
67 my ($self,$email, @tags) = @_;
69 read_usertags(\%ut, $email);
71 @tags{@tags} = (1) x @tags;
73 for my $tag (keys %ut) {
74 delete $ut{$tag} unless exists $tags{$tag};
85 my @statuses = get_status(@bugs);
86 my @statuses = get_status([bug => 304234,
94 Returns an arrayref of hashrefs which output the status for specific
97 In the first case, no options are passed to
98 L<Debbugs::Status::get_bug_status> besides the bug number; in the
99 second the bug, dist, arch, bugusertags, sourceversions, and version
100 parameters are passed if they are present.
102 As a special case for suboptimal SOAP implementations, if only one
103 argument is passed to get_status and it is an arrayref which either is
104 empty, has a number as the first element, or contains an arrayref as
105 the first element, the outer arrayref is dereferenced, and processed
106 as in the examples above.
108 See L<Debbugs::Status::get_bug_status> for details.
113 my $VERSION = __populate_version(pop);
114 my ($self,@bugs) = @_;
120 looks_like_number($bugs[0][0])
126 for my $bug (@bugs) {
129 my %param = __collapse_params(@{$bug});
130 next unless defined $param{bug};
132 $bug_status = get_bug_status(map {(exists $param{$_})?($_,$param{$_}):()}
133 qw(bug dist arch bugusertags sourceversions version indicatesource)
137 $bug_status = get_bug_status(bug => $bug);
139 if (defined $bug_status and keys %{$bug_status} > 0) {
140 $status{$bug} = $bug_status;
143 # __prepare_response($self);
149 my @bugs = get_bugs(...);
150 my @bugs = get_bugs([...]);
152 Returns a list of bugs. In the second case, allows the variable
153 parameters to be specified as an array reference in case your favorite
154 language's SOAP implementation is craptacular.
156 See L<Debbugs::Bugs::get_bugs> for details on what C<...> actually
161 use Debbugs::Bugs qw();
164 my $VERSION = __populate_version(pop);
165 my ($self,@params) = @_;
166 # Because some soap implementations suck and can't handle
167 # variable numbers of arguments we allow get_bugs([]);
168 if (@params == 1 and ref($params[0]) eq 'ARRAY') {
169 @params = @{$params[0]};
171 my %params = __collapse_params(@params);
173 @bugs = Debbugs::Bugs::get_bugs(%params);
179 my @bugs = newest_bugs(5);
181 Returns a list of the newest bugs. [Note that all bugs are *not*
182 guaranteed to exist, but they should in the most common cases.]
187 my $VERSION = __populate_version(pop);
188 my ($self,$num) = @_;
189 my $newest_bug = Debbugs::Bugs::newest_bug();
190 return [($newest_bug - $num + 1) .. $newest_bug];
196 my $bug_log = get_bug_log($bug);
197 my $bug_log = get_bug_log($bug,$msg_num);
199 Retuns a parsed set of the bug log; this is an array of hashes with
216 Currently $msg_num is completely ignored.
220 use Debbugs::Log qw();
221 use Debbugs::MIME qw(parse);
224 my $VERSION = __populate_version(pop);
225 my ($self,$bug,$msg_num) = @_;
227 my $location = getbuglocation($bug,'log');
228 my $bug_log = getbugcomponent($bug,'log',$location);
230 my $log_fh = IO::File->new($bug_log, 'r') or
231 die "Unable to open bug log $bug_log for reading: $!";
233 my $log = Debbugs::Log->new($log_fh) or
234 die "Debbugs::Log was unable to be initialized";
240 while (my $record = $log->read_record()) {
242 #next if defined $msg_num and ($current_msg ne $msg_num);
243 next unless $record->{type} eq 'incoming-recv';
244 my ($msg_id) = $record->{text} =~ /^Message-Id:\s+<(.+)>/im;
245 next if defined $msg_id and exists $seen_msg_ids{$msg_id};
246 $seen_msg_ids{$msg_id} = 1 if defined $msg_id;
247 next if defined $msg_id and $msg_id =~ /handler\..+\.ack(?:info)?\@/;
248 my $message = parse($record->{text});
249 my ($header,$body) = map {join("\n",make_list($_))}
250 @{$message}{qw(header body)};
251 push @messages,{header => $header,
254 msg_num => $current_msg,
260 =head2 binary_to_source
262 binary_to_source($binary_name,$binary_version,$binary_architecture)
264 Returns a reference to the source package name and version pair
265 corresponding to a given binary package name, version, and
266 architecture. If undef is passed as the architecture, returns a list
267 of references to all possible pairs of source package names and
268 versions for all architectures, with any duplicates removed.
270 (This function corresponds to L<Debbugs::Packages::binarytosource>)
274 sub binary_to_source{
275 my $VERSION = __populate_version(pop);
277 return [binarytosource(@_)];
280 =head2 source_to_binary
282 source_to_binary($source_name,$source_version);
284 Returns a reference to an array of references to binary package name,
285 version, and architecture corresponding to a given source package name
286 and version. In the case that the given name and version cannot be
287 found, the unversioned package to source map is consulted, and the
288 architecture is not returned.
290 (This function corresponds to L<Debbugs::Packages::sourcetobinary>)
294 sub source_to_binary {
295 my $VERSION = __populate_version(pop);
297 return [source_to_binary(@_)];
302 get_version(package=>'foopkg',
307 Returns a list of the versions of package in the distributions and
308 architectures listed. This routine only returns unique values.
312 =item package -- package to return list of versions
314 =item dist -- distribution (unstable, stable, testing); can be an
317 =item arch -- architecture (i386, source, ...); can be an arrayref
319 =item time -- returns a version=>time hash at which the newest package
320 matching this version was uploaded
322 =item source -- returns source/version instead of just versions
324 =item no_source_arch -- discards the source architecture when arch is
325 not passed. [Used for finding the versions of binary packages only.]
326 Defaults to 0, which does not discard the source architecture. (This
327 may change in the future, so if you care, please code accordingly.)
329 =item return_archs -- returns a version=>[archs] hash indicating which
330 architectures are at which versions.
334 This function correponds to L<Debbugs::Packages::get_versions>
339 my $VERSION = __populate_version(pop);
341 return scalar get_versions(@_);
344 =head1 VERSION COMPATIBILITY
346 The functionality provided by the SOAP interface will change over time.
348 To the greatest extent possible, we will attempt to provide backwards
349 compatibility with previous versions; however, in order to have
350 backwards compatibility, you need to specify the version with which
355 sub __populate_version{
357 return $request->{___debbugs_soap_version};
360 sub __collapse_params{
364 # Because some clients can't handle passing arrayrefs, we allow
365 # options to be specified multiple times
366 while (my ($key,$value) = splice @params,0,2) {
367 push @{$params{$key}}, make_list($value);
369 # However, for singly specified options, we want to pull them
371 for my $key (keys %params) {
372 if (@{$params{$key}} == 1) {
373 ($params{$key}) = @{$params{$key}}