X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=cgi%2Fpkgreport.cgi;h=1f2294cf8449b5f00854811687fccba6cb60cc8b;hb=fa679d62cf5562f6206cf0f09cb36a05bb3f77b0;hp=86ebba632b7d6efbd56023d1822d44dde96b8798;hpb=dd5b9b25b5b477ca1b046492f461aeb796370f31;p=debbugs.git diff --git a/cgi/pkgreport.cgi b/cgi/pkgreport.cgi index 86ebba6..1f2294c 100755 --- a/cgi/pkgreport.cgi +++ b/cgi/pkgreport.cgi @@ -3,15 +3,17 @@ package debbugs; use strict; -use POSIX qw(strftime tzset nice); +use POSIX qw(strftime nice); -#require '/usr/lib/debbugs/errorlib'; require './common.pl'; -require '/etc/debbugs/config'; -require '/etc/debbugs/text'; +use Debbugs::Config qw(:globals :text); +use Debbugs::User; +use Debbugs::CGI qw(version_url); +use Debbugs::Common qw(getparsedaddrs); +use Debbugs::Bugs qw(get_bugs); -use vars qw($gPackagePages $gWebDomain); +use vars qw($gPackagePages $gWebDomain %gSeverityDisplay @gSeverityList); if (defined $ENV{REQUEST_METHOD} and $ENV{REQUEST_METHOD} eq 'HEAD') { print "Content-Type: text/html; charset=utf-8\n\n"; @@ -27,7 +29,18 @@ my $repeatmerged = ($param{'repeatmerged'} || "yes") eq "yes"; my $archive = ($param{'archive'} || "no") eq "yes"; my $include = $param{'&include'} || $param{'include'} || ""; my $exclude = $param{'&exclude'} || $param{'exclude'} || ""; + +my $users = $param{'users'} || ""; + +my $ordering = $param{'ordering'}; my $raw_sort = ($param{'raw'} || "no") eq "yes"; +my $old_view = ($param{'oldview'} || "no") eq "yes"; +unless (defined $ordering) { + $ordering = "normal"; + $ordering = "oldview" if $old_view; + $ordering = "raw" if $raw_sort; +} + my $bug_rev = ($param{'bug-rev'} || "no") eq "yes"; my $pend_rev = ($param{'pend-rev'} || "no") eq "yes"; my $sev_rev = ($param{'sev-rev'} || "no") eq "yes"; @@ -53,12 +66,6 @@ my $show_list_footer = ($param{'show_list_footer'} || $userAgent->{'show_list_fo } if ($vt eq "bypkg" || $vt eq "bysrc") { $dist = undef; $arch = undef; } } - if (defined $param{'ordering'}) { - my $o = $param{'ordering'}; - if ($o eq "raw") { $raw_sort = 1; $bug_rev = 0; } - if ($o eq "normal") { $raw_sort = 0; $bug_rev = 0; } - if ($o eq "reverse") { $raw_sort = 0; $bug_rev = 1; } - } if (defined $param{'includesubj'}) { my $is = $param{'includesubj'}; $include .= "," . join(",", map { "subj:$_" } (split /[\s,]+/, $is)); @@ -70,7 +77,41 @@ my $show_list_footer = ($param{'show_list_footer'} || $userAgent->{'show_list_fo } -my ($pkg, $src, $maint, $maintenc, $submitter, $severity, $status, $tag); +my %hidden = map { $_, 1 } qw(status severity classification); +my %cats = ( + "status" => [ { + "nam" => "Status", + "pri" => [map { "pending=$_" } + qw(pending forwarded pending-fixed fixed done absent)], + "ttl" => ["Outstanding","Forwarded","Pending Upload", + "Fixed in NMU","Resolved","From other Branch"], + "def" => "Unknown Pending Status", + "ord" => [0,1,2,3,4,5,6], + } ], + "severity" => [ { + "nam" => "Severity", + "pri" => [map { "severity=$_" } @gSeverityList], + "ttl" => [map { $gSeverityDisplay{$_} } @gSeverityList], + "def" => "Unknown Severity", + "ord" => [0..@gSeverityList], + } ], + "classification" => [ { + "nam" => "Classification", + "pri" => [qw(pending=pending+tag=wontfix + pending=pending+tag=moreinfo + pending=pending+tag=patch + pending=pending+tag=confirmed + pending=pending)], + "ttl" => ["Will Not Fix","More information needed", + "Patch Available","Confirmed"], + "def" => "Unclassified", + "ord" => [2,3,4,1,0,5], + } ], + "oldview" => [ qw(status severity) ], + "normal" => [ qw(status severity classification) ], +); + +my ($pkg, $src, $maint, $maintenc, $submitter, $severity, $status, $tag, $usertag); my %which = ( 'pkg' => \$pkg, @@ -80,6 +121,7 @@ my %which = ( 'submitter' => \$submitter, 'severity' => \$severity, 'tag' => \$tag, + 'usertag' => \$usertag, ); my @allowedEmpty = ( 'maint' ); @@ -113,6 +155,25 @@ if (!$found) { } quitcgi("You have to choose something to select by") if (!$found); +my %bugusertags; +my %ut; +for my $user (split /[\s*,]+/, $users) { + next unless ($user =~ m/..../); + add_user($user); +} + +if (defined $usertag) { + my %select_ut = (); + my ($u, $t) = split /:/, $usertag, 2; + Debbugs::User::read_usertags(\%select_ut, $u); + unless (defined $t && $t ne "") { + $t = join(",", keys(%select_ut)); + } + + add_user($u); + $tag = $t; +} + my $Archived = $archive ? " Archived" : ""; my $this = ""; @@ -120,10 +181,7 @@ my $this = ""; my %indexentry; my %strings = (); -$ENV{"TZ"} = 'UTC'; -tzset(); - -my $dtime = strftime "%a, %e %b %Y %T UTC", localtime; +my $dtime = strftime "%a, %e %b %Y %T UTC", gmtime; my $tail_html = $debbugs::gHTMLTail; $tail_html = $debbugs::gHTMLTail; $tail_html =~ s/SUBSTITUTE_DTIME/$dtime/; @@ -132,10 +190,6 @@ set_option("repeatmerged", $repeatmerged); set_option("archive", $archive); set_option("include", $include); set_option("exclude", $exclude); -set_option("raw", $raw_sort); -set_option("bug-rev", $bug_rev); -set_option("pend-rev", $pend_rev); -set_option("sev-rev", $sev_rev); set_option("pend-exc", $pend_exc); set_option("pend-inc", $pend_inc); set_option("sev-exc", $sev_exc); @@ -149,10 +203,38 @@ set_option("use-bug-idx", defined($param{'use-bug-idx'}) ? $param{'use-bug-idx'} set_option("show_list_header", $show_list_header); set_option("show_list_footer", $show_list_footer); +sub add_user { + my $ut = \%ut; + my $u = shift; + + my $user = Debbugs::User::get_user($u); + + my %vis = map { $_, 1 } @{$user->{"visible_cats"}}; + for my $c (keys %{$user->{"categories"}}) { + $cats{$c} = $user->{"categories"}->{$c}; + $hidden{$c} = 1 unless defined $vis{$c}; + } + + for my $t (keys %{$user->{"tags"}}) { + $ut->{$t} = [] unless defined $ut->{$t}; + push @{$ut->{$t}}, @{$user->{"tags"}->{$t}}; + } + + %bugusertags = (); + for my $t (keys %{$ut}) { + for my $b (@{$ut->{$t}}) { + $bugusertags{$b} = [] unless defined $bugusertags{$b}; + push @{$bugusertags{$b}}, $t; + } + } + set_option("bugusertags", \%bugusertags); +} + my $title; my @bugs; if (defined $pkg) { $title = "package $pkg"; + add_user("$pkg\@packages.debian.org"); if (defined $version) { $title .= " (version $version)"; } elsif (defined $dist) { @@ -161,13 +243,9 @@ if (defined $pkg) { $title .= " ($verdesc)" if defined $verdesc; } my @pkgs = split /,/, $pkg; - @bugs = @{getbugs(sub {my %d=@_; - foreach my $try (splitpackages($d{"pkg"})) { - return 1 if grep($try eq $_, @pkgs); - } - return 0; - }, 'package', @pkgs)}; + @bugs = get_bugs(package=>\@pkgs); } elsif (defined $src) { + add_user("$src\@packages.debian.org"); $title = "source $src"; set_option('arch', 'source'); if (defined $version) { @@ -177,46 +255,12 @@ if (defined $pkg) { my $verdesc = getversiondesc($src); $title .= " ($verdesc)" if defined $verdesc; } - my @pkgs = (); - my @srcs = split /,/, $src; - foreach my $try (@srcs) { - push @pkgs, getsrcpkgs($try); - push @pkgs, $try if ( !grep(/^\Q$try\E$/, @pkgs) ); - } - @bugs = @{getbugs(sub {my %d=@_; - foreach my $try (splitpackages($d{"pkg"})) { - return 1 if grep($try eq $_, @pkgs); - } - return 0; - }, 'package', @pkgs)}; + @bugs = get_bugs(src=>[split /,/, $src]); } elsif (defined $maint) { - my %maintainers = %{getmaintainers()}; + add_user($maint); $title = "maintainer $maint"; $title .= " in $dist" if defined $dist; - if ($maint eq "") { - @bugs = @{getbugs(sub {my %d=@_; - foreach my $try (splitpackages($d{"pkg"})) { - return 1 if !getparsedaddrs($maintainers{$try}); - } - return 0; - })}; - } else { - my @maints = split /,/, $maint; - my @pkgs = (); - foreach my $try (@maints) { - foreach my $p (keys %maintainers) { - my @me = getparsedaddrs($maintainers{$p}); - push @pkgs, $p if grep { $_->address eq $try } @me; - } - } - @bugs = @{getbugs(sub {my %d=@_; - foreach my $try (splitpackages($d{"pkg"})) { - my @me = getparsedaddrs($maintainers{$try}); - return 1 if grep { $_->address eq $maint } @me; - } - return 0; - }, 'package', @pkgs)}; - } + @bugs = get_bugs(maint=>[split /,/,$maint]); } elsif (defined $maintenc) { my %maintainers = %{getmaintainers()}; $title = "encoded maintainer $maintenc"; @@ -231,15 +275,11 @@ if (defined $pkg) { return 0; })}; } elsif (defined $submitter) { + add_user($submitter); $title = "submitter $submitter"; $title .= " in $dist" if defined $dist; my @submitters = split /,/, $submitter; - @bugs = @{getbugs(sub {my %d=@_; - my @se = getparsedaddrs($d{"submitter"} || ""); - foreach my $try (@submitters) { - return 1 if grep { $_->address eq $try } @se; - } - }, 'submitter-email', @submitters)}; + @bugs = get_bugs(submitter => \@submitters); } elsif (defined($severity) && defined($status)) { $title = "$status $severity bugs"; $title .= " in $dist" if defined $dist; @@ -260,11 +300,27 @@ if (defined $pkg) { $title = "bugs tagged $tag"; $title .= " in $dist" if defined $dist; my @tags = split /,/, $tag; + my %bugs = (); + for my $t (@tags) { + for my $b (@{$ut{$t}}) { + $bugs{$b} = 1; + } + } @bugs = @{getbugs(sub {my %d = @_; + return 1 if $bugs{$d{"bug"}}; my %tags = map { $_ => 1 } split ' ', $d{"tags"}; return grep(exists $tags{$_}, @tags); })}; } +$title = htmlsanit($title); + +my @names; my @prior; my @title; my @order; +determine_ordering(); + +# strip out duplicate bugs +my %bugs; +@bugs{@bugs} = @bugs; +@bugs = keys %bugs; my $result = pkg_htmlizebugs(\@bugs); @@ -272,18 +328,18 @@ print "Content-Type: text/html; charset=utf-8\n\n"; print "\n"; print "\n" . - "$debbugs::gProject$Archived $debbugs::gBug report logs: $title\n" . - '' . + "$gProject$Archived $gBug report logs: $title\n" . + qq() . "\n" . - '' . + '' . "\n"; -print "

