]> git.donarmstrong.com Git - debbugs.git/commitdiff
* Modularize out cgi_parameters; make it do default values and
authorDon Armstrong <don@volo>
Tue, 7 Nov 2006 11:14:26 +0000 (03:14 -0800)
committerDon Armstrong <don@volo>
Tue, 7 Nov 2006 11:14:26 +0000 (03:14 -0800)
   singletons
 * Redo pkgindex so that it supports indexing by a first value, and
   indicing results
 * Adapt versions.cgi and search.cgi to deal with the changes in
   cgi_parameters
 * Fix versions.cgi so that it deals properly with source packages

Debbugs/CGI.pm
cgi/pkgindex.cgi
cgi/search.cgi
cgi/version.cgi

index a38a6a79861749a726dd6f3c2f8d5772239eb954..5a4469143e0810aab68b58d64292794d6e67cb49 100644 (file)
@@ -34,6 +34,7 @@ use Params::Validate qw(validate_with :types);
 use Debbugs::Config qw(:config);
 use Mail::Address;
 use POSIX qw(ceil);
+use Storable qw(dclone);
 
 my %URL_PARAMS = ();
 
@@ -49,7 +50,7 @@ BEGIN{
                     html   => [qw(html_escape htmlize_bugs htmlize_packagelinks),
                                qw(maybelink htmlize_addresslinks),
                               ],
-                    util   => [qw(getparsedaddrs)]
+                    util   => [qw(getparsedaddrs cgi_parameters)]
                     #status => [qw(getbugstatus)],
                    );
      @EXPORT_OK = ();
@@ -150,6 +151,51 @@ sub html_escape{
      return HTML::Entities::encode_entities($string)
 }
 
+=head2 cgi_parameters
+
+     cgi_parameters
+
+Returns all of the cgi_parameters from a CGI script using CGI::Simple
+
+=cut
+
+sub cgi_parameters {
+     my %options = validate_with(params => \@_,
+                                spec   => {query   => {type => OBJECT,
+                                                       can  => 'param',
+                                                      },
+                                           single  => {type => ARRAYREF,
+                                                       default => [],
+                                                      },
+                                           default => {type => HASHREF,
+                                                       default => {},
+                                                      },
+                                          },
+                               );
+     my $q = $options{query};
+     my %single;
+     @single{@{$options{single}}} = (1) x @{$options{single}};
+     my %param;
+     for my $paramname ($q->param) {
+         if ($single{$paramname}) {
+              $param{$paramname} = $q->param($paramname);
+         }
+         else {
+              $param{$paramname} = [$q->param($paramname)];
+         }
+     }
+     for my $default (keys %{$options{default}}) {
+         if (not exists $param{$default}) {
+              # We'll clone the reference here to avoid surprises later.
+              $param{$default} = ref($options{default}{$default})?
+                   dclone($options{default}{$default}):$options{default}{$default};
+         }
+     }
+     return %param;
+}
+
+
+
 my %common_bugusertags;
 
 # =head2 get_bug_status
index 60860473840b47ca20364f75edab9f910979a6eb..c667aacab0e2d11905e2a9cd81b45f28347479ff 100755 (executable)
@@ -1,55 +1,64 @@
 #!/usr/bin/perl -wT
 
-package debbugs;
-
+use warnings;
 use strict;
-use POSIX qw(strftime tzset nice);
+use POSIX qw(strftime nice);
 
-#require '/usr/lib/debbugs/errorlib';
+use Debbugs::Config;
+use CGI::Simple;
+use Debbugs::CGI qw(cgi_parameters);
 require './common.pl';
 
-require '/etc/debbugs/config';
-require '/etc/debbugs/text';
-
 nice(5);
 
