X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=gitweb%2Fgitweb.perl;h=5c7011a37b2e4dab8c38de54a3e531d2fa16ddbe;hb=ed82edc402c271a707da632083f1f4c19155d573;hp=66f306705f083da30a4629dc16f3aad604d4db51;hpb=8299886619b8dab99773b5810f50c63a50b2d611;p=git.git diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 66f306705..5c7011a37 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -146,6 +146,19 @@ our %feature = ( 'override' => 0, 'default' => [1]}, + # Enable grep search, which will list the files in currently selected + # tree containing the given string. Enabled by default. This can be + # potentially CPU-intensive, of course. + + # To enable system wide have in $GITWEB_CONFIG + # $feature{'grep'}{'default'} = [1]; + # To have project specific config enable override in $GITWEB_CONFIG + # $feature{'grep'}{'override'} = 1; + # and in project config gitweb.grep = 0|1; + 'grep' => { + 'override' => 0, + 'default' => [1]}, + # Enable the pickaxe search, which will list the commits that modified # a given string in a file. This can be practical and quite faster # alternative to 'blame', but still potentially CPU-intensive. @@ -245,6 +258,18 @@ sub gitweb_have_snapshot { return $have_snapshot; } +sub feature_grep { + my ($val) = git_get_project_config('grep', '--bool'); + + if ($val eq 'true') { + return (1); + } elsif ($val eq 'false') { + return (0); + } + + return ($_[0]); +} + sub feature_pickaxe { my ($val) = git_get_project_config('pickaxe', '--bool'); @@ -364,10 +389,17 @@ if (defined $page) { } } +our $searchtype = $cgi->param('st'); +if (defined $searchtype) { + if ($searchtype =~ m/[^a-z]/) { + die_error(undef, "Invalid searchtype parameter"); + } +} + our $searchtext = $cgi->param('s'); our $search_regexp; if (defined $searchtext) { - if ($searchtext =~ m/[^a-zA-Z0-9_\.\/\-\+\:\@ ]/) { + if ($searchtype ne 'grep' and $searchtype ne 'pickaxe' and $searchtext =~ m/[^a-zA-Z0-9_\.\/\-\+\:\@ ]/) { die_error(undef, "Invalid search parameter"); } if (length($searchtext) < 2) { @@ -376,13 +408,6 @@ if (defined $searchtext) { $search_regexp = quotemeta $searchtext; } -our $searchtype = $cgi->param('st'); -if (defined $searchtype) { - if ($searchtype =~ m/[^a-z]/) { - die_error(undef, "Invalid searchtype parameter"); - } -} - # now read PATH_INFO and use it as alternative to parameters sub evaluate_path_info { return if defined $project; @@ -1903,6 +1928,8 @@ EOF } print "\n"; } + print "\n"; + my ($have_search) = gitweb_check_feature('search'); if ((defined $project) && ($have_search)) { if (!defined $searchtext) { @@ -1925,14 +1952,13 @@ EOF $cgi->hidden(-name => "a") . "\n" . $cgi->hidden(-name => "h") . "\n" . $cgi->popup_menu(-name => 'st', -default => 'commit', - -values => ['commit', 'author', 'committer', 'pickaxe']) . + -values => ['commit', 'grep', 'author', 'committer', 'pickaxe']) . $cgi->sup($cgi->a({-href => href(action=>"search_help")}, "?")) . " search:\n", $cgi->textfield(-name => "s", -value => $searchtext) . "\n" . "" . $cgi->end_form() . "\n"; } - print "\n"; } sub git_footer_html { @@ -4625,6 +4651,12 @@ sub git_search { die_error('403 Permission denied', "Permission denied"); } } + if ($searchtype eq 'grep') { + my ($have_grep) = gitweb_check_feature('grep'); + if (!$have_grep) { + die_error('403 Permission denied', "Permission denied"); + } + } git_header_html(); @@ -4686,8 +4718,10 @@ sub git_search { my $alternate = 1; $/ = "\n"; my $git_command = git_cmd_str(); + my $searchqtext = $searchtext; + $searchqtext =~ s/'/'\\''/; open my $fd, "-|", "$git_command rev-list $hash | " . - "$git_command diff-tree -r --stdin -S\'$searchtext\'"; + "$git_command diff-tree -r --stdin -S\'$searchqtext\'"; undef %co; my @files; while (my $line = <$fd>) { @@ -4741,6 +4775,73 @@ sub git_search { print "\n"; } + + if ($searchtype eq 'grep') { + git_print_page_nav('','', $hash,$co{'tree'},$hash); + git_print_header_div('commit', esc_html($co{'title'}), $hash); + + print "\n"; + my $alternate = 1; + my $matches = 0; + $/ = "\n"; + open my $fd, "-|", git_cmd(), 'grep', '-n', '-i', '-E', $searchtext, $co{'tree'}; + my $lastfile = ''; + while (my $line = <$fd>) { + chomp $line; + my ($file, $lno, $ltext, $binary); + last if ($matches++ > 1000); + if ($line =~ /^Binary file (.+) matches$/) { + $file = $1; + $binary = 1; + } else { + (undef, $file, $lno, $ltext) = split(/:/, $line, 4); + } + if ($file ne $lastfile) { + $lastfile and print "\n"; + if ($alternate++) { + print "\n"; + } else { + print "\n"; + } + print "\n"; + if ($matches > 1000) { + print "
Too many matches, listing trimmed
\n"; + } + } else { + print "
No matches found
\n"; + } + close $fd; + + print "
". + $cgi->a({-href => href(action=>"blob", hash=>$co{'hash'}, + file_name=>"$file"), + -class => "list"}, esc_path($file)); + print "\n"; + $lastfile = $file; + } + if ($binary) { + print "
Binary file
\n"; + } else { + $ltext = untabify($ltext); + if ($ltext =~ m/^(.*)($searchtext)(.*)$/i) { + $ltext = esc_html($1, -nbsp=>1); + $ltext .= ''; + $ltext .= esc_html($2, -nbsp=>1); + $ltext .= ''; + $ltext .= esc_html($3, -nbsp=>1); + } else { + $ltext = esc_html($ltext, -nbsp=>1); + } + print "
" . + $cgi->a({-href => href(action=>"blob", hash=>$co{'hash'}, + file_name=>"$file").'#l'.$lno, + -class => "linenr"}, sprintf('%4i', $lno)) + . ' ' . $ltext . "
\n"; + } + } + if ($lastfile) { + print "
\n"; + } git_footer_html(); } @@ -4751,6 +4852,20 @@ sub git_search_help {
commit
The commit messages and authorship information will be scanned for the given string.
+EOT + my ($have_grep) = gitweb_check_feature('grep'); + if ($have_grep) { + print <grep +
All files in the currently selected tree (HEAD unless you are explicitly browsing + a different one) are searched for the given +regular expression +(POSIX extended) and the matches are listed. On large +trees, this search can take a while and put some strain on the server, so please use it with +some consideration.
+EOT + } + print <author
Name and e-mail of the change author and date of birth of the patch will be scanned for the given string.
committer
@@ -4925,7 +5040,8 @@ XML # get list of changed files open my $fd, "-|", git_cmd(), "diff-tree", '-r', @diff_opts, - $co{'parent'}, $co{'id'}, "--", (defined $file_name ? $file_name : ()) + $co{'parent'} || "--root", + $co{'id'}, "--", (defined $file_name ? $file_name : ()) or next; my @difftree = map { chomp; $_ } <$fd>; close $fd