gitweb: Add support for grep searches
The 'grep' type of search greps the currently selected tree for given regexp and shows the results in a fancy table with links into blob view. The number of shown matches is limited to 1000 and the whole feature can be turned off (grepping linux-2.6.git already makes repo.or.cz a bit unhappy). This second revision makes it in documentation explicit that grep accepts regexps, and makes grep accept extended regexps instead of basic regexps. Signed-off-by: Petr Baudis <pasky@suse.cz> Signed-off-by: Junio C Hamano <junkio@cox.net>
This commit is contained in:
parent
d77b5673e9
commit
e773855372
@ -484,3 +484,7 @@ span.atnight {
|
||||
span.match {
|
||||
color: #e00000;
|
||||
}
|
||||
|
||||
div.binary {
|
||||
font-style: italic;
|
||||
}
|
||||
|
@ -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 $searchtext =~ m/[^a-zA-Z0-9_\.\/\-\+\:\@ ]/) {
|
||||
die_error(undef, "Invalid search parameter");
|
||||
}
|
||||
if (length($searchtext) < 2) {
|
||||
@ -1927,7 +1959,7 @@ 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" .
|
||||
@ -4626,6 +4658,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();
|
||||
|
||||
@ -4742,6 +4780,73 @@ sub git_search {
|
||||
|
||||
print "</table>\n";
|
||||
}
|
||||
|
||||
if ($searchtype eq 'grep') {
|
||||
git_print_page_nav('','', $hash,$co{'tree'},$hash);
|
||||
git_print_header_div('commit', esc_html($co{'title'}), $hash);
|
||||
|
||||
print "<table cellspacing=\"0\">\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 "</td></tr>\n";
|
||||
if ($alternate++) {
|
||||
print "<tr class=\"dark\">\n";
|
||||
} else {
|
||||
print "<tr class=\"light\">\n";
|
||||
}
|
||||
print "<td class=\"list\">".
|
||||
$cgi->a({-href => href(action=>"blob", hash=>$co{'hash'},
|
||||
file_name=>"$file"),
|
||||
-class => "list"}, esc_path($file));
|
||||
print "</td><td>\n";
|
||||
$lastfile = $file;
|
||||
}
|
||||
if ($binary) {
|
||||
print "<div class=\"binary\">Binary file</div>\n";
|
||||
} else {
|
||||
$ltext = untabify($ltext);
|
||||
if ($ltext =~ m/^(.*)($searchtext)(.*)$/i) {
|
||||
$ltext = esc_html($1, -nbsp=>1);
|
||||
$ltext .= '<span class="match">';
|
||||
$ltext .= esc_html($2, -nbsp=>1);
|
||||
$ltext .= '</span>';
|
||||
$ltext .= esc_html($3, -nbsp=>1);
|
||||
} else {
|
||||
$ltext = esc_html($ltext, -nbsp=>1);
|
||||
}
|
||||
print "<div class=\"pre\">" .
|
||||
$cgi->a({-href => href(action=>"blob", hash=>$co{'hash'},
|
||||
file_name=>"$file").'#l'.$lno,
|
||||
-class => "linenr"}, sprintf('%4i', $lno))
|
||||
. ' ' . $ltext . "</div>\n";
|
||||
}
|
||||
}
|
||||
if ($lastfile) {
|
||||
print "</td></tr>\n";
|
||||
if ($matches > 1000) {
|
||||
print "<div class=\"diff nodifferences\">Too many matches, listing trimmed</div>\n";
|
||||
}
|
||||
} else {
|
||||
print "<div class=\"diff nodifferences\">No matches found</div>\n";
|
||||
}
|
||||
close $fd;
|
||||
|
||||
print "</table>\n";
|
||||
}
|
||||
git_footer_html();
|
||||
}
|
||||
|
||||
@ -4752,6 +4857,20 @@ sub git_search_help {
|
||||
<dl>
|
||||
<dt><b>commit</b></dt>
|
||||
<dd>The commit messages and authorship information will be scanned for the given string.</dd>
|
||||
EOT
|
||||
my ($have_grep) = gitweb_check_feature('grep');
|
||||
if ($have_grep) {
|
||||
print <<EOT;
|
||||
<dt><b>grep</b></dt>
|
||||
<dd>All files in the currently selected tree (HEAD unless you are explicitly browsing
|
||||
a different one) are searched for the given
|
||||
<a href="http://en.wikipedia.org/wiki/Regular_expression">regular expression</a>
|
||||
(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.</dd>
|
||||
EOT
|
||||
}
|
||||
print <<EOT;
|
||||
<dt><b>author</b></dt>
|
||||
<dd>Name and e-mail of the change author and date of birth of the patch will be scanned for the given string.</dd>
|
||||
<dt><b>committer</b></dt>
|
||||
|
Loading…
Reference in New Issue
Block a user