How about a tool to search in the BTS database?
Hi,
With Lucas Nussbaum, we thought that the BTS needs a tool to search in
the database.
So, I started to code something that may interest you, with a Xapian[0]
database. To have an overview, you can see the attached manpage bunny.1,
with less. If you would to see the project progress I've attached the
client bunny, the server side bunny-server.pl and the indexer
bunny-indexer.pl.
[0] http://xapian.org/features
To try it:
* Download a bts-spool-db version (with 01/ 02/ 03/ etc)
* Configure some paths in the header of the three scripts
* Launch ./bunny-index.pl to create the Xapian db version
* Install bunny-server.pl on a web server
* Use ./bunny as a client (less bunny.1)
Currently, all is implemented and the searcher works fine. It only
remains to find a solution to update the xapian db when bts-spool-db
change. A web front end will also be added quickly. And there is still
some bugs to fix before to release it.
How about add it in the devscripts and host the server side & the web
front end on a debian server?
Cheers,
ju.
--
Envoyé via un serveur personnel, hébergé dans mon appartement et relié
au réseau par un FAI participatif. Je suis le seul à pouvoir consulter
mon courrier ; et vous ?
* http://julien.vaubourg.com
* lemanchotvolant@jabber.fr
* +33(0)6 71 555 141
#!/usr/bin/perl
# bunny-indexer - Index a bts-spool-db mirror (Debian bugs) in a Xapian db
#
# Copyright (C) 2011 Julien Vaubourg <julien@vaubourg.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
use strict;
use Search::Xapian (':all');
use POSIX;
use WWW::Mechanize;
use JSON -support_by_pp;
########## CONFIGURE:BEGIN ##########
# Path of the bts-spool-db mirror directory (with 01/ 02/ 03/ etc)
my $textdb_path = "./simpledb";
# Path and name of the Xapian db to create
my $database_path = "./simpledb-xap";
########### CONFIGURE:END ###########
# Slots used for the sorting
my $SLOT_DATE = 0;
my $SLOT_SEVERITY = 1;
my $SLOT_WNPP = 2;
my $SLOT_PACKAGE = 3;
my ($database, $indexer);
eval {
# Create or open the Xapian db
$database = Search::Xapian::WritableDatabase->new(
$database_path,
DB_CREATE_OR_OPEN
);
$indexer = Search::Xapian::TermGenerator->new();
my $stemmer = Search::Xapian::Stem->new("english");
$indexer->set_stemmer($stemmer);
# Fill the Xapian db with .log and .summary files
index_bugs($textdb_path);
}; if($@) {
print STDERR "Exception: $@\n";
exit 1;
}
# Index all bugs from bugs_dir/nn/ID.{summary,log}
sub index_bugs {
my $bugs_dir = shift @_;
opendir(my $BUGS_DIR, $bugs_dir)
or die "Couldn't open $bugs_dir!";
# Sub-directories 01/ 02/ 03/ etc
while (my $ndir = readdir($BUGS_DIR)) {
# It's not a wrong file
if(-d "$bugs_dir/$ndir" && "$bugs_dir/$ndir" =~ /\d+/) {
opendir(my $BUGS_NDIR, "$bugs_dir/$ndir")
or die "Couldn't open $bugs_dir/$ndir!";
# For each file .log .report .summary .status
while (my $file = readdir($BUGS_NDIR)) {
# We use the .summary and the .log files for
# index the bug
if($file =~ /(\d+)\.summary$/) {
my (
$bug_id,
$bug_package_version,
$bug_doneby,
$bug_date,
$bug_fixed,
$bug_tags,
$bug_severity,
$bug_submitter,
$bug_subject,
$bug_wnpp,
$bug_package,
$bug_log
);
$bug_fixed = 0;
$bug_log = "";
$bug_id = $1;
# Open the ID.summary
open(my $SUMMARY, "$bugs_dir/$ndir/$file")
or die "Couldn't open $bugs_dir/$ndir/$file!";
# For each line, extract the field
while(<$SUMMARY>) {
chomp;
if(/^Found-In:\s+(.*)/) {
$bug_package_version = $1;
} elsif(/^Done:\s+(.*)/) {
$bug_doneby = $1;
} elsif(/^Date:\s+(.*)/) {
$bug_date = $1;
} elsif(/^Fixed-In:\s+(.*)/) {
$bug_fixed = 1;
} elsif(/^Tags:\s+(.*)/) {
if($1 eq "fixed") {
$bug_fixed = 1;
} else {
$bug_tags = $1;
}
} elsif(/^Severity:\s+(.*)/) {
# Old severity fixed,
# before the tag
if($1 eq "fixed") {
$bug_fixed = 1;
} else {
$bug_severity = $1;
}
} elsif(/^Submitter:\s+(.*)/) {
$bug_submitter = $1;
} elsif(/^Subject:\s+(.*)/) {
$bug_subject = $1;
if($1 =~ /^(ITA|ITP|O|RFA|RFH|RFP):\s+/) {
$bug_wnpp = $1;
}
} elsif(/^Package:\s+(.*)/) {
$bug_package = $1;
}
}
close $SUMMARY;
# Open the log version for index it
open(my $LOG, "$bugs_dir/$ndir/$bug_id.log")
or die "Couldn't open $bugs_dir/$ndir/$bug_id.log!";
$bug_log .= "$_ " while(<$LOG>);
close $LOG;
# Index all informations
index_bug(
$bug_id,
$bug_package_version,
$bug_doneby,
$bug_date,
$bug_fixed,
$bug_tags,
$bug_severity,
$bug_submitter,
$bug_subject,
$bug_wnpp,
$bug_package,
$bug_log
);
};
}
closedir $BUGS_NDIR;
}
}
closedir $BUGS_DIR;
}
# Index a bug in the Xapian db
sub index_bug {
my (
$bug_id,
$bug_package_version,
$bug_doneby,
$bug_date,
$bug_fixed,
$bug_tags,
$bug_severity,
$bug_submitter,
$bug_subject,
$bug_wnpp,
$bug_package,
$bug_log
) = @_;
eval {
my $bug = Search::Xapian::Document->new();
$indexer->set_document($bug);
# Booleans filters
$bug->add_term('I' . $bug_id);
$bug->add_term('F' . $bug_fixed);
$bug->add_term('S' . $bug_severity);
$bug->add_term('W' . $bug_wnpp);
my @tags = split(/\s+/, $bug_tags);
$bug->add_term('T' . $_) for (@tags);
# Free text fields
$indexer->index_text($bug_log);
$indexer->index_text($bug_package, 1, 'P');
$indexer->index_text($bug_doneby, 1, 'D');
$indexer->index_text($bug_subject, 1, 'S');
my @versions = split(/\s+/, $bug_package_version);
$indexer->index_text($_, 1, 'V') for (@versions);
my @submitters = split(/\s*,\s*/, $bug_submitter);
$indexer->index_text($_, 1, 'A') for (@submitters);
# Date in human format
my ($sec,$min,$hour,$mday,$mon,$year) = gmtime($bug_date);
my $date = sprintf("%4d/%02d/%02d", $year + 1900, $mon + 1, $mday);
# Data includes some informations, which will be extracted
$bug->set_data("[$bug_id] [$date] [$bug_severity] [$bug_fixed] $bug_subject");
# Date in Xapian format
$date = sprintf("%d%d%d", $year + 1900, $mon + 1, $mday);
# Sort
$bug->add_value($SLOT_DATE, $date);
$bug->add_value($SLOT_SEVERITY, $bug_severity);
$bug->add_value($SLOT_WNPP, $bug_wnpp);
$bug->add_value($SLOT_PACKAGE, $bug_package);
# Indexing
$database->add_document($bug);
}; if($@) {
print STDERR "Exception: $@\n";
exit 1;
}
}
#!/usr/bin/perl
# bunny-server - Backend and web frontend for searching in the Debian bugs
# database
#
# Copyright (C) 2011 Julien Vaubourg <julien@vaubourg.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
use strict;
use Search::Xapian (':all');
use JSON -support_by_pp;
use Data::Dumper::Simple;
########## CONFIGURE:BEGIN ##########
# Path of the Xapian db
my $database_path = "./simpledb-xap";
########### CONFIGURE:END ###########
my $flags = 0;
my $max = 10;
my $query_string = "";
my $sort_by = undef;
my $rsort = 0;
# Xapian options available
my %flags_values = (
"boolean" => FLAG_BOOLEAN,
"phrase" => FLAG_PHRASE,
"lovehate" => FLAG_LOVEHATE,
"anycase" => FLAG_BOOLEAN_ANY_CASE,
"wildcard" => FLAG_WILDCARD,
"not" => FLAG_PURE_NOT,
"partial" => FLAG_PARTIAL
);
# Slots used for the sorting
my %slot_values = (
"date" => 0,
"severity" => 1,
"wnpp" => 2,
"package" => 3
);
print "Content-type: text/plain\r\n\r\n";
eval {
# Separation of the GET params
for (split /\&/, $ENV{QUERY_STRING}) {
# URL decode
s/\%([A-Fa-f0-9]{2})/pack('C', hex($1))/seg;
my ($key, $value) = split /=/;
# This params corresponds to a Xapian option
if(defined $flags_values{$key}) {
$flags |= $flags_values{$key};
# Sort param
} elsif($key eq "sort" && length($value) > 1 &&
(defined $slot_values{$value} || defined $slot_values{substr($value, 1)})) {
# Case of a reverse value (e.g. rdate)
if($value =~ /^r(\w+)/) {
$sort_by = $slot_values{$1};
$rsort = 1;
# Standard value
} else {
$sort_by = $slot_values{$value};
}
# Max param
} elsif($key eq "max" && $value =~ /\d+/) {
$max = $value;
# This is not an option is a query part
} elsif($key eq "q") {
$query_string = $value;
}
}
# If no Xapian option
$flags = FLAG_DEFAULT if !$flags;
my $database = Search::Xapian::Database->new($database_path);
my $enquire = Search::Xapian::Enquire->new($database);
my $qp = Search::Xapian::QueryParser->new();
$qp->set_database($database);
$qp->set_stemmer(Search::Xapian::Stem->new("english"));
$qp->set_stemming_strategy(STEM_SOME);
# Boolean filters
$qp->add_boolean_prefix("id", 'I');
$qp->add_boolean_prefix("fixed", 'F');
$qp->add_boolean_prefix("severity", 'S');
$qp->add_boolean_prefix("wnpp", 'W');
$qp->add_boolean_prefix("tag", 'T');
# Free text fields
$qp->add_prefix("author", 'A');
$qp->add_prefix("doneby", 'D');
$qp->add_prefix("package", 'P');
$qp->add_prefix("subject", 'S');
$qp->add_prefix("version", 'V');
# Set the date slot
my $vrpdate = new Search::Xapian::DateValueRangeProcessor(
$slot_values{"date"}, 1, 1920);
$qp->add_valuerangeprocessor($vrpdate);
# Request on the db and sorting
my $query = $qp->parse_query($query_string, $flags);
$enquire->set_query($query);
$enquire->set_sort_by_value($sort_by, $rsort) if defined $sort_by;
# Retrieve the $max first results
my $mset = $enquire->get_mset(0, $max);
my $msize = $mset->size();
my %result;
$result{"count"} = $mset->get_matches_estimated();
$result{"about"} = $mset->get_matches_lower_bound() != $mset->get_matches_upper_bound();
# For each bug found
foreach my $m ($mset->items()) {
my $data = $m->get_document()->get_data();
# Data format: [ID]Â [DATE] [SEVERITY] [FIXED] Subject
my ($id, $date, $severity, $fixed, $subject) =
$data =~ /^\[(\w*)\] \[([\w\/]*)\] \[([\w-]*)\] \[(\w*)\] (.+)$/;
# Inject the result in the final hash
push(@{$result{"results"}}, {
"percent" => $m->get_percent(),
"date" => $date,
"id" => $id,
"severity" => $severity,
"fixed" => $fixed,
"subject" => $subject
});
}
# JSON encoding
my $json = JSON->new->allow_nonref;
my $json_string = $json->encode(\%result);
print $json_string;
exit 0;
}; if($@) {
print STDERR "Exception: $@\n";
exit 1;
}
#!/usr/bin/perl
# bunny - Search in the Debian bugs database
#
# Copyright (C) 2011 Julien Vaubourg <julien@vaubourg.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
use strict;
use WWW::Mechanize;
use JSON -support_by_pp;
use Getopt::Long;
########## CONFIGURE:BEGIN ##########
# URL of the bunny-server
my $bunny_server = "http://localhost/cgi-bin/bunny-server.pl";
########### CONFIGURE:END ###########
# Encode strings to URL format
sub urlencode {
my $txt = shift @_;
$txt =~ s/([^A-Za-z0-9])/sprintf("%%%02X", ord($1))/seg;
return $txt;
}
# Options available
my %opt = (
"fixed" => undef,
"sort" => undef,
"wnpp" => [],
"tag" => [],
"severity" => [],
"max" => 10,
"id" => [],
"report" => undef,
"display" => undef,
"boolean" => 1,
"phrase" => 1,
"lovehate" => 1,
"anycase" => undef,
"wildcard" => 1,
"not" => undef,
"partial" => undef
);
# Options format
GetOptions(
'fixed!' => \$opt{"fixed"},
'use-sort=s' => \$opt{"sort"},
'wnpp=s' => \@{$opt{"wnpp"}},
'tag=s' => \@{$opt{"tag"}},
'severity=s' => \@{$opt{"tag"}},
'max=i' => \$opt{"max"},
'id=i' => \@{$opt{"id"}},
'report=i' => \$opt{"report"},
'display=s' => \$opt{"display"},
'x-boolean!' => \$opt{"boolean"},
'x-quoted-phrase!' => \$opt{"phrase"},
'x-lovehate!' => \$opt{"lovehate"},
'x-any-case-boolean!' => \$opt{"anycase"},
'x-wildcard!' => \$opt{"wildcard"},
'x-not!' => \$opt{"not"},
'x-partial!' => \$opt{"partial"}
);
my $browser = WWW::Mechanize->new();
# With --report option, the user just wants see a single bug report
if($opt{"report"}) {
eval {
my $url = "http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=".$opt{"report"};
# Download the bug report
$browser->get($url.";mbox=yes");
my $content = $browser->content();
# Remove all mail headers except From: To: Subject: and Date:
$content =~ s/^(From|To|Subject|Date):/[\1]/gm;
$content =~ s/^[^ :]+:[^\n]*\n(\h+[^\n]+\n)*//gsm;
$content =~ s/^\n*From [^@]+@[^\n]+\n\[(From|To|Subject|Date)\]/"\n\n".('=' x 80)."\n\n[${1}]"/gsme;
# Displays the report
print "BUG #".$opt{"report"};
print $content;
print "".('=' x 80)."\n$url\n";
}; if($@) {
print STDERR "Bug ID not found.\n";
exit 2;
}
# The user wants a research (no -r)
} else {
my @query;
# Form the query_string with options (&option=value)
foreach (keys(%opt)) {
if($_ !~ /id|fixed|wnpp|tag|severity|display/ && $opt{$_}) {
push(@query, urlencode($_)."=".urlencode($opt{$_}));
}
}
# Booleans filters are added on the Xapian syntax (option:value),
# directly in the Xapian query, for each value.
for (qw(id wnpp tag severity)) {
if(@{$opt{$_}} > 0) {
for my $value (@{$opt{$_}}) {
push(@ARGV, $_.":".$value)
}
}
}
# Fixed is the only boolean filter who can have just a single value
push(@ARGV, "fixed:".$opt{"fixed"}) if defined $opt{"fixed"};
# Complete url, with options and Xapian query
my $url = sprintf(
$bunny_server."?%s&q=%s",
join('&', @query),
urlencode(join(' ', @ARGV))
);
eval {
# Send the request
$browser->get($url);
my $content = $browser->content();
# Retrieve the json response
my $json = new JSON;
my %result = %{
$json->allow_nonref->utf8->relaxed->escape_slash->loose->allow_singlequote->allow_barekey->decode($content)
};
# If any bugs were found
if($result{"count"}) {
# Displays the counter header only if -d contains 'c'
# This is by default
if($opt{"display"} =~ /(c|^$)/) {
print "About " if $result{"about"};
print $result{"count"}." matching bugs found.\n";
print "--\n" if length($opt{"display"}) != 1;
}
# If the user doesn't want only the counter
if($opt{"display"} ne 'c') {
my $date_e = $opt{"display"} =~ /e/;
$opt{"display"} =~ s/[ce]//g;
# For each bug found
for (@{$result{"results"}}) {
# European date format (-d de)
if($date_e) {
%$_->{"date"} =~ s/(\d{4})\/(\d\d)\/(\d\d)/\3\/\2\/\1/;
}
# Shows percents (-d p) - default
printf(
length($opt{"display"}) != 1 ?
"%3u\% - " : "%u",
%$_->{"percent"}
) if $opt{"display"} =~ /(p|^$)/;
# Shows dates (-d d)
printf(
length($opt{"display"}) != 1 ?
"[%10s] " : "%s",
%$_->{"date"}
) if $opt{"display"} =~ /d/;
# Shows severities (-d s)
printf(
length($opt{"display"}) != 1 ?
"[%9s] " : "%s",
%$_->{"severity"}
) if $opt{"display"} =~ /s/;
# Shows fixed flags (-d f)
printf(
length($opt{"display"}) != 1 ?
"[%5s] " : "%s",
%$_->{"fixed"} ? "FIXED" : ""
) if $opt{"display"} =~ /f/;
# Shows IDs (-d i) - default
printf(
length($opt{"display"}) != 1 ?
"[#%-7u] " : "%u",
%$_->{"id"}
) if $opt{"display"} =~ /(i|^$)/;
# Shows topics (-d t) - default
print %$_->{"subject"} if $opt{"display"} =~ /(t|^$)/;
print "\n";
}
}
# No bug found
} else {
exit 1;
}
}; if($@) {
print STDERR "Database access error!\n";
exit 2;
}
}
exit 0;
__END__
=head1 NAME
bunny - Search in the Debian bugs database
=head1 SYNOPSIS
bunny [I<OPTIONS>] [I<QUERY>]
=head1 QUERY
I<QUERY> use the Xapian syntax. See the B<EXAMPLES> section.
=head2 Free text fields
B<author:*> - Bug's author
B<doneby:*> - Who fixed the bug
B<package:*> - Package concerned
B<subject:*> - Topic
B<version:*> - Package's version
=head1 OPTIONS
All booleans filters and xapian options can be negated (e.g. B<--fixed> and
B<--nofixed>).
=head2 Booleans filters
=over
=item -f, --fixed
Only fixed bugs.
Same as C<fixed:1>.
=item B<[>-id IDB<]...>
Only the bug #ID.
Same as C<id:*>.
=item B<[>-w|--wnpp I<ITA|ITP|O|RFA|RFH|RFP>B<]...>
Only specifics wnpp bugs.
Same as C<wnpp:*>.
=item B<[>-t|--tag I<TAG>B<]...>
Only I<TAG> related.
See B<http://www.debian.org/Bugs/Developer#tags>.
Same as C<tag:*>.
=item B<[>-s|--severity I<critical|grave|serious|important|normal|minor|wishlist>B<]...>
Only specific severity related.
Same as C<severity:*>.
=back
=head2 Format
=over
=item -r, --report I<ID>
View the bug report #I<ID>.
=item -u, --use-sort I<date|severity|wnpp|package>
Sort results.
To have reverse order: I<rdate|rseverity|rwnpp|rpackage>
=item -m, --max I<LIMIT>
Max results. Default 10.
=item -d, --display I<DISPLAY>
B<c> - Shows counter header
B<d> - Shows dates
B<e> - Shows date with DD/MM/YYYY format
B<f> - Shows the fixed tag
B<i> - Shows IDs
B<p> - Shows percents
B<s> - Shows severity tags
B<t> - Shows topics
Example: C<-d fistdepc>
By default if empty: B<pict>
=back
=head2 Xapian options
=over
=item -x-b, --x-boolean
Support C<AND>, C<OR>, etc and bracketed subexpressions.
=item -x-q, --x-quoted-phrase B<(default)>
Support quoted phrases.
=item -x-l, --x-lovehate B<(default)>
Support C<+> and C<->.
=item -x-a, --x-any-case-boolean
Support C<AND>, C<OR>, etc even if they aren't in ALLCAPS.
=item -x-w, --x-wildcard B<(default)>
Support right truncation (not on B<Booleans filters>).
=item -x-n, --x-not
Allow queries such as C<NOT debian>.
These require the use of a list of all bugs in the database which is
expensive, so this feature isn't enabled by default.
=item -x-p, --x-partial
Enable partial matching.
Partial matching causes the parser to treat the query as a "partially entered"
search. This will automatically treat the final word as a wildcarded match,
unless it is followed by whitespace, to produce more stable results from
interactive searches.
Currently B<--x-partial> doesn't do anything if the final word in the query has a
boolean filter prefix, or if it is in a phrase (either an explicitly quoted one,
or one implicitly generated by hyphens or other punctuation). It also doesn't do
anything if if the final word is part of a value range.
=back
=head1 EXAMPLES
bunny author:john severity:grave tag:sid version:3.5.13
bunny -x-n --nofixed package:iceweasel AND NOT author:john
bunny doneby:'john doe' 25/12/01..31/12/01
bunny package:'iceweasel*' it\'s embarassing
bunny -w ITP -w RFP -w O
bunny -r 421337 | less
=head1 EXIT STATUS
B<0> - Matching bugs found
B<1> - No matching bugs found
B<Others> - Error
=head1 AUTHOR
Julien Vaubourg E<lt>julien@vaubourg.comE<gt>
=head1 COPYRIGHT
Copyright (C) 2011 Julien Vaubourg <julien@vaubourg.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
=cut
BUNNY(1) User Contributed Perl Documentation BUNNY(1)
NNAAMMEE
bunny - Search in the Debian bugs database
SSYYNNOOPPSSIISS
bunny [_O_P_T_I_O_N_S] [_Q_U_E_R_Y]
QQUUEERRYY
_Q_U_E_R_Y use the Xapian syntax. See the EEXXAAMMPPLLEESS section.
FFrreeee tteexxtt ffiieellddss
aauutthhoorr::** - Bug's author
ddoonneebbyy::** - Who fixed the bug
ppaacckkaaggee::** - Package concerned
ssuubbjjeecctt::** - Topic
vveerrssiioonn::** - Package's version
OOPPTTIIOONNSS
All booleans filters and xapian options can be negated (e.g. ----ffiixxeedd
and ----nnooffiixxeedd).
BBoooolleeaannss ffiilltteerrss
-f, --fixed
Only fixed bugs.
Same as "fixed:1".
[[-id ID]]......
Only the bug #ID.
Same as "id:*".
[[-w|--wnpp _I_T_A_|_I_T_P_|_O_|_R_F_A_|_R_F_H_|_R_F_P]]......
Only specifics wnpp bugs.
Same as "wnpp:*".
[[-t|--tag _T_A_G]]......
Only _T_A_G related.
See hhttttpp::////wwwwww..ddeebbiiaann..oorrgg//BBuuggss//DDeevveellooppeerr##ttaaggss.
Same as "tag:*".
[[-s|--severity
_c_r_i_t_i_c_a_l_|_g_r_a_v_e_|_s_e_r_i_o_u_s_|_i_m_p_o_r_t_a_n_t_|_n_o_r_m_a_l_|_m_i_n_o_r_|_w_i_s_h_l_i_s_t]]......
Only specific severity related.
Same as "severity:*".
FFoorrmmaatt
-r, --report _I_D
View the bug report #_I_D.
-u, --use-sort _d_a_t_e_|_s_e_v_e_r_i_t_y_|_w_n_p_p_|_p_a_c_k_a_g_e
Sort results.
To have reverse order: _r_d_a_t_e_|_r_s_e_v_e_r_i_t_y_|_r_w_n_p_p_|_r_p_a_c_k_a_g_e
-m, --max _L_I_M_I_T
Max results. Default 10.
-d, --display _D_I_S_P_L_A_Y
cc - Shows counter header
dd - Shows dates
ee - Shows date with DD/MM/YYYY format
ff - Shows the fixed tag
ii - Shows IDs
pp - Shows percents
ss - Shows severity tags
tt - Shows topics
Example: "-d fistdepc"
By default if empty: ppiicctt
XXaappiiaann ooppttiioonnss
-x-b, --x-boolean
Support "AND", "OR", etc and bracketed subexpressions.
-x-q, --x-quoted-phrase ((ddeeffaauulltt))
Support quoted phrases.
-x-l, --x-lovehate ((ddeeffaauulltt))
Support "+" and "-".
-x-a, --x-any-case-boolean
Support "AND", "OR", etc even if they aren't in ALLCAPS.
-x-w, --x-wildcard ((ddeeffaauulltt))
Support right truncation (not on BBoooolleeaannss ffiilltteerrss).
-x-n, --x-not
Allow queries such as "NOT debian".
These require the use of a list of all bugs in the database which
is expensive, so this feature isn't enabled by default.
-x-p, --x-partial
Enable partial matching.
Partial matching causes the parser to treat the query as a
"partially entered" search. This will automatically treat the final
word as a wildcarded match, unless it is followed by whitespace, to
produce more stable results from interactive searches.
Currently ----xx--ppaarrttiiaall doesn't do anything if the final word in the
query has a boolean filter prefix, or if it is in a phrase (either
an explicitly quoted one, or one implicitly generated by hyphens or
other punctuation). It also doesn't do anything if if the final
word is part of a value range.
EEXXAAMMPPLLEESS
bunny author:john severity:grave tag:sid version:3.5.13
bunny -x-n --nofixed package:iceweasel AND NOT author:john
bunny doneby:'john doe' 25/12/01..31/12/01
bunny package:'iceweasel*' it\'s embarassing
bunny -w ITP -w RFP -w O
bunny -r 421337 | less
EEXXIITT SSTTAATTUUSS
00 - Matching bugs found
11 - No matching bugs found
OOtthheerrss - Error
AAUUTTHHOORR
Julien Vaubourg <julien@vaubourg.com>
CCOOPPYYRRIIGGHHTT
Copyright (C) 2011 Julien Vaubourg <julien@vaubourg.com>
This program is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation, either version 3 of the License, or (at your
option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program. If not, see <http://www.gnu.org/licenses/>.
perl v5.10.1 2011-08-01 BUNNY(1)
Reply to: