Index: lib/TWiki/Store/RcsFile.pm =================================================================== --- lib/TWiki/Store/RcsFile.pm (revision 12498) +++ lib/TWiki/Store/RcsFile.pm (working copy) @@ -328,43 +328,63 @@ my( $this, $searchString, $topics, $options ) = @_; ASSERT(defined $options) if DEBUG; my $type = $options->{type} || ''; - - # I18N: 'grep' must use locales if needed, - # for case-insensitive searching. See TWiki::setupLocale. - my $program = ''; - # FIXME: For Cygwin grep, do something about -E and -F switches - # - best to strip off any switches after first space in - # EgrepCmd etc and apply those as argument 1. - if( $type eq 'regex' ) { - $program = $TWiki::cfg{RCS}{EgrepCmd}; - } else { - $program = $TWiki::cfg{RCS}{FgrepCmd}; - } - - $program =~ s/%CS{(.*?)\|(.*?)}%/$options->{casesensitive}?$1:$2/ge; - $program =~ s/%DET{(.*?)\|(.*?)}%/$options->{files_without_match}?$2:$1/ge; - my $sDir = $TWiki::cfg{DataDir}.'/'.$this->{web}.'/'; - my $seen = {}; - # process topics in sets, fix for Codev.ArgumentListIsTooLongForSearch - my $maxTopicsInSet = 512; # max number of topics for a grep call - my @take = @$topics; - my @set = splice( @take, 0, $maxTopicsInSet ); - my $sandbox = $this->{session}->{sandbox}; - while( @set ) { - @set = map { "$sDir/$_.txt" } @set; - my ($matches, $exit ) = $sandbox->sysCommand( - $program, - TOKEN => $searchString, - FILES => \@set); - foreach my $match ( split( /\r?\n/, $matches )) { - if( $match =~ m/([^\/]*)\.txt(:(.*))?$/ ) { - push( @{$seen->{$1}}, $3 ); + my $matches = ''; + my %seen; + if (exists $ENV{MOD_PERL}) { + # Use pure-perl grep if MOD_PERL, as the fork() used by TWiki::Sandbox + # is horribly inefficient with mod_perl + local $/ = "\n"; + if ($type eq 'regex') { + $searchString =~ s!/!\\/!g; + } else { + $searchString =~ s/(\W)/\\$1/g; + } + my $match_code = "/$searchString/o"; + $match_code .= 'i' unless ($options->{casesensitive}); + my $doMatch = eval "sub { $match_code }"; + FILE: + foreach my $file ( @$topics ) { + next unless open(FILE, "$sDir/$file.txt"); + while () { + if (&$doMatch()) { + push( @{$seen{$file}}, $_ ); + next FILE if $options->{files_without_match}; + } } } - @set = splice( @take, 0, $maxTopicsInSet ); + } else { + # I18N: 'grep' must use locales if needed, + # for case-insensitive searching. See TWiki::setupLocale. + my $program = ''; + # FIXME: For Cygwin grep, do something about -E and -F switches + # - best to strip off any switches after first space in + # EgrepCmd etc and apply those as argument 1. + if( $type eq 'regex' ) { + $program = $TWiki::cfg{RCS}{EgrepCmd}; + } else { + $program = $TWiki::cfg{RCS}{FgrepCmd}; + } + + $program =~ s/%CS{(.*?)\|(.*?)}%/$options->{casesensitive}?$1:$2/ge; + $program =~ s/%DET{(.*?)\|(.*?)}%/$options->{files_without_match}?$2:$1/ge; + # process topics in sets, fix for Codev.ArgumentListIsTooLongForSearch + my $maxTopicsInSet = 512; # max number of topics for a grep call + my @take = @$topics; + my @set = splice( @take, 0, $maxTopicsInSet ); + my $sandbox = $this->{session}->{sandbox}; + while( @set ) { + @set = map { "$sDir/$_.txt" } @set; + my ($m, $exit ) = $sandbox->sysCommand( + $program, + TOKEN => $searchString, + FILES => \@set); + $matches .= $m; + @set = splice( @take, 0, $maxTopicsInSet ); + } + $matches =~ s/([^\/]*)\.txt(:(.*))?$/push( @{$seen{$1}}, $3 ); ''/gem; } - return $seen; + return \%seen; } =pod