" . "$debbugs::gProject$Archived $debbugs::gBug report logs: $title" . +print "

" . "$gProject$Archived $gBug report logs: $title" . "

\n"; my $showresult = 1; if (defined $pkg || defined $src) { - my $showpkg = (defined $pkg) ? $pkg : "source package $src"; + my $showpkg = htmlsanit((defined $pkg) ? $pkg : "source package $src"); my %maintainers = %{getmaintainers()}; my $maint = $pkg ? $maintainers{$pkg} : $maintainers{$src} ? $maintainers{$src} : undef; if (defined $maint) { @@ -322,30 +378,27 @@ if (defined $pkg || defined $src) { if ($pkg and defined($pseudodesc) and exists($pseudodesc->{$pkg})) { push @references, "to the list of other pseudo-packages"; } else { - if ($pkg and defined $debbugs::gPackagePages) { + if ($pkg and defined $gPackagePages) { push @references, sprintf "to the %s package page", urlsanit("http://${debbugs::gPackagePages}/$pkg"), htmlsanit("$pkg"); } - if (defined $debbugs::gSubscriptionDomain) { + if (defined $gSubscriptionDomain) { my $ptslink = $pkg ? $srcforpkg : $src; - push @references, "to the Package Tracking System"; + push @references, "to the Package Tracking System"; } # Only output this if the source listing is non-trivial. if ($pkg and $srcforpkg and (@pkgs or $pkg ne $srcforpkg)) { push @references, sprintf "to the source package %s's bug page", srcurl($srcforpkg), htmlsanit($srcforpkg); } } - if ($pkg) { - set_option("archive", !$archive); - push @references, sprintf "to the %s reports for %s", pkgurl($pkg), ($archive ? "active" : "archived"), htmlsanit($pkg); - set_option("archive", $archive); - } if (@references) { $references[$#references] = "or $references[$#references]" if @references > 1; print "

