use warnings;
use strict;
use vars qw($VERSION $DEBUG %EXPORT_TAGS @EXPORT_OK @EXPORT);
-use base qw(Exporter);
+use Exporter qw(import);
use IO::Scalar;
use Params::Validate qw(validate_with :types);
use Debbugs::Packages qw(:mapping);
use Debbugs::Text qw(:templates);
+use Encode qw(decode_utf8);
use POSIX qw(strftime);
},
bugs => {type => ARRAYREF,
},
+ schema => {type => OBJECT,
+ optional => 1,
+ },
},
);
my %pkgsrc = %{getpkgsrc()};
my $srcforpkg = $package;
- if ($param{binary} and exists $pkgsrc{$package}
- and defined $pkgsrc{$package}) {
- $srcforpkg = $pkgsrc{$package};
+ if ($param{binary}) {
+ $srcforpkg =
+ binary_to_source(source_only => 1,
+ scalar_only => 1,
+ binary => $package,
+ exists $param{schema}?(schema => $param{schema}):(),
+ );
}
my $showpkg = html_escape($package);
- my $maintainers = getmaintainers();
- my $maint = $maintainers->{$srcforpkg};
- if (defined $maint) {
+ my @maint = package_maintainer($param{binary}?'binary':'source',
+ $package
+ );
+ if (@maint) {
print {$output} '<p>';
- print {$output} (($maint =~ /,/)? "Maintainer for $showpkg is "
+ print {$output} (@maint > 1? "Maintainer for $showpkg is "
: "Maintainers for $showpkg are ") .
- package_links(maint => $maint);
+ package_links(maintainer => \@maint);
print {$output} ".</p>\n";
}
else {
my @references;
my $pseudodesc = getpseudodesc();
if ($package and defined($pseudodesc) and exists($pseudodesc->{$package})) {
- push @references, "to the <a href=\"http://$config{web_domain}/pseudo-packages$config{html_suffix}\">".
+ push @references, "to the <a href=\"$config{web_domain}/pseudo-packages$config{html_suffix}\">".
"list of other pseudo-packages</a>";
}
- elsif (not defined $maint and not @{$param{bugs}}) {
- # don't bother printing out this information, because it's
- # already present above.
- # print {$output} "<p>There is no record of the " . html_escape($package) .
- # ($param{binary} ? " package" : " source package") .
- # ", and no bugs have been filed against it.</p>";
- }
else {
if ($package and defined $config{package_pages} and length $config{package_pages}) {
push @references, sprintf "to the <a href=\"%s\">%s package page</a>",
- html_escape("http://$config{package_pages}/$package"), html_escape("$package");
+ html_escape("$config{package_pages}/$package"), html_escape("$package");
}
- if (defined $config{subscription_domain} and
- length $config{subscription_domain}) {
+ if (defined $config{package_tracking_domain} and
+ length $config{package_tracking_domain}) {
my $ptslink = $param{binary} ? $srcforpkg : $package;
# the pts only wants the source, and doesn't care about src: (#566089)
$ptslink =~ s/^src://;
- push @references, q(to the <a href="http://).html_escape("$config{subscription_domain}/$ptslink").q(">Package Tracking System</a>);
+ push @references, q(to the <a href=").html_escape("$config{package_tracking_domain}/$ptslink").q(">Package Tracking System</a>);
}
# Only output this if the source listing is non-trivial.
if ($param{binary} and $srcforpkg) {
$references[$#references] = "or $references[$#references]" if @references > 1;
print {$output} "<p>You might like to refer ", join(", ", @references), ".</p>\n";
}
- if (defined $maint) {
+ if (@maint) {
print {$output} "<p>If you find a bug not listed here, please\n";
printf {$output} "<a href=\"%s\">report it</a>.</p>\n",
- html_escape("http://$config{web_domain}/Reporting$config{html_suffix}");
+ html_escape("$config{web_domain}/Reporting$config{html_suffix}");
}
- return $output_scalar;
+ return decode_utf8($output_scalar);
}
dist => {type => SCALAR,
optional => 1,
},
+ schema => {type => OBJECT,
+ optional => 1,
+ },
}
);
my @bugs = @{$param{bugs}};
push @{$exclude{$key}}, split /\s*,\s*/, $value;
}
- foreach my $bug (@bugs) {
- my %status = %{get_bug_status(bug=>$bug,
- (exists $param{dist}?(dist => $param{dist}):()),
- bugusertags => $param{bugusertags},
- (exists $param{version}?(version => $param{version}):()),
- (exists $param{arch}?(arch => $param{arch}):(arch => $config{default_architectures})),
- )};
- next unless %status;
- next if bug_filter(bug => $bug,
- status => \%status,
- repeat_merged => $param{repeatmerged},
- seen_merged => \%seenmerged,
- (keys %include ? (include => \%include):()),
- (keys %exclude ? (exclude => \%exclude):()),
- );
-
- my $html = "<li>"; #<a href=\"%s\">#%d: %s</a>\n<br>",
- #bug_url($bug), $bug, html_escape($status{subject});
- $html .= short_bug_status_html(status => \%status,
- options => $param{options},
- ) . "\n";
- push @status, [ $bug, \%status, $html ];
+ my $binary_to_source_cache = {};
+ my $statuses =
+ get_bug_statuses(bug => \@bugs,
+ (map {exists $param{$_}?($_,$param{$_}):()}
+ qw(dist version schema bugusertags)
+ ),
+ (exists $param{arch}?(arch => $param{arch}):(arch => $config{default_architectures})),
+ binary_to_source_cache => $binary_to_source_cache,
+ );
+ for my $bug (sort {$a <=> $b} keys %{$statuses}) {
+ next unless %{$statuses->{$bug}};
+ next if bug_filter(bug => $bug,
+ status => $statuses->{$bug},
+ repeat_merged => $param{repeatmerged},
+ seen_merged => \%seenmerged,
+ (keys %include ? (include => \%include):()),
+ (keys %exclude ? (exclude => \%exclude):()),
+ );
+
+ my $html = "<li>"; #<a href=\"%s\">#%d: %s</a>\n<br>",
+ $html .= short_bug_status_html(status => $statuses->{$bug},
+ options => $param{options},
+ ) . "\n";
+ push @status, [ $bug, $statuses->{$bug}, $html ];
}
if ($param{bug_order} eq 'age') {
# MWHAHAHAHA
return $result;
}
+sub parse_order_statement_into_boolean {
+ my ($statement,$status,$tags) = @_;
+
+ if (not defined $tags) {
+ $tags = {map { $_, 1 } split / /, $status->{"tags"}
+ }
+ if defined $status->{"tags"};
+
+ }
+ # replace all + with &&
+ $statement =~ s/\+/&&/g;
+ # replace all , with ||
+ $statement =~ s/,/||/g;
+ $statement =~ s{([^\&\|\=]+) # field
+ =
+ ([^\&\|\=]+) # value
+ }{
+ my $ok = 0;
+ if ($1 eq 'tag') {
+ $ok = 1 if defined $tags->{$2};
+ } else {
+ $ok = 1 if defined $status->{$1} and
+ $status->{$1} eq $2;
+ }
+ $ok;
+ }exg;
+ # check that the parsed statement is just valid boolean statements
+ if ($statement =~ /^([01\(\)\&\|]+)$/) {
+ return eval "$1";
+ } else {
+ # this is an invalid boolean statement
+ return 0;
+ }
+}
+
sub get_bug_order_index {
my $order = shift;
my $status = shift;
- my $pos = -1;
-
- my %tags = ();
- %tags = map { $_, 1 } split / /, $status->{"tags"}
- if defined $status->{"tags"};
-
+ my $pos = 0;
+ my $tags = {map { $_, 1 } split / /, $status->{"tags"}
+ }
+ if defined $status->{"tags"};
for my $el (@${order}) {
- $pos++;
- my $match = 1;
- my $first_field = 1; # true if no previous fields have been
- # checked
- while ($el =~ /(?<joiner>^|\+|,)(?<field>[^=]+)=(?<value>[^=,\+]+)/g) {
- my ($j,$f,$v) = @+{qw(joiner field value)};
- my $isokay = 0;
- $isokay = 1 if (defined $status->{$f} and $v eq $status->{$f});
- $isokay = 1 if ($f eq "tag" && defined $tags{$v});
- if (defined $j and $j eq ',') {
- $match ||= $isokay;
- } else {
- $match &&= $isokay;
- }
- $first_field = 0;
- }
- # if there is a match, or if there were no fields to check,
- # this usertag matched.
- if ($match || $first_field) {
- return $pos;
- last;
- }
+ if (not length $el or
+ parse_order_statement_into_boolean($el,$status,$tags)
+ ) {
+ return $pos;
+ }
+ $pos++;
}
- return $pos + 1;
+ return $pos;
}
# sets: my @names; my @prior; my @title; my @order;