-my %param = readparse();
+my $q = new CGI::Simple;
+my %param = cgi_parameters(query   => $q,
+                          single  => [qw(indexon repeatmerged archive sortby),
+                                      qw(skip max_results first),
+                                     ],
+                          default => {indexon      => 'pkg',
+                                      repeatmerged => 'yes',
+                                      archive      => 'no',
+                                      sortby       => 'alpha',
+                                      skip         => 0,
+                                      max_results  => 100,
+                                     },
+                         );
+
+if (defined $param{first}) {
+     # rip out all non-words from first
+     $param{first} =~ s/\W//g;
+}
+if (defined $param{next}) {
+     $param{skip}+=$param{max_results};
+}
+elsif (defined $param{prev}) {
+     $param{skip}-=$param{max_results};
+     $param{skip} = 0 if $param{skip} < 0;
+}
 
-my $indexon = $param{'indexon'} || 'pkg';
-if ($indexon !~ m/^(pkg|src|maint|submitter|tag)$/) {
+my $indexon = $param{indexon};
+if ($param{indexon} !~ m/^(pkg|src|maint|submitter|tag)$/) {
     quitcgi("You have to choose something to index on");
 }
 
-my $repeatmerged = ($param{'repeatmerged'} || "yes") eq "yes";
-my $archive = ($param{'archive'} || "no") eq "yes";
-my $sortby = $param{'sortby'} || 'alpha';
+my $repeatmerged = $param{repeatmerged} eq 'yes';
+my $archive = $param{archive} eq "yes";
+my $sortby = $param{sortby};
 if ($sortby !~ m/^(alpha|count)$/) {
     quitcgi("Don't know how to sort like that");
 }
 
-#my $include = $param{'include'} || "";
-#my $exclude = $param{'exclude'} || "";
-
 my $Archived = $archive ? " Archived" : "";
 
 my %maintainers = %{&getmaintainers()};
 my %strings = ();
 
-$ENV{"TZ"} = 'UTC';
-tzset();
-
-my $dtime = strftime "%a, %e %b %Y %T UTC", localtime;
-my $tail_html = $debbugs::gHTMLTail;
-$tail_html = $debbugs::gHTMLTail;
+my $dtime = strftime "%a, %e %b %Y %T UTC", gmtime;
+my $tail_html = '';#$gHTMLTail;
+$tail_html = '';#$gHTMLTail;
 $tail_html =~ s/SUBSTITUTE_DTIME/$dtime/;
 
-set_option("repeatmerged", $repeatmerged);
-set_option("archive", $archive);
-#set_option("include", { map {($_,1)} (split /[\s,]+/, $include) })
-#      if ($include);
-#set_option("exclude", { map {($_,1)} (split /[\s,]+/, $exclude) })
-#      if ($exclude);
-
 my %count;
 my $tag;
 my $note;
@@ -58,6 +67,16 @@ my %sortkey = ();
 if ($indexon eq "pkg") {
   $tag = "package";
   %count = countbugs(sub {my %d=@_; return splitpackages($d{"pkg"})});
+  if (defined $param{first}) {
+       %count = map {
+           if (/^\Q$param{first}\E/) {
+                ($_,$count{$_});
+           }
+           else {
+                ();
+           } 
+       } keys %count;
+  }
   $note = "<p>Note that with multi-binary packages there may be other\n";
   $note .= "reports filed under the different binary package names.</p>\n";
   foreach my $pkg (keys %count) {
@@ -72,6 +91,16 @@ if ($indexon eq "pkg") {
 } elsif ($indexon eq "src") {
   $tag = "source package";
   my $pkgsrc = getpkgsrc();
+  if (defined $param{first}) {
+       %count = map {
+           if (/^\Q$param{first}\E/) {
+                ($_,$count{$_});
+           }
+           else {
+                ();
+           } 
+       } keys %count;
+  }
   %count = countbugs(sub {my %d=@_;
                           return map {
                             $pkgsrc->{$_} || $_
@@ -100,6 +129,16 @@ if ($indexon eq "pkg") {
                             map { $_->address } @me;
                           } splitpackages($d{"pkg"});
                          });
+  if (defined $param{first}) {
+       %count = map {
+           if (/^\Q$param{first}\E/) {
+                ($_,$count{$_});
+           }
+           else {
+                ();
+           } 
+       } keys %count;
+  }
   $note = "<p>Note that maintainers may use different Maintainer fields for\n";
   $note .= "different packages, so there may be other reports filed under\n";
   $note .= "different addresses.</p>\n";
@@ -118,6 +157,16 @@ if ($indexon eq "pkg") {
                           }
                           map { $_->address } @se;
                          });
+  if (defined $param{first}) {
+       %count = map {
+           if (/^\Q$param{first}\E/) {
+                ($_,$count{$_});
+           }
+           else {
+                ();
+           } 
+       } keys %count;
+  }
   foreach my $sub (keys %count) {
     $sortkey{$sub} = lc $fullname{$sub};
     $htmldescrip{$sub} = sprintf('<a href="%s">%s</a>',
@@ -130,6 +179,16 @@ if ($indexon eq "pkg") {
 } elsif ($indexon eq "tag") {
   $tag = "tag";
   %count = countbugs(sub {my %d=@_; return split ' ', $d{tags}; });
+  if (defined $param{first}) {
+       %count = map {
+           if (/^\Q$param{first}\E/) {
+                ($_,$count{$_});
+           }
+           else {
+                ();
+           } 
+       } keys %count;
+  }
   $note = "";
   foreach my $keyword (keys %count) {
     $sortkey{$keyword} = lc $keyword;
@@ -146,7 +205,13 @@ if ($sortby eq "count") {
 } else { # sortby alpha
   @orderedentries = sort { $sortkey{$a} cmp $sortkey{$b} } keys %count;
 }
+my $skip = $param{skip};
+my $max_results = $param{max_results};
 foreach my $x (@orderedentries) {
+     if (not defined $param{first}) {
+         $skip-- and next if $skip > 0;
+         last if --$max_results < 0;
+     }
   $result .= "<li>" . $htmldescrip{$x} . " has $count{$x} " .
             ($count{$x} == 1 ? "bug" : "bugs") . "</li>\n";
 }
@@ -164,6 +229,28 @@ print "<H1>" . "$debbugs::gProject$Archived $debbugs::gBug report logs by $tag"
       "</H1>\n";
 
 print $note;
+print <<END;
+<form>
+<input type="hidden" name="skip" value="$param{skip}">
+<input type="hidden" name="max_results" value="$param{max_results}">
+<input type="hidden" name="indexon" value="$param{indexon}">
+<input type="hidden" name="repeatmerged" value="$param{repeatmerged}">
+<input type="hidden" name="archive" value="$param{archive}">
+<input type="hidden" name="sortby" value="$param{sortby}">
+END
+if (defined $param{first}) {
+     print qq(<input type="hidden" name="first" value="$param{first}">\n);
+}
+else {
+     print q(<p>);
+     if ($param{skip} > 0) {
+         print q(<input type="submit" name="prev" value="Prev">);
+     }
+     if (keys %count > ($param{skip} + $param{max_results})) {
+         print q(<input type="submit" name="next" value="Next">);
+     }
+     print qq(</p>\n);
+}
 print $result;
 
 print "<hr>\n";
index 554b4ad5a1a618b2ada748bae15abb27ce14b248..d3f449ea16ee2b179d9640a9c20ba9e78fd65e42 100755 (executable)
@@ -19,19 +19,24 @@ use CGI::Alert 'don@donarmstrong.com';
 use Search::Estraier;
 use Debbugs::Config qw(:config);
 use Debbugs::Estraier;
-use Debbugs::CGI qw(htmlize_packagelinks html_escape);
+use Debbugs::CGI qw(htmlize_packagelinks html_escape cgi_parameters);
 use HTML::Entities qw(encode_entities);
 
 my $q = new CGI::Simple;
 
 #my %var_defaults = (attr => 1,);
 
-my %cgi_var = cgi_parameters($q);
+my %cgi_var = cgi_parameters(query => $q,
+                            single => [qw(phrase max_results order_field order_operator),
+                                       qw(skip prev next),
+                                      ],
+                            default => {phrase      => '',
+                                        max_results => 10,
+                                        skip        => 0,
+                                       }.
+                           );
 
-$cgi_var{phrase} = '' if not defined $cgi_var{phrase};
-$cgi_var{max_results} = 10 if not defined $cgi_var{max_results};
 $cgi_var{attribute} = parse_attribute(\%cgi_var) || [];
-$cgi_var{skip} = 0 if not defined $cgi_var{skip};
 
 my @results;
 
@@ -315,15 +320,3 @@ sub parse_attribute {
      }
      return \@attributes;
 }
-
-
-sub cgi_parameters {
-     my ($q) = @_;
-
-     my %param;
-     foreach my $paramname ($q->param) {
-         my @value = $q->param($paramname);
-         $param{$paramname} = @value > 1 ? [@value] : $value[0];
-     }
-     return %param;
-}
index e0471a389fb231cce49d9038f61acc1965d4fe36..d5ebf2856b6a74170a604a6364a6eb6e60fb71b6 100755 (executable)
@@ -17,33 +17,37 @@ use CGI::Simple;
 use CGI::Alert 'don@donarmstrong.com';
 
 use Debbugs::Config qw(:config);
-use Debbugs::CGI qw(htmlize_packagelinks html_escape);
+use Debbugs::CGI qw(htmlize_packagelinks html_escape cgi_parameters);
 use Debbugs::Versions;
 use Debbugs::Versions::Dpkg;
-use Debbugs::Packages qw(getversions);
+use Debbugs::Packages qw(getversions makesourceversions);
 use HTML::Entities qw(encode_entities);
 use File::Temp qw(tempdir);
 use IO::File;
 use IO::Handle;
 
 
+my %img_types = (svg => 'image/svg+xml',
+                png => 'image/png',
+               );
 
 my $q = new CGI::Simple;
 
-my %cgi_var = cgi_parameters($q);
-
-$cgi_var{package} = ['xterm'] if not defined $cgi_var{package};
-$cgi_var{found} = [] if not defined $cgi_var{found};
-$cgi_var{fixed} = [] if not defined $cgi_var{fixed};
-
-# we only care about one package
-$cgi_var{package} = $cgi_var{package}[0];
+my %cgi_var = cgi_parameters(query   => $q,
+                            single  => [qw(package format ignore_boring)],
+                            default => {package       => 'xterm',
+                                        found         => [],
+                                        fixed         => [],
+                                        ignore_boring => 1,
+                                        format        => 'png',
+                                       },
+                           );
 
 # we want to first load the appropriate file,
 # then figure out which versions are there in which architectures,
 my %versions;
 my %version_to_dist;
-for my $dist (qw(oldstable stable testing unstable)) {
+for my $dist (qw(oldstable stable testing unstable experimental)) {
      $versions{$dist} = [getversions($cgi_var{package},$dist)];
      # make version_to_dist
      foreach my $version (@{$versions{$dist}}){
@@ -51,11 +55,21 @@ for my $dist (qw(oldstable stable testing unstable)) {
      }
 }
 # then figure out which are affected.
-
-my $srchash = substr $cgi_var{package}, 0, 1;
+# turn found and fixed into full versions
+@{$cgi_var{found}} = makesourceversions($cgi_var{package},undef,@{$cgi_var{found}});
+@{$cgi_var{fixed}} = makesourceversions($cgi_var{package},undef,@{$cgi_var{fixed}});
+my @interesting_versions = makesourceversions($cgi_var{package},undef,keys %version_to_dist);
+
+# We need to be able to rip out leaves which the versions that do not affect the current versions of unstable/testing
+my %sources;
+@sources{map {m{(.+)/}; $1} @{$cgi_var{found}}} = (1) x @{$cgi_var{found}};
+@sources{map {m{(.+)/}; $1} @{$cgi_var{fixed}}} = (1) x @{$cgi_var{fixed}};
 my $version = Debbugs::Versions->new(\&Debbugs::Versions::Dpkg::vercmp);
-my $version_fh = new IO::File "$config{version_packages_dir}/$srchash/$cgi_var{package}", 'r';
-$version->load($version_fh);
+foreach my $source (keys %sources) {
+     my $srchash = substr $source, 0, 1;
+     my $version_fh = new IO::File "$config{version_packages_dir}/$srchash/$source", 'r';
+     $version->load($version_fh);
+}
 # Here, we need to generate a short version to full version map
 my %version_map;
 foreach my $key (keys %{$version->{parent}}) {
@@ -95,6 +109,9 @@ my %state = (found  => ['fillcolor="salmon"',
            );
 foreach my $key (keys %all_states) {
      my ($short_version) = $key =~ m{/(.+)$};
+     next if $cgi_var{ignore_boring} and (not defined $all_states{$key}
+                                         or $all_states{$key} eq 'absent');
+     next if $cgi_var{ignore_boring} and not version_relevant($version,$key,\@interesting_versions);
      my @attributes = @{$state{$all_states{$key}}};
      if (length $short_version and exists $version_to_dist{$short_version}) {
          push @attributes, 'label="'.$key.'\n'."(".join(', ',@{$version_to_dist{$short_version}}).")\"";
@@ -103,6 +120,12 @@ foreach my $key (keys %all_states) {
      $dot .= $node_attributes;
 }
 foreach my $key (keys %{$version->{parent}}) {
+     next if not defined $version->{parent}{$key};
+     next if $cgi_var{ignore_boring} and $all_states{$key} eq 'absent';
+     next if $cgi_var{ignore_boring} and (not defined $all_states{$version->{parent}{$key}}
+                                         or $all_states{$version->{parent}{$key}} eq 'absent');
+     # Ignore branches which are not ancestors of a currently distributed version
+     next if $cgi_var{ignore_boring} and not version_relevant($version,$key,\@interesting_versions);
      $dot .= qq("$key").'->'.qq("$version->{parent}{$key}" [dir="back"])."\n" if defined $version->{parent}{$key};
 }
 $dot .= "}\n";
@@ -114,25 +137,28 @@ if (not defined $cgi_var{dot}) {
          die "Unable to open $temp_dir/temp.dot for writing: $!";
      print {$dot_fh} $dot or die "Unable to print output to the dot file: $!";
      close $dot_fh or die "Unable to close the dot file: $!";
-     system('dot','-Tpng',"$temp_dir/temp.dot",'-o',"$temp_dir/temp.png") == 0
+     system('dot','-T'.$cgi_var{format},"$temp_dir/temp.dot",'-o',"$temp_dir/temp.$cgi_var{format}") == 0
          or print "Content-Type: text\n\nDot failed." and die "Dot failed: $?";
-     my $png_fh = new IO::File "$temp_dir/temp.png", 'r' or
-         die "Unable to open $temp_dir/temp.png for reading: $!";
-     print "Content-Type: image/png\n\n";
-     print <$png_fh>;
-     close $png_fh;
+     my $img_fh = new IO::File "$temp_dir/temp.$cgi_var{format}", 'r' or
+         die "Unable to open $temp_dir/temp.$cgi_var{format} for reading: $!";
+     print "Content-Type: $img_types{$cgi_var{format}}\n\n";
+     print <$img_fh>;
+     close $img_fh;
 }
 else {
      print "Content-Type: text\n\n";
      print $dot;
 }
 
-sub cgi_parameters {
-     my ($q) = @_;
 
-     my %param;
-     foreach my $paramname ($q->param) {
-         $param{$paramname} = [$q->param($paramname)]
+my %_version_relevant_cache;
+sub version_relevant {
+     my ($version,$test_version,$relevant_versions) = @_;
+     for my $dist_version (@{$relevant_versions}) {
+         print STDERR "Testing $dist_version against $test_version\n";
+         return 1 if $version->isancestor($test_version,$dist_version);
      }
-     return %param;
+     return 0;
 }
+
+