X-Git-Url: https://git.deb.at/?p=deb%2Fpackages.git;a=blobdiff_plain;f=lib%2FPackages%2FDoSearchContents.pm;h=debbbb2a93e28539aef61f66556ae17871080c85;hp=1a51ba3d445eb28c2f697ce5dd80a46e06e61d83;hb=e2881c2279414d845cb0b21b5e2661924194cb77;hpb=06c6f30bfc4f55cecc7485fef0f0a227e32b44f0 diff --git a/lib/Packages/DoSearchContents.pm b/lib/Packages/DoSearchContents.pm index 1a51ba3..debbbb2 100644 --- a/lib/Packages/DoSearchContents.pm +++ b/lib/Packages/DoSearchContents.pm @@ -14,13 +14,12 @@ our @EXPORT = qw( do_search_contents ); use Deb::Versions; use Packages::I18N::Locale; use Packages::Search qw( :all ); -use Packages::CGI; +use Packages::CGI qw( :DEFAULT error ); use Packages::DB; -use Packages::Config qw( $DBDIR $SEARCH_URL $SEARCH_PAGE - @SUITES @ARCHIVES @ARCHITECTURES $ROOT ); +use Packages::Config qw( $DBDIR @SUITES @ARCHIVES @ARCHITECTURES $ROOT ); sub do_search_contents { - my ($params, $opts, $html_header, $menu, $page_content) = @_; + my ($params, $opts, $page_content) = @_; if ($params->{errors}{keywords}) { fatal_error( _g( "keyword not valid or missing" ) ); @@ -35,33 +34,19 @@ sub do_search_contents { #FIXME: that's extremely hacky atm if ($params->{values}{suite}{no_replace}[0] eq 'default') { $params->{values}{suite}{no_replace} = - $params->{values}{suite}{final} = $opts->{suite} = [ 'stable' ]; + $params->{values}{suite}{final} = $opts->{suite} = [ 'etch' ]; } if (@{$opts->{suite}} > 1) { fatal_error( sprintf( _g( "more than one suite specified for contents search (%s)" ), "@{$opts->{suite}}" ) ); } - $$menu = ""; - my @keywords = @{$opts->{keywords}}; my $mode = $opts->{mode} || ''; my $suite = $opts->{suite}[0]; my $archive = $opts->{archive}[0] ||''; $Packages::Search::too_many_hits = 0; - # for URL construction - my $keyword_esc = uri_escape( "@keywords" ); - my $suites_param = join ',', @{$params->{values}{suite}{no_replace}}; - my $sections_param = join ',', @{$params->{values}{section}{no_replace}}; - my $archs_param = join ',', @{$params->{values}{arch}{no_replace}}; - - # for output - my $keyword_enc = encode_entities "@keywords" || ''; - my $suites_enc = encode_entities( join( ', ', @{$params->{values}{suite}{no_replace}} ), '&<>"' ); - my $sections_enc = encode_entities( join( ', ', @{$params->{values}{section}{no_replace}} ), '&<>"' ); - my $archs_enc = encode_entities( join( ', ', @{$params->{values}{arch}{no_replace}} ), '&<>"' ); - my $st0 = new Benchmark; my (@results); @@ -90,6 +75,7 @@ sub do_search_contents { &searchfile(\@results, reverse($_)."/", \$nres, $reverses); last if $Packages::Search::too_many_hits; } + while () {}; close FILENAMES or warn "fgrep error: $!\n"; } else { @@ -97,7 +83,8 @@ sub do_search_contents { if @keywords; my $kw = reverse $first_kw; - + $kw =~ s{/+$}{}; + # exact filename searching follows trivially: $kw = "$kw/" if $mode eq 'exactfilename'; @@ -106,65 +93,12 @@ sub do_search_contents { $reverses = undef; untie %reverses; - + my $st1 = new Benchmark; my $std = timediff($st1, $st0); debug( "Search took ".timestr($std) ) if DEBUG; } - - my $suite_wording = sprintf(_g("suite %s"), $suites_enc ); - my $section_wording = $sections_enc eq 'all' ? _g("all sections") - : sprintf(_g("section(s) %s"), $sections_enc ); - my $arch_wording = $archs_enc eq 'any' ? _g("all architectures") - : sprintf(_g("architecture(s) %s"), $archs_enc ); - my $wording = _g("paths that end with"); - if ($mode eq 'filename') { - $wording = _g("files named"); - } elsif ($mode eq 'exactfilename') { - $wording = _g("filenames that contain"); - } - msg( sprintf( _g("You have searched for %s %s in %s, %s, and %s." ), - $wording, $keyword_enc, - $suite_wording, $section_wording, $arch_wording ) ); - - if ($mode ne 'filename') { - msg( ''filename'}). - "\">"._g("Search within filenames").""); - } - if ($mode ne 'exactfilename') { - msg( ''exactfilename'}). - "\">"._g("Search exact filename").""); - } - if ($mode eq 'exactfilename' || $mode eq 'filename') { - msg( 'undef}). - "\">"._g("Search for paths ending with").""); - } - msg( _g("Search in other suite:")." ". - join( ' ', map { '[$_}). - "\">$_]" } @SUITES ) ); - - if ($Packages::Search::too_many_hits) { - error( _g( "Your search was too wide so we will only display only the first about 100 matches. Please consider using a longer keyword or more keywords." ) ); - } - - %$html_header = ( title => _g( 'Package Contents Search Results' ), - lang => $opts->{lang}, - title_tag => _g( 'Debian Package Contents Search Results' ), - print_title => 1, - print_search_field => 'packages', - search_field_values => { - keywords => $keyword_enc, - searchon => 'contents', - arch => $archs_enc, - suite => $suites_enc, - section => $sections_enc, - exact => $opts->{exact}, - debug => $opts->{debug}, - }, - ); - - $$page_content = ''; my (%results,%archs); foreach my $result (sort { $a->[0] cmp $b->[0] } @results) { my $file = shift @$result; @@ -178,54 +112,49 @@ sub do_search_contents { next unless keys %pkgs; $results{$file} = \%pkgs; } - my @all_archs = keys %archs; - @all_archs = @ARCHITECTURES unless @all_archs; + my @all_archs = sort keys %archs; + @all_archs = sort @ARCHITECTURES unless @all_archs; + $page_content->{suite} = $suite; + $page_content->{archive} = $archive; + $page_content->{all_architectures} = \@all_archs; + $page_content->{all_suites} = \@SUITES; + $page_content->{mode} = $mode; + $page_content->{search_architectures} = $opts->{arch}; + $page_content->{search_keywords} = $opts->{keywords}; + $page_content->{sections} = $opts->{section}; + $page_content->{too_many_hits} = $Packages::Search::too_many_hits; + debug( "all_archs = @all_archs", 1 ) if DEBUG; - msg(_g("Limit search to a specific architecture:")." ". - join( ' ', map { '[$_}). - "\">$_]" } @all_archs ) ) - unless (@{$opts->{arch}} == 1) || (@all_archs == 1); - msg(sprintf(_g('Search in all architectures'), - make_search_url('',"keywords=$keyword_esc",{arch=>undef}))) - if @{$opts->{arch}} == 1; - - if (!@Packages::CGI::fatal_errors && !keys(%results)) { - error( _g( "Nothing found" ) ); - } if (keys %results) { - $$page_content .= "

