]> git.donarmstrong.com Git - debbugs.git/blobdiff - Debbugs/CGI/Pkgreport.pm
move Debbugs to lib
[debbugs.git] / Debbugs / CGI / Pkgreport.pm
diff --git a/Debbugs/CGI/Pkgreport.pm b/Debbugs/CGI/Pkgreport.pm
deleted file mode 100644 (file)
index e3dcc12..0000000
+++ /dev/null
@@ -1,654 +0,0 @@
-# This module is part of debbugs, and is released
-# under the terms of the GPL version 2, or any later version. See the
-# file README and COPYING for more information.
-#
-# [Other people have contributed to this file; their copyrights should
-# be listed here too.]
-# Copyright 2008 by Don Armstrong <don@donarmstrong.com>.
-
-
-package Debbugs::CGI::Pkgreport;
-
-=head1 NAME
-
-Debbugs::CGI::Pkgreport -- specific routines for the pkgreport cgi script
-
-=head1 SYNOPSIS
-
-
-=head1 DESCRIPTION
-
-
-=head1 BUGS
-
-None known.
-
-=cut
-
-use warnings;
-use strict;
-use vars qw($VERSION $DEBUG %EXPORT_TAGS @EXPORT_OK @EXPORT);
-use Exporter qw(import);
-
-use IO::Scalar;
-use Params::Validate qw(validate_with :types);
-
-use Debbugs::Collection::Bug;
-
-use Carp;
-use List::AllUtils qw(apply);
-
-use Debbugs::Config qw(:config :globals);
-use Debbugs::CGI qw(:url :html :util);
-use Debbugs::Common qw(:misc :util :date);
-use Debbugs::Status qw(:status);
-use Debbugs::Bugs qw(bug_filter);
-use Debbugs::Packages qw(:mapping);
-
-use Debbugs::Text qw(:templates);
-use Encode qw(decode_utf8);
-
-use POSIX qw(strftime);
-
-
-BEGIN{
-     ($VERSION) = q$Revision: 494 $ =~ /^Revision:\s+([^\s+])/;
-     $DEBUG = 0 unless defined $DEBUG;
-
-     @EXPORT = ();
-     %EXPORT_TAGS = (html => [qw(short_bug_status_html pkg_htmlizebugs),
-                            ],
-                    misc => [qw(generate_package_info),
-                             qw(determine_ordering),
-                            ],
-                   );
-     @EXPORT_OK = (qw());
-     Exporter::export_ok_tags(keys %EXPORT_TAGS);
-     $EXPORT_TAGS{all} = [@EXPORT_OK];
-}
-
-=head2 generate_package_info
-
-     generate_package_info($srcorbin,$package)
-
-Generates the informational bits for a package and returns it
-
-=cut
-
-sub generate_package_info{
-     my %param = validate_with(params => \@_,
-                              spec  => {binary => {type => BOOLEAN,
-                                                   default => 1,
-                                                  },
-                                        package => {type => SCALAR,#|ARRAYREF,
-                                                   },
-                                        options => {type => HASHREF,
-                                                   },
-                                        bugs    => {type => ARRAYREF,
-                                                   },
-                                        schema => {type => OBJECT,
-                                                   optional => 1,
-                                                  },
-                                       },
-                             );
-
-     my $output_scalar = '';
-     my $output = globify_scalar(\$output_scalar);
-
-     my $package = $param{package};
-
-     my %pkgsrc = %{getpkgsrc()};
-     my $srcforpkg = $package;
-     if ($param{binary}) {
-        $srcforpkg =
-            binary_to_source(source_only => 1,
-                             scalar_only => 1,
-                             binary => $package,
-                             hash_slice(%param,qw(schema)),
-                            );
-     }
-
-     my $showpkg = html_escape($package);
-     my @maint = package_maintainer($param{binary}?'binary':'source',
-                                   $package,
-                                   hash_slice(%param,qw(schema)),
-                                  );
-     if (@maint) {
-         print {$output} '<p>';
-         print {$output} (@maint > 1? "Maintainer for $showpkg is "
-                          : "Maintainers for $showpkg are ") .
-                               package_links(maintainer => \@maint);
-         print {$output} ".</p>\n";
-     }
-     else {
-         print {$output} "<p>There is no maintainer for $showpkg. ".
-              "This means that this package no longer exists (or never existed). ".
-                  "Please do not report new bugs against this package. </p>\n";
-     }
-     my @pkgs = source_to_binary(source => $srcforpkg,
-                                hash_slice(%param,qw(schema)),
-                                binary_only => 1,
-                                # if there are distributions, only bother to
-                                # show packages which are currently in a
-                                # distribution.
-                                @{$config{distributions}//[]} ?
-                                (dist => [@{$config{distributions}}]) : (),
-                               ) if defined $srcforpkg;
-     @pkgs = grep( !/^\Q$package\E$/, @pkgs );
-     if ( @pkgs ) {
-         @pkgs = sort @pkgs;
-         if ($param{binary}) {
-              print {$output} "<p>You may want to refer to the following packages that are part of the same source:\n";
-         }
-         else {
-              print {$output} "<p>You may want to refer to the following individual bug pages:\n";
-         }
-         #push @pkgs, $src if ( $src && !grep(/^\Q$src\E$/, @pkgs) );
-         print {$output} scalar package_links(package=>[@pkgs]);
-         print {$output} ".\n";
-     }
-     my @references;
-     my $pseudodesc = getpseudodesc();
-     if ($package and defined($pseudodesc) and exists($pseudodesc->{$package})) {
-         push @references, "to the <a href=\"$config{web_domain}/pseudo-packages$config{html_suffix}\">".
-              "list of other pseudo-packages</a>";
-     }
-     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("$config{package_pages}/$package"), html_escape("$package");
-         }
-         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=").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) {
-              push @references,
-                   "to the source package ".
-                        package_links(src=>$srcforpkg,
-                                      options => $param{options}) .
-                             "'s bug page";
-         }
-     }
-     if (@references) {
-         $references[$#references] = "or $references[$#references]" if @references > 1;
-         print {$output} "<p>You might like to refer ", join(", ", @references), ".</p>\n";
-     }
-     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("$config{web_domain}/Reporting$config{html_suffix}");
-     }
-     return decode_utf8($output_scalar);
-}
-
-
-=head2 short_bug_status_html
-
-     print short_bug_status_html(status => read_bug(bug => 5),
-                                 options => \%param,
-                                );
-
-=over
-
-=item status -- status hashref as returned by read_bug
-
-=item options -- hashref of options to pass to package_links (defaults
-to an empty hashref)
-
-=item bug_options -- hashref of options to pass to bug_links (default
-to an empty hashref)
-
-=item snippet -- optional snippet of information about the bug to
-display below
-
-
-=back
-
-
-
-=cut
-
-sub short_bug_status_html {
-     my %param = validate_with(params => \@_,
-                              spec   => {bug => {type => OBJECT,
-                                                 isa => 'Debbugs::Bug',
-                                                },
-                                        },
-                             );
-
-     return fill_in_template(template => 'cgi/short_bug_status',
-                            variables => {bug => $param{bug},
-                                          isstrongseverity => \&Debbugs::Status::isstrongseverity,
-                                          html_escape   => \&Debbugs::CGI::html_escape,
-                                          looks_like_number => \&Scalar::Util::looks_like_number,
-                                         },
-                            hole_var  => {'&package_links' => \&Debbugs::CGI::package_links,
-                                          '&bug_links'     => \&Debbugs::CGI::bug_links,
-                                          '&version_url'   => \&Debbugs::CGI::version_url,
-                                          '&secs_to_english' => \&Debbugs::Common::secs_to_english,
-                                          '&strftime'      => \&POSIX::strftime,
-                                          '&maybelink'     => \&Debbugs::CGI::maybelink,
-                                         },
-                           );
-}
-
-
-sub pkg_htmlizebugs {
-     my %param = validate_with(params => \@_,
-                              spec   => {bugs => {type => OBJECT,
-                                                 },
-                                         names => {type => ARRAYREF,
-                                                  },
-                                         title => {type => ARRAYREF,
-                                                  },
-                                         prior => {type => ARRAYREF,
-                                                  },
-                                         order => {type => ARRAYREF,
-                                                  },
-                                         ordering => {type => SCALAR,
-                                                     },
-                                         bugusertags => {type => HASHREF,
-                                                         default => {},
-                                                        },
-                                         bug_rev => {type => BOOLEAN,
-                                                     default => 0,
-                                                    },
-                                         bug_order => {type => SCALAR,
-                                                      },
-                                         repeatmerged => {type => BOOLEAN,
-                                                          default => 1,
-                                                         },
-                                         include => {type => ARRAYREF,
-                                                     default => [],
-                                                    },
-                                         exclude => {type => ARRAYREF,
-                                                     default => [],
-                                                    },
-                                         this     => {type => SCALAR,
-                                                      default => '',
-                                                     },
-                                         options  => {type => HASHREF,
-                                                      default => {},
-                                                     },
-                                         dist     => {type => SCALAR,
-                                                      optional => 1,
-                                                     },
-                                         schema   => {type => OBJECT,
-                                                      optional => 1,
-                                                     },
-                                        }
-                             );
-     my $bugs = $param{bugs};
-     my %count;
-     my $header = '';
-     my $footer = "<h2 class=\"outstanding\">Summary</h2>\n";
-
-     if ($bugs->count == 0) {
-         return "<HR><H2>No reports found!</H2></HR>\n";
-     }
-
-     my %seenmerged;
-
-     my %common = (
-                  'show_list_header' => 1,
-                  'show_list_footer' => 1,
-                 );
-
-     my %section = ();
-     # Make the include/exclude map
-     my %include;
-     my %exclude;
-     for my $include (make_list($param{include})) {
-         next unless defined $include;
-         my ($key,$value) = split /\s*:\s*/,$include,2;
-         unless (defined $value) {
-              $key = 'tags';
-              $value = $include;
-         }
-         push @{$include{$key}}, split /\s*,\s*/, $value;
-     }
-     for my $exclude (make_list($param{exclude})) {
-         next unless defined $exclude;
-         my ($key,$value) = split /\s*:\s*/,$exclude,2;
-         unless (defined $value) {
-              $key = 'tags';
-              $value = $exclude;
-         }
-         push @{$exclude{$key}}, split /\s*,\s*/, $value;
-     }
-
-     my $sorter = sub {$_[0]->id <=> $_[1]->id};
-     if ($param{bug_rev}) {
-        $sorter = sub {$_[1]->id <=> $_[0]->id}
-     }
-     elsif ($param{bug_order} eq 'age') {
-        $sorter = sub {$_[0]->modified->epoch <=> $_[1]->modified->epoch};
-     }
-     elsif ($param{bug_order} eq 'agerev') {
-        $sorter = sub {$_[1]->modified->epoch <=> $_[0]->modified->epoch};
-     }
-     my @status;
-     for my $bug ($bugs->sort($sorter)) {
-        next if
-            $bug->filter(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(bug => $bug,
-                                      ) . "\n";
-        push @status, [ $bug, $html ];
-     }
-     # parse bug order indexes into subroutines
-     my @order_subs =
-        map {
-            my $a = $_;
-            [map {parse_order_statement_to_subroutine($_)} @{$a}];
-        } @{$param{prior}};
-     for my $entry (@status) {
-         my $key = "";
-         for my $i (0..$#order_subs) {
-              my $v = get_bug_order_index($order_subs[$i], $entry->[0]);
-              $count{"g_${i}_${v}"}++;
-              $key .= "_$v";
-         }
-         $section{$key} .= $entry->[1];
-         $count{"_$key"}++;
-     }
-
-     my $result = "";
-     if ($param{ordering} eq "raw") {
-         $result .= "<UL class=\"bugs\">\n" . join("", map( { $_->[ 1 ] } @status ) ) . "</UL>\n";
-     }
-     else {
-         $header .= "<div class=\"msgreceived\">\n<ul>\n";
-         my @keys_in_order = ("");
-         for my $o (@{$param{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 = $param{title}[0]->[$ttl[0]] . " bugs";
-              if ($#ttl > 0) {
-                   $title .= " -- ";
-                   $title .= join("; ", grep {($_ || "") ne ""}
-                                  map { $param{title}[$_]->[$ttl[$_]] } 1..$#ttl);
-              }
-              $title = html_escape($title);
-
-              my $count = $count{"_$order"};
-              my $bugs = $count == 1 ? "bug" : "bugs";
-
-              $header .= "<li><a href=\"#$order\">$title</a> ($count $bugs)</li>\n";
-              if ($common{show_list_header}) {
-                   my $count = $count{"_$order"};
-                   my $bugs = $count == 1 ? "bug" : "bugs";
-                   $result .= "<H2 CLASS=\"outstanding\"><a name=\"$order\"></a>$title ($count $bugs)</H2>\n";
-              }
-              else {
-                   $result .= "<H2 CLASS=\"outstanding\">$title</H2>\n";
-              }
-              $result .= "<div class=\"msgreceived\">\n<UL class=\"bugs\">\n";
-              $result .= "\n\n\n\n";
-              $result .= $section{$order};
-              $result .= "\n\n\n\n";
-              $result .= "</UL>\n</div>\n";
-         } 
-         $header .= "</ul></div>\n";
-
-         $footer .= "<div class=\"msgreceived\">\n<ul>\n";
-         for my $i (0..$#{$param{prior}}) {
-              my $local_result = '';
-              foreach my $key ( @{$param{order}[$i]} ) {
-                   my $count = $count{"g_${i}_$key"};
-                   next if !$count or !$param{title}[$i]->[$key];
-                   $local_result .= "<li>$count $param{title}[$i]->[$key]</li>\n";
-              }
-              if ( $local_result ) {
-                   $footer .= "<li>$param{names}[$i]<ul>\n$local_result</ul></li>\n";
-              }
-         }
-         $footer .= "</ul>\n</div>\n";
-     }
-
-     $result = $header . $result if ( $common{show_list_header} );
-     $result .= $footer if ( $common{show_list_footer} );
-     return $result;
-}
-
-sub parse_order_statement_to_subroutine {
-    my ($statement) = @_;
-    if (not defined $statement or not length $statement) {
-       return sub {return 1};
-    }
-    croak "invalid statement '$statement'" unless
-       $statement =~ /^(?:(package|tag|pending|severity) # field
-                          = # equals
-                          ([^=|\&,\+]+(?:,[^=|\&,+])*) #value
-                          (\+|,|$) # joiner or end
-                      )+ # one or more of these statements
-                     /x;
-    my @sub_bits;
-    while ($statement =~ /(?<joiner>^|,|\+) # joiner
-                         (?<field>package|tag|pending|severity) # field
-                          = # equals
-                          (?<value>[^=|\&,\+]+(?:,[^=|\&,\+])*) #value
-                        /xg) {
-       my $field = $+{field};
-       my $value = $+{value};
-       my $joiner = $+{joiner} // '';
-       my @vals = apply {quotemeta($_)} split /,/,$value;
-       if (length $joiner) {
-           if ($joiner eq '+') {
-               push @sub_bits, ' and ';
-           }
-           else {
-               push @sub_bits, ' or ';
-           }
-       }
-       my @vals_bits;
-       for my $val (@vals) {
-           if ($field =~ /package|severity/o) {
-               push @vals_bits, '$_[0]->status->'.$field.
-                   ' eq q('.$val.')';
-           } elsif ($field eq 'tag') {
-               push @vals_bits, '$_[0]->tags->is_set('.
-                   'q('.$val.'))';
-           } elsif ($field eq 'pending') {
-               push @vals_bits, '$_[0]->'.$field.
-                   ' eq q('.$val.')';
-           }
-       }
-       push @sub_bits ,' ('.join(' or ',@vals_bits).') ';
-    }
-    # return a subroutine reference which determines whether an order statement
-    # matches this bug
-    my $sub = 'sub { return ('.join ("\n",@sub_bits).');};';
-    my $subref = eval $sub;
-    if ($@) {
-       croak "Unable to generate subroutine: $@; $sub";
-    }
-    return $subref;
-}
-
-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,$bug) = @_;
-    my $pos = 0;
-    for my $el (@{$order}) {
-       if ($el->($bug)) {
-           return $pos;
-        }
-        $pos++;
-     }
-     return $pos;
-}
-
-# sets: my @names; my @prior; my @title; my @order;
-
-sub determine_ordering {
-     my %param = validate_with(params => \@_,
-                             spec => {cats => {type => HASHREF,
-                                              },
-                                      param => {type => HASHREF,
-                                               },
-                                      ordering => {type => SCALARREF,
-                                                  },
-                                      names    => {type => ARRAYREF,
-                                                  },
-                                      pend_rev => {type => BOOLEAN,
-                                                   default => 0,
-                                                  },
-                                      sev_rev  => {type => BOOLEAN,
-                                                   default => 0,
-                                                  },
-                                      prior    => {type => ARRAYREF,
-                                                  },
-                                      title    => {type => ARRAYREF,
-                                                  },
-                                      order    => {type => ARRAYREF,
-                                                  },
-                                     },
-                            );
-     $param{cats}{status}[0]{ord} = [ reverse @{$param{cats}{status}[0]{ord}} ]
-         if ($param{pend_rev});
-     $param{cats}{severity}[0]{ord} = [ reverse @{$param{cats}{severity}[0]{ord}} ]
-         if ($param{sev_rev});
-
-     my $i;
-     if (defined $param{param}{"pri0"}) {
-         my @c = ();
-         $i = 0;
-         while (defined $param{param}{"pri$i"}) {
-              my $h = {};
-
-              my ($pri) = make_list($param{param}{"pri$i"});
-              if ($pri =~ m/^([^:]*):(.*)$/) {
-                   $h->{"nam"} = $1; # overridden later if necesary
-                   $h->{"pri"} = [ map { "$1=$_" } (split /,/, $2) ];
-              }
-              else {
-                   $h->{"pri"} = [ split /,/, $pri ];
-              }
-
-              ($h->{"nam"}) = make_list($param{param}{"nam$i"})
-                   if (defined $param{param}{"nam$i"});
-              $h->{"ord"} = [ map {split /\s*,\s*/} make_list($param{param}{"ord$i"}) ]
-                   if (defined $param{param}{"ord$i"});
-              $h->{"ttl"} = [ map {split /\s*,\s*/} make_list($param{param}{"ttl$i"}) ]
-                   if (defined $param{param}{"ttl$i"});
-
-              push @c, $h;
-              $i++;
-         }
-         $param{cats}{"_"} = [@c];
-         ${$param{ordering}} = "_";
-     }
-
-     ${$param{ordering}} = "normal" unless defined $param{cats}{${$param{ordering}}};
-
-     sub get_ordering {
-         my @res;
-         my $cats = shift;
-         my $o = shift;
-         for my $c (@{$cats->{$o}}) {
-              if (ref($c) eq "HASH") {
-                   push @res, $c;
-              }
-              else {
-                   push @res, get_ordering($cats, $c);
-              }
-         }
-         return @res;
-     }
-     my @cats = get_ordering($param{cats}, ${$param{ordering}});
-
-     sub toenglish {
-         my $expr = shift;
-         $expr =~ s/[+]/ and /g;
-         $expr =~ s/[a-z]+=//g;
-         return $expr;
-     }
-     $i = 0;
-     for my $c (@cats) {
-         $i++;
-         push @{$param{prior}}, $c->{"pri"};
-         push @{$param{names}}, ($c->{"nam"} || "Bug attribute #" . $i);
-         if (defined $c->{"ord"}) {
-              push @{$param{order}}, $c->{"ord"};
-         }
-         else {
-              push @{$param{order}}, [ 0..$#{$param{prior}[-1]} ];
-         }
-         my @t = @{ $c->{"ttl"} } if defined $c->{ttl};
-         if (@t < $#{$param{prior}[-1]}) {
-              push @t, map { toenglish($param{prior}[-1][$_]) } @t..($#{$param{prior}[-1]});
-         }
-         push @t, $c->{"def"} || "";
-         push @{$param{title}}, [@t];
-     }
-}
-
-
-
-
-1;
-
-
-__END__
-
-
-
-
-
-