{"thread":{"id":"7865","subject":"[PATCH] gitweb: Add support for grep searches","startedAt":"2007-04-27T03:41:39Z","lastAt":"2007-04-27T04:34:50Z","messageCount":6,"participants":["Petr Baudis","Linus Torvalds","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"40553","messageId":"20070427034138.1646.15989.stgit@rover","threadId":"7865","inReplyTo":null,"subject":"[PATCH] gitweb: Add support for grep searches","fromName":"Petr Baudis","fromEmail":"pasky@suse.cz","sentAt":"2007-04-27T03:41:39Z","receivedAt":"2007-04-27T03:41:39Z","isPatch":true,"sender":{"key":"pasky@ucw.cz","avatar":"https://avatars.githubusercontent.com/u/18439?v=4"},"body":"The 'grep' type of search greps the currently selected tree for given\nregexp and shows the results in a fancy table with links into blob view.\nThe number of shown matches is limited to 1000 and the whole feature\ncan be turned off (grepping linux-2.6.git already makes repo.or.cz a bit\nunhappy).\n\nSigned-off-by: Petr Baudis <pasky@suse.cz>\n---\n\n gitweb/gitweb.css  |    4 ++\n gitweb/gitweb.perl |  130 ++++++++++++++++++++++++++++++++++++++++++++++++----\n 2 files changed, 125 insertions(+), 9 deletions(-)\n\ndiff --git a/gitweb/gitweb.css b/gitweb/gitweb.css\nindex 2b023bd..c070d4b 100644\n--- a/gitweb/gitweb.css\n+++ b/gitweb/gitweb.css\n@@ -467,3 +467,7 @@ span.atnight {\n span.match {\n \tcolor: #e00000;\n }\n+\n+div.binary {\n+\tfont-style: italic;\n+}\ndiff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl\nindex cbd8d03..642ee0d 100755\n--- a/gitweb/gitweb.perl\n+++ b/gitweb/gitweb.perl\n@@ -142,6 +142,19 @@ our %feature = (\n \t\t'override' => 0,\n \t\t'default' => [1]},\n \n+\t# Enable grep search, which will list the files in currently selected\n+\t# tree containing the given string. Enabled by default. This can be\n+\t# potentially CPU-intensive, of course.\n+\n+\t# To enable system wide have in $GITWEB_CONFIG\n+\t# $feature{'grep'}{'default'} = [1];\n+\t# To have project specific config enable override in $GITWEB_CONFIG\n+\t# $feature{'grep'}{'override'} = 1;\n+\t# and in project config gitweb.grep = 0|1;\n+\t'grep' => {\n+\t\t'override' => 0,\n+\t\t'default' => [1]},\n+\n \t# Enable the pickaxe search, which will list the commits that modified\n \t# a given string in a file. This can be practical and quite faster\n \t# alternative to 'blame', but still potentially CPU-intensive.\n@@ -241,6 +254,18 @@ sub gitweb_have_snapshot {\n \treturn $have_snapshot;\n }\n \n+sub feature_grep {\n+\tmy ($val) = git_get_project_config('grep', '--bool');\n+\n+\tif ($val eq 'true') {\n+\t\treturn (1);\n+\t} elsif ($val eq 'false') {\n+\t\treturn (0);\n+\t}\n+\n+\treturn ($_[0]);\n+}\n+\n sub feature_pickaxe {\n \tmy ($val) = git_get_project_config('pickaxe', '--bool');\n \n@@ -360,21 +385,23 @@ if (defined $page) {\n \t}\n }\n \n+our $searchtype = $cgi->param('st');\n+if (defined $searchtype) {\n+\tif ($searchtype =~ m/[^a-z]/) {\n+\t\tdie_error(undef, \"Invalid searchtype parameter\");\n+\t}\n+}\n+\n our $searchtext = $cgi->param('s');\n if (defined $searchtext) {\n-\tif ($searchtext =~ m/[^a-zA-Z0-9_\\.\\/\\-\\+\\:\\@ ]/) {\n+\tif ($searchtype ne 'grep' and $searchtext =~ m/[^a-zA-Z0-9_\\.\\/\\-\\+\\:\\@ ]/) {\n \t\tdie_error(undef, \"Invalid search parameter\");\n \t}\n \tif (length($searchtext) < 2) {\n \t\tdie_error(undef, \"At least two characters are required for search parameter\");\n \t}\n-\t$searchtext = quotemeta $searchtext;\n-}\n-\n-our $searchtype = $cgi->param('st');\n-if (defined $searchtype) {\n-\tif ($searchtype =~ m/[^a-z]/) {\n-\t\tdie_error(undef, \"Invalid searchtype parameter\");\n+\tif ($searchtype ne 'grep') {\n+\t\t$searchtext = quotemeta $searchtext;\n \t}\n }\n \n@@ -1823,7 +1850,7 @@ #provides backwards capability for those\n \t\t      $cgi->hidden(-name => \"a\") . \"\\n\" .\n \t\t      $cgi->hidden(-name => \"h\") . \"\\n\" .\n \t\t      $cgi->popup_menu(-name => 'st', -default => 'commit',\n-\t\t                       -values => ['commit', 'author', 'committer', 'pickaxe']) .\n+\t\t                       -values => ['commit', 'grep', 'author', 'committer', 'pickaxe']) .\n \t\t      $cgi->sup($cgi->a({-href => href(action=>\"search_help\")}, \"?\")) .\n \t\t      \" search:\\n\",\n \t\t      $cgi->textfield(-name => \"s\", -value => $searchtext) . \"\\n\" .\n@@ -4313,6 +4340,12 @@ sub git_search {\n \t\t\tdie_error('403 Permission denied', \"Permission denied\");\n \t\t}\n \t}\n+\tif ($searchtype eq 'grep') {\n+\t\tmy ($have_grep) = gitweb_check_feature('grep');\n+\t\tif (!$have_grep) {\n+\t\t\tdie_error('403 Permission denied', \"Permission denied\");\n+\t\t}\n+\t}\n \n \tgit_header_html();\n \n@@ -4429,6 +4462,73 @@ sub git_search {\n \n \t\tprint \"</table>\\n\";\n \t}\n+\n+\tif ($searchtype eq 'grep') {\n+\t\tgit_print_page_nav('','', $hash,$co{'tree'},$hash);\n+\t\tgit_print_header_div('commit', esc_html($co{'title'}), $hash);\n+\n+\t\tprint \"<table cellspacing=\\\"0\\\">\\n\";\n+\t\tmy $alternate = 1;\n+\t\tmy $matches = 0;\n+\t\t$/ = \"\\n\";\n+\t\topen my $fd, \"-|\", git_cmd(), 'grep', '-n', '-i', $searchtext, $co{'tree'};\n+\t\tmy $lastfile = '';\n+\t\twhile (my $line = <$fd>) {\n+\t\t\tchomp $line;\n+\t\t\tmy ($file, $lno, $ltext, $binary);\n+\t\t\tlast if ($matches++ > 1000);\n+\t\t\tif ($line =~ /^Binary file (.+) matches$/) {\n+\t\t\t\t$file = $1;\n+\t\t\t\t$binary = 1;\n+\t\t\t} else {\n+\t\t\t\t(undef, $file, $lno, $ltext) = split(/:/, $line, 4);\n+\t\t\t}\n+\t\t\tif ($file ne $lastfile) {\n+\t\t\t\t$lastfile and print \"</td></tr>\\n\";\n+\t\t\t\tif ($alternate++) {\n+\t\t\t\t\tprint \"<tr class=\\\"dark\\\">\\n\";\n+\t\t\t\t} else {\n+\t\t\t\t\tprint \"<tr class=\\\"light\\\">\\n\";\n+\t\t\t\t}\n+\t\t\t\tprint \"<td class=\\\"list\\\">\".\n+\t\t\t\t\t$cgi->a({-href => href(action=>\"blob\", hash=>$co{'hash'},\n+\t\t\t\t\t\t\t       file_name=>\"$file\"),\n+\t\t\t\t\t\t-class => \"list\"}, esc_path($file));\n+\t\t\t\tprint \"</td><td>\\n\";\n+\t\t\t\t$lastfile = $file;\n+\t\t\t}\n+\t\t\tif ($binary) {\n+\t\t\t\tprint \"<div class=\\\"binary\\\">Binary file</div>\\n\";\n+\t\t\t} else {\n+\t\t\t\t$ltext = untabify($ltext);\n+\t\t\t\tif ($ltext =~ m/^(.*)($searchtext)(.*)$/i) {\n+\t\t\t\t\t$ltext = esc_html($1, -nbsp=>1);\n+\t\t\t\t\t$ltext .= '<span class=\"match\">';\n+\t\t\t\t\t$ltext .= esc_html($2, -nbsp=>1);\n+\t\t\t\t\t$ltext .= '</span>';\n+\t\t\t\t\t$ltext .= esc_html($3, -nbsp=>1);\n+\t\t\t\t} else {\n+\t\t\t\t\t$ltext = esc_html($ltext, -nbsp=>1);\n+\t\t\t\t}\n+\t\t\t\tprint \"<div class=\\\"pre\\\">\" .\n+\t\t\t\t\t$cgi->a({-href => href(action=>\"blob\", hash=>$co{'hash'},\n+\t\t\t\t\t\t\t       file_name=>\"$file\").'#l'.$lno,\n+\t\t\t\t\t\t-class => \"linenr\"}, sprintf('%4i', $lno))\n+\t\t\t\t\t. ' ' .  $ltext . \"</div>\\n\";\n+\t\t\t}\n+\t\t}\n+\t\tif ($lastfile) {\n+\t\t\tprint \"</td></tr>\\n\";\n+\t\t\tif ($matches > 1000) {\n+\t\t\t\tprint \"<div class=\\\"diff nodifferences\\\">Too many matches, listing trimmed</div>\\n\";\n+\t\t\t}\n+\t\t} else {\n+\t\t\tprint \"<div class=\\\"diff nodifferences\\\">No matches found</div>\\n\";\n+\t\t}\n+\t\tclose $fd;\n+\n+\t\tprint \"</table>\\n\";\n+\t}\n \tgit_footer_html();\n }\n \n@@ -4439,6 +4539,18 @@ sub git_search_help {\n <dl>\n <dt><b>commit</b></dt>\n <dd>The commit messages and authorship information will be scanned for the given string.</dd>\n+EOT\n+\tmy ($have_grep) = gitweb_check_feature('grep');\n+\tif ($have_grep) {\n+\t\tprint <<EOT;\n+<dt><b>grep</b></dt>\n+<dd>All files in the currently selected tree (HEAD unless you are explicitly browsing\n+    a different one) are searched for the given string and the matches are listed. On large\n+trees, this search can take a while and strain the server a little, so please use it with\n+some consideration.</dd>\n+EOT\n+\t}\n+\tprint <<EOT;\n <dt><b>author</b></dt>\n <dd>Name and e-mail of the change author and date of birth of the patch will be scanned for the given string.</dd>\n <dt><b>committer</b></dt>\n"},{"id":"40554","messageId":"20070427034729.GU4489@pasky.or.cz","threadId":"7865","inReplyTo":"20070427034138.1646.15989.stgit@rover","subject":"Re: [PATCH] gitweb: Add support for grep searches","fromName":"Petr Baudis","fromEmail":"pasky@suse.cz","sentAt":"2007-04-27T03:47:29Z","receivedAt":"2007-04-27T03:47:29Z","isPatch":true,"sender":{"key":"pasky@ucw.cz","avatar":"https://avatars.githubusercontent.com/u/18439?v=4"},"body":"On Fri, Apr 27, 2007 at 05:41:39AM CEST, Petr Baudis wrote:\n> The 'grep' type of search greps the currently selected tree for given\n> regexp and shows the results in a fancy table with links into blob view.\n> The number of shown matches is limited to 1000 and the whole feature\n> can be turned off (grepping linux-2.6.git already makes repo.or.cz a bit\n> unhappy).\n\nIt seems that with basically a single exception, Git is remarkably\nunemotional and cold...\n\n\thttp://repo.or.cz/w?p=git.git&a=search&h=HEAD&st=grep&s=hate%5B%5Ev%5D\n\n...and pretty much all the feelings are brought to us from the wild CVS\nworld...\n\n\thttp://repo.or.cz/w?p=git.git&a=search&h=HEAD&st=grep&s=love\n\n  You could say that git lacks a human dimension here! Maybe we should at least\nmake it utter some awesome jokes at random moments (more usage errors = less\njokes for the user, that'll teach 'em).\n\n-- \n\t\t\t\tPetr \"Pasky\" Baudis\nStuff: http://pasky.or.cz/\nEver try. Ever fail. No matter. // Try again. Fail again. Fail better.\n\t\t-- Samuel Beckett\n"},{"id":"40556","messageId":"alpine.LFD.0.98.0704262055270.9964@woody.linux-foundation.org","threadId":"7865","inReplyTo":"20070427034729.GU4489@pasky.or.cz","subject":"Re: [PATCH] gitweb: Add support for grep searches","fromName":"Linus Torvalds","fromEmail":"torvalds@linux-foundation.org","sentAt":"2007-04-27T03:59:29Z","receivedAt":"2007-04-27T03:59:29Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Fri, 27 Apr 2007, Petr Baudis wrote:\n> \n> \thttp://repo.or.cz/w?p=git.git&a=search&h=HEAD&st=grep&s=hate%5B%5Ev%5D\n\nThat looks bogus. It doesn't find\n\n - Documentation/git-cvsimport.txt:\n\n\tgit-cvsimport - Salvage your data out of another SCM people love to hate\n\nWhy?\n\n\t\tLinus\n"},{"id":"40557","messageId":"20070427042111.GV4489@pasky.or.cz","threadId":"7865","inReplyTo":"alpine.LFD.0.98.0704262055270.9964@woody.linux-foundation.org","subject":"Re: [PATCH] gitweb: Add support for grep searches","fromName":"Petr Baudis","fromEmail":"pasky@suse.cz","sentAt":"2007-04-27T04:21:11Z","receivedAt":"2007-04-27T04:21:11Z","isPatch":true,"sender":{"key":"pasky@ucw.cz","avatar":"https://avatars.githubusercontent.com/u/18439?v=4"},"body":"On Fri, Apr 27, 2007 at 05:59:29AM CEST, Linus Torvalds wrote:\n> \n> \n> On Fri, 27 Apr 2007, Petr Baudis wrote:\n> > \n> > \thttp://repo.or.cz/w?p=git.git&a=search&h=HEAD&st=grep&s=hate%5B%5Ev%5D\n> \n> That looks bogus. It doesn't find\n> \n>  - Documentation/git-cvsimport.txt:\n> \n> \tgit-cvsimport - Salvage your data out of another SCM people love to hate\n> \n> Why?\n\nBecause it doesn't accept hate$, it should be like\n\n\thttp://repo.or.cz/w?p=git.git&a=search&h=HEAD&st=grep&s=hate%28%5B%5Ev%5D%7C%24%29\n\nor even better\n\n\thttp://repo.or.cz/w?p=git.git&a=search&h=HEAD&st=grep&s=hate%5Cb\n\nbut in order to be able to use the regexps without breaking your\nbackslash key and eyes, I think it's somewhat saner to accept extended\nregexps instead of basic regexps; YMMV, I'll let Junio or the list\ndecide which way is better.\n\n-- \n\t\t\t\tPetr \"Pasky\" Baudis\nStuff: http://pasky.or.cz/\nEver try. Ever fail. No matter. // Try again. Fail again. Fail better.\n\t\t-- Samuel Beckett\n"},{"id":"40558","messageId":"20070427042157.20038.19163.stgit@rover","threadId":"7865","inReplyTo":"alpine.LFD.0.98.0704262055270.9964@woody.linux-foundation.org","subject":"[PATCH] gitweb: Add support for grep searches","fromName":"Petr Baudis","fromEmail":"pasky@suse.cz","sentAt":"2007-04-27T04:21:58Z","receivedAt":"2007-04-27T04:21:58Z","isPatch":true,"sender":{"key":"pasky@ucw.cz","avatar":"https://avatars.githubusercontent.com/u/18439?v=4"},"body":"The 'grep' type of search greps the currently selected tree for given\nregexp and shows the results in a fancy table with links into blob view.\nThe number of shown matches is limited to 1000 and the whole feature\ncan be turned off (grepping linux-2.6.git already makes repo.or.cz a bit\nunhappy).\n\nThis second revision makes it in documentation explicit that grep accepts\nregexps, and makes grep accept extended regexps instead of basic regexps.\n\nSigned-off-by: Petr Baudis <pasky@suse.cz>\n---\n\n gitweb/gitweb.css  |    4 ++\n gitweb/gitweb.perl |  132 ++++++++++++++++++++++++++++++++++++++++++++++++----\n 2 files changed, 127 insertions(+), 9 deletions(-)\n\ndiff --git a/gitweb/gitweb.css b/gitweb/gitweb.css\nindex 2b023bd..c070d4b 100644\n--- a/gitweb/gitweb.css\n+++ b/gitweb/gitweb.css\n@@ -467,3 +467,7 @@ span.atnight {\n span.match {\n \tcolor: #e00000;\n }\n+\n+div.binary {\n+\tfont-style: italic;\n+}\ndiff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl\nindex cbd8d03..b67ce41 100755\n--- a/gitweb/gitweb.perl\n+++ b/gitweb/gitweb.perl\n@@ -142,6 +142,19 @@ our %feature = (\n \t\t'override' => 0,\n \t\t'default' => [1]},\n \n+\t# Enable grep search, which will list the files in currently selected\n+\t# tree containing the given string. Enabled by default. This can be\n+\t# potentially CPU-intensive, of course.\n+\n+\t# To enable system wide have in $GITWEB_CONFIG\n+\t# $feature{'grep'}{'default'} = [1];\n+\t# To have project specific config enable override in $GITWEB_CONFIG\n+\t# $feature{'grep'}{'override'} = 1;\n+\t# and in project config gitweb.grep = 0|1;\n+\t'grep' => {\n+\t\t'override' => 0,\n+\t\t'default' => [1]},\n+\n \t# Enable the pickaxe search, which will list the commits that modified\n \t# a given string in a file. This can be practical and quite faster\n \t# alternative to 'blame', but still potentially CPU-intensive.\n@@ -241,6 +254,18 @@ sub gitweb_have_snapshot {\n \treturn $have_snapshot;\n }\n \n+sub feature_grep {\n+\tmy ($val) = git_get_project_config('grep', '--bool');\n+\n+\tif ($val eq 'true') {\n+\t\treturn (1);\n+\t} elsif ($val eq 'false') {\n+\t\treturn (0);\n+\t}\n+\n+\treturn ($_[0]);\n+}\n+\n sub feature_pickaxe {\n \tmy ($val) = git_get_project_config('pickaxe', '--bool');\n \n@@ -360,21 +385,23 @@ if (defined $page) {\n \t}\n }\n \n+our $searchtype = $cgi->param('st');\n+if (defined $searchtype) {\n+\tif ($searchtype =~ m/[^a-z]/) {\n+\t\tdie_error(undef, \"Invalid searchtype parameter\");\n+\t}\n+}\n+\n our $searchtext = $cgi->param('s');\n if (defined $searchtext) {\n-\tif ($searchtext =~ m/[^a-zA-Z0-9_\\.\\/\\-\\+\\:\\@ ]/) {\n+\tif ($searchtype ne 'grep' and $searchtext =~ m/[^a-zA-Z0-9_\\.\\/\\-\\+\\:\\@ ]/) {\n \t\tdie_error(undef, \"Invalid search parameter\");\n \t}\n \tif (length($searchtext) < 2) {\n \t\tdie_error(undef, \"At least two characters are required for search parameter\");\n \t}\n-\t$searchtext = quotemeta $searchtext;\n-}\n-\n-our $searchtype = $cgi->param('st');\n-if (defined $searchtype) {\n-\tif ($searchtype =~ m/[^a-z]/) {\n-\t\tdie_error(undef, \"Invalid searchtype parameter\");\n+\tif ($searchtype ne 'grep') {\n+\t\t$searchtext = quotemeta $searchtext;\n \t}\n }\n \n@@ -1823,7 +1850,7 @@ #provides backwards capability for those\n \t\t      $cgi->hidden(-name => \"a\") . \"\\n\" .\n \t\t      $cgi->hidden(-name => \"h\") . \"\\n\" .\n \t\t      $cgi->popup_menu(-name => 'st', -default => 'commit',\n-\t\t                       -values => ['commit', 'author', 'committer', 'pickaxe']) .\n+\t\t                       -values => ['commit', 'grep', 'author', 'committer', 'pickaxe']) .\n \t\t      $cgi->sup($cgi->a({-href => href(action=>\"search_help\")}, \"?\")) .\n \t\t      \" search:\\n\",\n \t\t      $cgi->textfield(-name => \"s\", -value => $searchtext) . \"\\n\" .\n@@ -4313,6 +4340,12 @@ sub git_search {\n \t\t\tdie_error('403 Permission denied', \"Permission denied\");\n \t\t}\n \t}\n+\tif ($searchtype eq 'grep') {\n+\t\tmy ($have_grep) = gitweb_check_feature('grep');\n+\t\tif (!$have_grep) {\n+\t\t\tdie_error('403 Permission denied', \"Permission denied\");\n+\t\t}\n+\t}\n \n \tgit_header_html();\n \n@@ -4429,6 +4462,73 @@ sub git_search {\n \n \t\tprint \"</table>\\n\";\n \t}\n+\n+\tif ($searchtype eq 'grep') {\n+\t\tgit_print_page_nav('','', $hash,$co{'tree'},$hash);\n+\t\tgit_print_header_div('commit', esc_html($co{'title'}), $hash);\n+\n+\t\tprint \"<table cellspacing=\\\"0\\\">\\n\";\n+\t\tmy $alternate = 1;\n+\t\tmy $matches = 0;\n+\t\t$/ = \"\\n\";\n+\t\topen my $fd, \"-|\", git_cmd(), 'grep', '-n', '-i', '-E', $searchtext, $co{'tree'};\n+\t\tmy $lastfile = '';\n+\t\twhile (my $line = <$fd>) {\n+\t\t\tchomp $line;\n+\t\t\tmy ($file, $lno, $ltext, $binary);\n+\t\t\tlast if ($matches++ > 1000);\n+\t\t\tif ($line =~ /^Binary file (.+) matches$/) {\n+\t\t\t\t$file = $1;\n+\t\t\t\t$binary = 1;\n+\t\t\t} else {\n+\t\t\t\t(undef, $file, $lno, $ltext) = split(/:/, $line, 4);\n+\t\t\t}\n+\t\t\tif ($file ne $lastfile) {\n+\t\t\t\t$lastfile and print \"</td></tr>\\n\";\n+\t\t\t\tif ($alternate++) {\n+\t\t\t\t\tprint \"<tr class=\\\"dark\\\">\\n\";\n+\t\t\t\t} else {\n+\t\t\t\t\tprint \"<tr class=\\\"light\\\">\\n\";\n+\t\t\t\t}\n+\t\t\t\tprint \"<td class=\\\"list\\\">\".\n+\t\t\t\t\t$cgi->a({-href => href(action=>\"blob\", hash=>$co{'hash'},\n+\t\t\t\t\t\t\t       file_name=>\"$file\"),\n+\t\t\t\t\t\t-class => \"list\"}, esc_path($file));\n+\t\t\t\tprint \"</td><td>\\n\";\n+\t\t\t\t$lastfile = $file;\n+\t\t\t}\n+\t\t\tif ($binary) {\n+\t\t\t\tprint \"<div class=\\\"binary\\\">Binary file</div>\\n\";\n+\t\t\t} else {\n+\t\t\t\t$ltext = untabify($ltext);\n+\t\t\t\tif ($ltext =~ m/^(.*)($searchtext)(.*)$/i) {\n+\t\t\t\t\t$ltext = esc_html($1, -nbsp=>1);\n+\t\t\t\t\t$ltext .= '<span class=\"match\">';\n+\t\t\t\t\t$ltext .= esc_html($2, -nbsp=>1);\n+\t\t\t\t\t$ltext .= '</span>';\n+\t\t\t\t\t$ltext .= esc_html($3, -nbsp=>1);\n+\t\t\t\t} else {\n+\t\t\t\t\t$ltext = esc_html($ltext, -nbsp=>1);\n+\t\t\t\t}\n+\t\t\t\tprint \"<div class=\\\"pre\\\">\" .\n+\t\t\t\t\t$cgi->a({-href => href(action=>\"blob\", hash=>$co{'hash'},\n+\t\t\t\t\t\t\t       file_name=>\"$file\").'#l'.$lno,\n+\t\t\t\t\t\t-class => \"linenr\"}, sprintf('%4i', $lno))\n+\t\t\t\t\t. ' ' .  $ltext . \"</div>\\n\";\n+\t\t\t}\n+\t\t}\n+\t\tif ($lastfile) {\n+\t\t\tprint \"</td></tr>\\n\";\n+\t\t\tif ($matches > 1000) {\n+\t\t\t\tprint \"<div class=\\\"diff nodifferences\\\">Too many matches, listing trimmed</div>\\n\";\n+\t\t\t}\n+\t\t} else {\n+\t\t\tprint \"<div class=\\\"diff nodifferences\\\">No matches found</div>\\n\";\n+\t\t}\n+\t\tclose $fd;\n+\n+\t\tprint \"</table>\\n\";\n+\t}\n \tgit_footer_html();\n }\n \n@@ -4439,6 +4539,20 @@ sub git_search_help {\n <dl>\n <dt><b>commit</b></dt>\n <dd>The commit messages and authorship information will be scanned for the given string.</dd>\n+EOT\n+\tmy ($have_grep) = gitweb_check_feature('grep');\n+\tif ($have_grep) {\n+\t\tprint <<EOT;\n+<dt><b>grep</b></dt>\n+<dd>All files in the currently selected tree (HEAD unless you are explicitly browsing\n+    a different one) are searched for the given\n+<a href=\"http://en.wikipedia.org/wiki/Regular_expression\">regular expression</a>\n+(POSIX extended) and the matches are listed. On large\n+trees, this search can take a while and put some strain on the server, so please use it with\n+some consideration.</dd>\n+EOT\n+\t}\n+\tprint <<EOT;\n <dt><b>author</b></dt>\n <dd>Name and e-mail of the change author and date of birth of the patch will be scanned for the given string.</dd>\n <dt><b>committer</b></dt>\n"},{"id":"40561","messageId":"7vtzv2ph91.fsf@assigned-by-dhcp.cox.net","threadId":"7865","inReplyTo":"alpine.LFD.0.98.0704262055270.9964@woody.linux-foundation.org","subject":"Re: [PATCH] gitweb: Add support for grep searches","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2007-04-27T04:34:50Z","receivedAt":"2007-04-27T04:34:50Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Linus Torvalds <torvalds@linux-foundation.org> writes:\n\n> On Fri, 27 Apr 2007, Petr Baudis wrote:\n>> \n>> \thttp://repo.or.cz/w?p=git.git&a=search&h=HEAD&st=grep&s=hate%5B%5Ev%5D\n>\n> That looks bogus. It doesn't find\n>\n>  - Documentation/git-cvsimport.txt:\n>\n> \tgit-cvsimport - Salvage your data out of another SCM people love to hate\n>\n> Why?\n\nBecause he uses \"hate[^v]\" to exclude \"whatever\" from matching,\nbut the line you quoted does not have anything after \"hate\".\n"}]}