".sprintf( _g( 'Found %s results' ), - scalar keys %results )."

"; - $$page_content .= '
\n"; - foreach my $file (sort keys %results) { - my $file_enc = encode_entities($file); - foreach my $kw (@{$opts->{keywords}}) { - my $kw_enc = encode_entities($kw); - $file_enc =~ s#(\Q$kw_enc\E)#$1#g; - } - $$page_content .= "\n"; + push @{$page_content->{results}}, \%result; } - $$page_content .= '\n" if @results > 20; - $$page_content .= '
'._g('File').''._g('Packages') - ."
/$file_enc"; - my @pkgs; + my $sort_func = sub { $_[0] cmp $_[1] }; + $sort_func = sub { (sort keys %{$results{$_[0]}})[0] + cmp + (sort keys %{$results{$_[1]}})[0] + } if $opts->{sort_by} eq 'pkg'; + + $page_content->{results} = []; + foreach my $file (sort {&$sort_func($a,$b)} keys %results) { + my %result; + $result{file} = "/$file"; + $result{packages} = []; foreach my $pkg (sort keys %{$results{$file}}) { my $arch_str = ''; my @archs = keys %{$results{$file}{$pkg}}; + my $arch_neg = 0; unless ($results{$file}{$pkg}{all} || (@archs == @all_archs)) { - if (@archs < @all_archs/2) { - $arch_str = ' ['.join(' ',sort @archs).']'; - } else { - $arch_str = ' ['._g('not').' '. - join(' ', grep { !$results{$file}{$pkg}{$_} } @all_archs).']'; + if (@archs >= @all_archs/2) { + @archs = grep { !$results{$file}{$pkg}{$_} } @all_archs; + $arch_neg = 1; } + } else { + @archs = (); } - push @pkgs, "$suite})."\">$pkg$arch_str"; + push @{$result{packages}}, { pkg => $pkg, architectures => \@archs, architectures_are_rev => $arch_neg }; } - $$page_content .= join( ", ", @pkgs); - $$page_content .= "
'._g('File').''._g('Packages')."
'; } } # sub do_search_contents @@ -237,15 +166,22 @@ sub searchfile debug( "searchfile: kw=$kw", 1 ) if DEBUG; for (my $status = $reverses->seq($key, $value, R_CURSOR); $status == 0; - $status = $reverses->seq( $key, $value, R_NEXT)) { + $status = $reverses->seq( $key, $value, R_NEXT)) { # FIXME: what's the most efficient "is prefix of" thingy? We only want to know # whether $kw is or is not a prefix of $key last unless index($key, $kw) == 0; debug( "found $key", 2 ) if DEBUG; - my @hits = split /\0/o, $value; - push @$results, [ scalar reverse($key), @hits ]; + my @files = split /\001/o, $value; + foreach my $f (@files) { + my @hits = split /\0/o, $f; + my $file = shift @hits; + if ($file eq '-') { + $file = reverse($key); + } + push @$results, [ $file, @hits ]; + } last if ($$nres)++ > 100; }