You might like to refer ", join(", ", @references), ".

\n"; } - print "

If you find a bug not listed here, please\n"; - printf "report it.

\n", - urlsanit("http://${debbugs::gWebDomain}/Reporting${debbugs::gHTMLSuffix}"); + if (defined $maint || defined $maintenc) { + print "

If you find a bug not listed here, please\n"; + printf "report it.

\n", + urlsanit("http://${debbugs::gWebDomain}/Reporting${debbugs::gHTMLSuffix}"); + } } else { print "

There is no record of the " . (defined($pkg) ? htmlsanit($pkg) . " package" @@ -363,9 +416,21 @@ if (defined $pkg || defined $src) { print "different addresses.\n"; } +set_option("archive", !$archive); +printf "

See the %s reports

", + urlsanit(pkg_url(( + map { + $_ eq 'archive'?():($_,$param{$_}) + } keys %param + ), + ('archive',($archive?"no":"yes")) + ) + ), ($archive ? "active" : "archived"); +set_option("archive", $archive); + print $result if $showresult; -print pkg_javascript(); +print pkg_javascript() . "\n"; print "

Options

\n"; print "
\n"; printf "
\n", myurl(); @@ -387,44 +452,86 @@ print ""; print " " . pkg_htmlselectsuite(1,2,1) . " for " . pkg_htmlselectarch(1,2,2) . "\n"; if (defined $pkg) { - my $v = $version || ""; + my $v = htmlsanit($version) || ""; + my $pkgsane = htmlsanit($pkg); print ""; - print " $pkg version \n"; + print " $pkgsane version \n"; } elsif (defined $src) { - my $v = $version || ""; + my $v = htmlsanit($version) || ""; + my $srcsane = htmlsanit($src); print ""; - print " $src version \n"; + print " $srcsane version \n"; } +print " \n"; -my $sel_rmy = ($repeatmerged ? " selected" : ""); -my $sel_rmn = ($repeatmerged ? "" : " selected"); -my $sel_ordraw = ($raw_sort ? " selected" : ""); -my $sel_ordnor = (!$raw_sort && !$bug_rev ? " selected" : ""); -my $sel_ordrev = (!$raw_sort && $bug_rev ? " selected" : ""); -my $includetags = join(" ", grep { !m/^subj:/i } split /[\s,]+/, $include); -my $excludetags = join(" ", grep { !m/^subj:/i } split /[\s,]+/, $exclude); -my $includesubj = join(" ", map { s/^subj://i; $_ } grep { m/^subj:/i } split /[\s,]+/, $include); -my $excludesubj = join(" ", map { s/^subj://i; $_ } grep { m/^subj:/i } split /[\s,]+/, $exclude); +my $includetags = htmlsanit(join(" ", grep { !m/^subj:/i } map {split /[\s,]+/} ref($include)?@{$include}:$include)); +my $excludetags = htmlsanit(join(" ", grep { !m/^subj:/i } map {split /[\s,]+/} ref($exclude)?@{$exclude}:$exclude)); +my $includesubj = htmlsanit(join(" ", map { s/^subj://i; $_ } grep { m/^subj:/i } map {split /[\s,]+/} ref($include)?@{$include}:$include)); +my $excludesubj = htmlsanit(join(" ", map { s/^subj://i; $_ } grep { m/^subj:/i } map {split /[\s,]+/} ref($exclude)?@{$exclude}:$exclude)); my $vismindays = ($mindays == 0 ? "" : $mindays); my $vismaxdays = ($maxdays == -1 ? "" : $maxdays); +my $sel_rmy = ($repeatmerged ? " selected" : ""); +my $sel_rmn = ($repeatmerged ? "" : " selected"); +my $sel_ordraw = ($ordering eq "raw" ? " selected" : ""); +my $sel_ordold = ($ordering eq "oldview" ? " selected" : ""); +my $sel_ordnor = ($ordering eq "normal" ? " selected" : ""); + +my $chk_bugrev = ($bug_rev ? " checked" : ""); +my $chk_pendrev = ($pend_rev ? " checked" : ""); +my $chk_sevrev = ($sev_rev ? " checked" : ""); + print <Display merged bugs +Only include bugs tagged with or that have in their subject +Exclude bugs tagged with or that have in their subject +Only show bugs older than days, and younger than days + +  + + +Merged bugs should be - -Order bugs by +Categorise bugs by - -Only include bugs tagged with or that have in their subject -Exclude bugs tagged with or that have in their subject -Only show bugs older than days, and younger than days + + + +EOF + +{ +my $any = 0; +my $o = $param{"ordering"} || ""; +for my $n (keys %cats) { + next if ($n eq "normal" || $n eq "oldview"); + next if defined $hidden{$n}; + unless ($any) { + $any = 1; + print "\n"; + } + my @names = map { ref($_) eq "HASH" ? $_->{"nam"} : $_ } @{$cats{$n}}; + my $name; + if (@names == 1) { $name = $names[0]; } + else { $name = " and " . pop(@names); $name = join(", ", @names) . $name; } + + printf "\n", + $n, ($o eq $n ? " selected" : ""), $name; +} +} + +print "\n"; + +printf "Order bugs by%s\n", + pkg_htmlselectyesno("pend-rev", "outstanding bugs first", "done bugs first", $pend_rev); +printf "%s\n", + pkg_htmlselectyesno("sev-rev", "highest severity first", "lowest severity first", $sev_rev); +printf "%s\n", + pkg_htmlselectyesno("bug-rev", "oldest bugs first", "newest bugs first", $bug_rev); + +print <  with new settings EOF @@ -455,19 +562,19 @@ sub pkg_htmlindexentrystatus { my $showversions = ''; if (@{$status{found_versions}}) { my @found = @{$status{found_versions}}; - local $_; - s{/}{ } foreach @found; - $showversions .= join ', ', map htmlsanit($_), @found; + $showversions .= join ', ', map {s{/}{ }; htmlsanit($_)} @found; } if (@{$status{fixed_versions}}) { $showversions .= '; ' if length $showversions; $showversions .= 'fixed: '; my @fixed = @{$status{fixed_versions}}; - local $_; - s{/}{ } foreach @fixed; - $showversions .= join ', ', map htmlsanit($_), @fixed; + $showversions .= join ', ', map {s{/}{ }; htmlsanit($_)} @fixed; } - $result .= " ($showversions)" if length $showversions; + $result .= ' ($showversions)} if length $showversions; $result .= ";\n"; $result .= $showseverity; @@ -480,28 +587,31 @@ sub pkg_htmlindexentrystatus { . "" if (length($status{tags})); - my @merged= split(/ /,$status{mergedwith}); - my $mseparator= ";\nMerged with "; - for my $m (@merged) { - $result .= $mseparator."#$m"; - $mseparator= ", "; - } + $result .= buglinklist(";\nMerged with ", ", ", + split(/ /,$status{mergedwith})); + $result .= buglinklist(";\nBlocked by ", ", ", + split(/ /,$status{blockedby})); + $result .= buglinklist(";\nBlocks ", ", ", + split(/ /,$status{blocks})); - my $days = 0; if (length($status{done})) { $result .= "
Done: " . htmlsanit($status{done}); - $days = ceil($debbugs::gRemoveAge - -M buglog($status{id})); + my $days = bug_archiveable(bug => $status{id}, + status => \%status, + days_until => 1, + ); if ($days >= 0) { $result .= ";\nWill be archived" . ( $days == 0 ? " today" : $days == 1 ? " in $days day" : " in $days days" ) . ""; - } else { - $result .= ";\nArchived"; } } unless (length($status{done})) { if (length($status{forwarded})) { $result .= ";\nForwarded to " - . maybelink($status{forwarded}); + . join(', ', + map {maybelink($_)} + split /[,\s]+/,$status{forwarded} + ); } my $daysold = int((time - $status{date}) / 86400); # seconds to days if ($daysold >= 7) { @@ -535,14 +645,13 @@ sub pkg_htmlindexentrystatus { sub pkg_htmlizebugs { $b = $_[0]; my @bugs = @$b; - my $anydone = 0; my @status = (); my %count; my $header = ''; my $footer = "

Summary

\n"; - my @dummy = ($debbugs::gRemoveAge, @debbugs::gSeverityList, @debbugs::gSeverityDisplay); #, $debbugs::gHTMLExpireNote); + my @dummy = ($gRemoveAge); #, @gSeverityList, @gSeverityDisplay); #, $gHTMLExpireNote); if (@bugs == 0) { return "

No reports found!

\n"; @@ -555,32 +664,10 @@ sub pkg_htmlizebugs { } my %seenmerged; - my @common_grouping = ( 'severity', 'pending' ); - my %common_grouping_order = ( - 'pending' => [ qw( pending forwarded pending-fixed fixed done absent ) ], - 'severity' => \@debbugs::gSeverityList, - ); - my %common_grouping_display = ( - 'pending' => 'Status', - 'severity' => 'Severity', - ); - my %common_headers = ( - 'pending' => { - "pending" => "outstanding", - "pending-fixed" => "pending upload", - "fixed" => "fixed in NMU", - "done" => "resolved", - "forwarded" => "forwarded to upstream software authors", - "absent" => "not applicable to this version", - }, - 'severity' => \%debbugs::gSeverityDisplay, - ); - my %common_reverse = ( 'pending' => $pend_rev, 'severity' => $sev_rev ); my %common = ( 'show_list_header' => 1, 'show_list_footer' => 1, ); - my $common_raw_sort = $raw_sort; my %section = (); @@ -592,79 +679,80 @@ sub pkg_htmlizebugs { my $html = sprintf "
  • #%d: %s\n
    ", bugurl($bug), $bug, htmlsanit($status{subject}); $html .= pkg_htmlindexentrystatus(\%status) . "\n"; - my $key = join( '_', map( {$status{$_}} @common_grouping ) ); + + my $key = ""; + for my $i (0..$#prior) { + my $v = get_bug_order_index($prior[$i], \%status); + $count{"g_${i}_${v}"}++; + $key .= "_$v"; + } $section{$key} .= $html; $count{"_$key"}++; - foreach my $grouping ( @common_grouping ) { - $count{"${grouping}_$status{$grouping}"}++; - } - $anydone = 1 if $status{pending} eq 'done'; + push @status, [ $bug, \%status, $html ]; } my $result = ""; - if ($common_raw_sort) { + if ($ordering eq "raw") { $result .= "
      \n" . join("", map( { $_->[ 2 ] } @status ) ) . "
    \n"; } else { - my (@order, @headers); - for( my $i = 0; $i < @common_grouping; $i++ ) { - my $grouping_name = $common_grouping[ $i ]; - my @items = @{ $common_grouping_order{ $grouping_name } }; - @items = reverse( @items ) if ( $common_reverse{ $grouping_name } ); - my @neworder = (); - my @newheaders = (); - if ( @order ) { - foreach my $grouping ( @items ) { - push @neworder, map( { "${_}_$grouping" } @order ); - push @newheaders, map( { "$_ - $common_headers{$grouping_name}{$grouping}" } @headers ); - } - @order = @neworder; - @headers = @newheaders; - } else { - push @order, @items; - push @headers, map( { $common_headers{$common_grouping[$i]}{$_} } @items ); - } - } - $header .= "
      \n
      "; - for ( my $i = 0; $i < @order; $i++ ) { - my $order = $order[ $i ]; + $header .= "
        \n
        \n"; + my @keys_in_order = (""); + for my $o (@order) { + push @keys_in_order, "X"; + while ((my $k = shift @keys_in_order) ne "X") { + for my $k2 (@{$o}) { + $k2+=0; + push @keys_in_order, "${k}_${k2}"; + } + } + } + for my $order (@keys_in_order) { next unless defined $section{$order}; + my @ttl = split /_/, $order; shift @ttl; + my $title = $title[0]->[$ttl[0]] . " bugs"; + if ($#ttl > 0) { + $title .= " -- "; + $title .= join("; ", grep {($_ || "") ne ""} + map { $title[$_]->[$ttl[$_]] } 1..$#ttl); + } + $title = htmlsanit($title); + my $count = $count{"_$order"}; my $bugs = $count == 1 ? "bug" : "bugs"; - $header .= "
      • $headers[$i] ($count $bugs)
      • \n"; - } - $header .= "
      \n"; - for ( my $i = 0; $i < @order; $i++ ) { - my $order = $order[ $i ]; - next unless defined $section{$order}; + + $header .= "
    • $title ($count $bugs)
    • \n"; if ($common{show_list_header}) { my $count = $count{"_$order"}; my $bugs = $count == 1 ? "bug" : "bugs"; - $result .= "

      $headers[$i] ($count $bugs)

      \n"; + $result .= "

      $title ($count $bugs)

      \n"; } else { - $result .= "

      $headers[$i]

      \n"; + $result .= "

      $title

      \n"; } $result .= "
      \n
        \n"; + $result .= "\n\n\n\n"; $result .= $section{$order}; + $result .= "\n\n\n\n"; $result .= "
      \n
      \n"; } + $header .= "
  • \n"; + $footer .= "\n"; } $result = $header . $result if ( $common{show_list_header} ); - #$result .= "

    " . $debbugs::gHTMLExpireNote if $debbugs::gRemoveAge and $anydone; $result .= $footer if ( $common{show_list_footer} ); return $result; } @@ -689,33 +777,70 @@ sub pkg_htmlpackagelinks { } sub pkg_htmladdresslinks { - my ($prefixfunc, $urlfunc, $addresses) = @_; - if (defined $addresses and $addresses ne '') { - my @addrs = getparsedaddrs($addresses); - my $prefix = (ref $prefixfunc) ? $prefixfunc->(scalar @addrs) - : $prefixfunc; - return $prefix . - join ', ', map { sprintf '%s', - $urlfunc->($_->address), - htmlsanit($_->format) || '(unknown)' - } @addrs; - } else { - my $prefix = (ref $prefixfunc) ? $prefixfunc->(1) : $prefixfunc; - return sprintf '%s(unknown)', $prefix, $urlfunc->(''); - } + htmlize_addresslinks(@_,'submitter'); } sub pkg_javascript { return <