{"thread":{"id":"4467","subject":"[PATCH] gitweb: Adding a `blame' interface.","startedAt":"2006-06-11T15:45:19Z","lastAt":"2006-06-15T19:46:18Z","messageCount":19,"participants":["Florian Forster","Martin Langhoff","Shawn Pearce","Johannes Schindelin","Linus Torvalds","Jon Loeliger","Fredrik Kuivinen","Junio C Hamano","Marco Costalba"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"21598","messageId":"11500407193506-git-send-email-octo@verplant.org","threadId":"4467","inReplyTo":null,"subject":"[PATCH] gitweb: Adding a `blame' interface.","fromName":"Florian Forster","fromEmail":"octo@verplant.org","sentAt":"2006-06-11T15:45:19Z","receivedAt":"2006-06-11T15:45:19Z","isPatch":true,"sender":{"key":"octo@verplant.org","avatar":null},"body":"This patch adds an interface for `git-blame' to `gitweb.cgi'. Links to it are\nplace in `git_blob'.\nInternally the code uses `git-annotate' because `git-blame's output differs for\nfiles that have been renamed in the past. However, I like the term `blame'\nbetter.\n\nSigned-off-by: Florian Forster <octo@verplant.org>\n\n\n---\n\n gitweb/gitweb.cgi |  108 +++++++++++++++++++++++++++++++++++++++++++++++++++++\n 1 files changed, 107 insertions(+), 1 deletions(-)\n\nb11522d270365b293197680e43e8feb87328a352\ndiff --git a/gitweb/gitweb.cgi b/gitweb/gitweb.cgi\nindex ea21fbe..91c075d 100755\n--- a/gitweb/gitweb.cgi\n+++ b/gitweb/gitweb.cgi\n@@ -203,6 +203,9 @@ if (!defined $action || $action eq \"summ\n } elsif ($action eq \"tag\") {\n \tgit_tag();\n \texit;\n+} elsif ($action eq \"blame\") {\n+\tgit_blame();\n+\texit;\n } else {\n \tundef $action;\n \tdie_error(undef, \"Unknown action.\");\n@@ -1228,6 +1231,107 @@ sub git_tag {\n \tgit_footer_html();\n }\n \n+sub git_blame {\n+\tmy $fd;\n+\tdie_error('404 Not Found', \"What file will it be, master?\") if (!$file_name);\n+\t$hash_base ||= git_read_head($project);\n+\tdie_error(undef, \"Reading commit failed.\") unless ($hash_base);\n+\tmy %co = git_read_commit($hash_base)\n+\t\tor die_error(undef, \"Reading commit failed.\");\n+\tif (!defined $hash) {\n+\t\t$hash = git_get_hash_by_path($hash_base, $file_name, \"blob\")\n+\t\t\tor die_error(undef, \"Error lookup file.\");\n+\t}\n+\topen ($fd, \"-|\", \"$gitbin/git-annotate\", '-l', '-t', '-r', $file_name, $hash_base)\n+\t\tor die_error(undef, \"Open failed.\");\n+\tgit_header_html();\n+\tprint \"<div class=\\\"page_nav\\\">\\n\" .\n+\t\t$cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=summary\")}, \"summary\") .\n+\t\t\" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=shortlog\")}, \"shortlog\") .\n+\t\t\" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=log\")}, \"log\") .\n+\t\t\" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=commit;h=$hash_base\")}, \"commit\") .\n+\t\t\" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=commitdiff;h=$hash_base\")}, \"commitdiff\") .\n+\t\t\" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=tree;h=$co{'tree'};hb=$hash_base\")}, \"tree\") . \"<br/>\\n\";\n+\tprint $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=blob;h=$hash;hb=$hash_base;f=$file_name\")}, \"blob\") .\n+\t\t\" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=blame;f=$file_name\")}, \"head\") . \"<br/>\\n\";\n+\tprint \"</div>\\n\".\n+\t\t\"<div>\" .\n+\t\t$cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=commit;h=$hash_base\"), -class => \"title\"}, esc_html($co{'title'})) .\n+\t\t\"</div>\\n\";\n+\tprint \"<div class=\\\"page_path\\\"><b>\" . esc_html($file_name) . \"</b></div>\\n\";\n+\tprint \"<div class=\\\"page_body\\\">\\n\";\n+\tprint <<HTML;\n+<table style=\"border-collapse: collapse;\">\n+  <tr>\n+    <th>Commit</th>\n+    <th>Age</th>\n+    <th>Author</th>\n+    <th>Line</th>\n+    <th>Data</th>\n+  </tr>\n+HTML\n+\tmy @line_class = (qw(light dark));\n+\tmy $line_class_len = scalar (@line_class);\n+\tmy $line_class_num = $#line_class;\n+\twhile (my $line = <$fd>) {\n+\t\tmy $long_rev;\n+\t\tmy $short_rev;\n+\t\tmy $author;\n+\t\tmy $time;\n+\t\tmy $lineno;\n+\t\tmy $data;\n+\t\tmy $age;\n+\t\tmy $age_str;\n+\t\tmy $age_style;\n+\n+\t\tchomp $line;\n+\t\t$line_class_num = ($line_class_num + 1) % $line_class_len;\n+\n+\t\tif ($line =~ m/^([0-9a-fA-F]{40})\\t\\(\\s*([^\\t]+)\\t(\\d+) \\+\\d\\d\\d\\d\\t(\\d+)\\)(.*)$/) {\n+\t\t\t$long_rev = $1;\n+\t\t\t$author   = $2;\n+\t\t\t$time     = $3;\n+\t\t\t$lineno   = $4;\n+\t\t\t$data     = $5;\n+\t\t} else {\n+\t\t\tprint qq(  <tr><td colspan=\"5\" style=\"color: red; background-color: yellow;\">Unable to parse: $line</td></tr>\\n);\n+\t\t\tnext;\n+\t\t}\n+\t\t$short_rev  = substr ($long_rev, 0, 8);\n+\t\t$age        = time () - $time;\n+\t\t$age_str    = age_string ($age);\n+\t\t$age_str    =~ s/ /&nbsp;/g;\n+\t\t$age_style  = 'font-style: italic;';\n+\t\t$age_style .= ' color: #009900; background: transparent;' if ($age < 60*60*24*2);\n+\t\t$age_style .= ' font-weight: bold;' if ($age < 60*60*2);\n+\t\t$author     = esc_html ($author);\n+\t\t$author     =~ s/ /&nbsp;/g;\n+\t\t# escape tabs\n+\t\twhile ((my $pos = index($data, \"\\t\")) != -1) {\n+\t\t\tif (my $count = (8 - ($pos % 8))) {\n+\t\t\t\tmy $spaces = ' ' x $count;\n+\t\t\t\t$data =~ s/\\t/$spaces/;\n+\t\t\t}\n+\t\t}\n+\t\t$data = esc_html ($data);\n+\t\t$data =~ s/ /&nbsp;/g;\n+\n+\t\tprint <<HTML;\n+  <tr class=\"$line_class[$line_class_num]\">\n+    <td style=\"font-family: monospace;\"><a href=\"$my_uri?${\\esc_param (\"p=$project;a=commit;h=$long_rev\")}\" class=\"text\">$short_rev..</a></td>\n+    <td style=\"$age_style\">$age_str</td>\n+    <td>$author</td>\n+    <td style=\"text-align: right;\"><a id=\"$lineno\" href=\"#$lineno\" class=\"linenr\">$lineno</a></td>\n+    <td style=\"font-family: monospace;\">$data</td>\n+  </tr>\n+HTML\n+\t} # while (my $line = <$fd>)\n+\tprint \"</table>\\n\\n\";\n+\tclose $fd or print \"Reading blob failed.\\n\";\n+\tprint \"</div>\";\n+\tgit_footer_html();\n+}\n+\n sub git_tags {\n \tmy $head = git_read_head($project);\n \tgit_header_html();\n@@ -1375,7 +1479,8 @@ sub git_blob {\n \t\t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=commitdiff;h=$hash_base\")}, \"commitdiff\") .\n \t\t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=tree;h=$co{'tree'};hb=$hash_base\")}, \"tree\") . \"<br/>\\n\";\n \t\tif (defined $file_name) {\n-\t\t\tprint $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=blob_plain;h=$hash;f=$file_name\")}, \"plain\") .\n+\t\t\tprint $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=blame;h=$hash;hb=$hash_base;f=$file_name\")}, \"blame\") .\n+\t\t\t\" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=blob_plain;h=$hash;f=$file_name\")}, \"plain\") .\n \t\t\t\" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=blob;hb=HEAD;f=$file_name\")}, \"head\") . \"<br/>\\n\";\n \t\t} else {\n \t\t\tprint $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=blob_plain;h=$hash\")}, \"plain\") . \"<br/>\\n\";\n@@ -1496,6 +1601,7 @@ sub git_tree {\n \t\t\t      \"</td>\\n\" .\n \t\t\t      \"<td class=\\\"link\\\">\" .\n \t\t\t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=blob;h=$t_hash$base_key;f=$base$t_name\")}, \"blob\") .\n+#\t\t\t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=blame;h=$t_hash$base_key;f=$base$t_name\")}, \"blame\") .\n \t\t\t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=history;h=$hash_base;f=$base$t_name\")}, \"history\") .\n \t\t\t      \"</td>\\n\";\n \t\t} elsif ($t_type eq \"tree\") {\n-- \n1.3.3\n"},{"id":"21612","messageId":"46a038f90606111502g607be3cfnf83ce81764a5f909@mail.gmail.com","threadId":"4467","inReplyTo":"11500407193506-git-send-email-octo@verplant.org","subject":"Re: [PATCH] gitweb: Adding a `blame' interface.","fromName":"Martin Langhoff","fromEmail":"martin.langhoff@gmail.com","sentAt":"2006-06-11T22:02:05Z","receivedAt":"2006-06-11T22:02:05Z","isPatch":true,"sender":{"key":"martin.langhoff@gmail.com","avatar":"https://gravatar.com/avatar/1e3f311b6c4c15836501901ca58f8c0b0667246488084ba524d8bc9867e22fd9?d=mp&s=160"},"body":"Florian,\n\nLooks good! git-blame/git-annotate are quite expensive to run. Do you\nthink it would make sense making it conditional on a git-repo-config\noption (gitweb.blame=1)?\n\nkernel.org is the flagship user for gitweb, so expensive options\nshould default to off :-/\n\ncheers,\n\n\n\nmartin\n"},{"id":"21635","messageId":"20060612082448.GA11857@verplant.org","threadId":"4467","inReplyTo":"46a038f90606111502g607be3cfnf83ce81764a5f909@mail.gmail.com","subject":"Re: [PATCH] gitweb: Adding a `blame' interface.","fromName":"Florian Forster","fromEmail":"octo@verplant.org","sentAt":"2006-06-12T08:24:48Z","receivedAt":"2006-06-12T08:24:48Z","isPatch":true,"sender":{"key":"octo@verplant.org","avatar":null},"body":"Hi Martin,\n\nOn Mon, Jun 12, 2006 at 10:02:05AM +1200, Martin Langhoff wrote:\n> good! git-blame/git-annotate are quite expensive to run. Do you think\n> it would make sense making it conditional on a git-repo-config option\n> (gitweb.blame=1)?\n\nsure, that it's a big change and if it helps the kernel.org folks ;)\nI'll follow-up with a patch for this in a second..\n\nWould it help to cache `git-annotate's output, e.g. using one of the\n`Cache::Cache' modules? Or is browsing of blobs too sparse for this to\nresult in a performance gain? I'm sure the modules could be integrated\nas a weak precondition.\n\nI have two more points regarding gitweb's configuration:\n- IMHO it would make sense to move the general gitweb-configuration\n  (where are the repositories, where are the binaries, etc) out of the\n  script.  As far as I know the Debian maintainer of the `gitweb'\n  package has asked for this before but was refused for some reason..\n  Possibly a file `gitweb.conf' in the same directory as the script\n  could be read and overwrite the builtin defaults..?\n- If `GIT_DIR/description' is only used by gitweb it may be more\n  consistent to use the git-repo-config option `gitweb.description' in\n  the future.\n\nRegards,\n-octo\n-- \nFlorian octo Forster\nHacker in training\nGnuPG: 0x91523C3D\nhttp://verplant.org/\n"},{"id":"21636","messageId":"11501011173804-git-send-email-octo@verplant.org","threadId":"4467","inReplyTo":"20060612082448.GA11857@verplant.org","subject":"[PATCH] gitweb: Make the availability of the `blame' interface in gitweb configurable.","fromName":"Florian Forster","fromEmail":"octo@verplant.org","sentAt":"2006-06-12T08:31:57Z","receivedAt":"2006-06-12T08:31:57Z","isPatch":true,"sender":{"key":"octo@verplant.org","avatar":null},"body":"Since `git-annotate' is an expensive operation to run it may be desirable to\ndeactivate this functionality. This patch introduces the `gitweb.blame' option\nto git-repo-config and disables the blame support by default.\n\nSigned-off-by: Florian Forster <octo@verplant.org>\n\n\n---\n\n gitweb/gitweb.cgi |   27 +++++++++++++++++++++++++--\n 1 files changed, 25 insertions(+), 2 deletions(-)\n\n3eea23e8d8a13579455cdf8d5088794d33bdcba2\ndiff --git a/gitweb/gitweb.cgi b/gitweb/gitweb.cgi\nindex 91c075d..5eabe06 100755\n--- a/gitweb/gitweb.cgi\n+++ b/gitweb/gitweb.cgi\n@@ -837,6 +837,25 @@ sub git_read_projects {\n \treturn @list;\n }\n \n+sub git_get_project_config {\n+\tmy $key = shift;\n+\n+\treturn unless ($key);\n+\t$key =~ s/^gitweb\\.//;\n+\treturn if ($key =~ m/\\W/);\n+\n+\tmy $val = qx(git-repo-config --get gitweb.$key);\n+\treturn ($val);\n+}\n+\n+sub git_get_project_config_bool {\n+\tmy $val = git_get_project_config (@_);\n+\tif ($val and $val =~ m/true|yes|on/) {\n+\t\treturn (1);\n+\t}\n+\treturn; # implicit false\n+}\n+\n sub git_project_list {\n \tmy @list = git_read_projects();\n \tmy @projects;\n@@ -1233,6 +1252,7 @@ sub git_tag {\n \n sub git_blame {\n \tmy $fd;\n+\tdie_error('403 Permission denied', \"Permission denied.\") if (!git_get_project_config_bool ('blame'));\n \tdie_error('404 Not Found', \"What file will it be, master?\") if (!$file_name);\n \t$hash_base ||= git_read_head($project);\n \tdie_error(undef, \"Reading commit failed.\") unless ($hash_base);\n@@ -1468,6 +1488,7 @@ sub git_blob {\n \t\tmy $base = $hash_base || git_read_head($project);\n \t\t$hash = git_get_hash_by_path($base, $file_name, \"blob\") || die_error(undef, \"Error lookup file.\");\n \t}\n+\tmy $have_blame = git_get_project_config_bool ('blame');\n \topen my $fd, \"-|\", \"$gitbin/git-cat-file blob $hash\" or die_error(undef, \"Open failed.\");\n \tgit_header_html();\n \tif (defined $hash_base && (my %co = git_read_commit($hash_base))) {\n@@ -1479,8 +1500,10 @@ sub git_blob {\n \t\t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=commitdiff;h=$hash_base\")}, \"commitdiff\") .\n \t\t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=tree;h=$co{'tree'};hb=$hash_base\")}, \"tree\") . \"<br/>\\n\";\n \t\tif (defined $file_name) {\n-\t\t\tprint $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=blame;h=$hash;hb=$hash_base;f=$file_name\")}, \"blame\") .\n-\t\t\t\" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=blob_plain;h=$hash;f=$file_name\")}, \"plain\") .\n+\t\t\tif ($have_blame) {\n+\t\t\t\tprint $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=blame;h=$hash;hb=$hash_base;f=$file_name\")}, \"blame\") .  \" | \";\n+\t\t\t}\n+\t\t\tprint $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=blob_plain;h=$hash;f=$file_name\")}, \"plain\") .\n \t\t\t\" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=blob;hb=HEAD;f=$file_name\")}, \"head\") . \"<br/>\\n\";\n \t\t} else {\n \t\t\tprint $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=blob_plain;h=$hash\")}, \"plain\") . \"<br/>\\n\";\n-- \n1.3.3\n"},{"id":"21637","messageId":"46a038f90606120134n21c269bbj3e8c7e31d4d93a23@mail.gmail.com","threadId":"4467","inReplyTo":"20060612082448.GA11857@verplant.org","subject":"Re: [PATCH] gitweb: Adding a `blame' interface.","fromName":"Martin Langhoff","fromEmail":"martin.langhoff@gmail.com","sentAt":"2006-06-12T08:34:43Z","receivedAt":"2006-06-12T08:34:43Z","isPatch":true,"sender":{"key":"martin.langhoff@gmail.com","avatar":"https://gravatar.com/avatar/1e3f311b6c4c15836501901ca58f8c0b0667246488084ba524d8bc9867e22fd9?d=mp&s=160"},"body":"On 6/12/06, Florian Forster <octo@verplant.org> wrote:\n> On Mon, Jun 12, 2006 at 10:02:05AM +1200, Martin Langhoff wrote:\n> > good! git-blame/git-annotate are quite expensive to run. Do you think\n> > it would make sense making it conditional on a git-repo-config option\n> > (gitweb.blame=1)?\n>\n> sure, that it's a big change and if it helps the kernel.org folks ;)\n> I'll follow-up with a patch for this in a second..\n\nThat'd be great. I am looking into integrating other feature patches\ntoo (like tarball downloads) that are useful but costly, making them\nconditional too...\n\n> Would it help to cache `git-annotate's output, e.g. using one of the\n\nI think we can rely on proxies doing good caching -- a busy host like\nkernel.org will have big reverse proxies in front. A git-blame for a\ngiven file+commitsha doesn't change, so we can give it a long cache\ntime, like... forever ;-)\n\n> I have two more points regarding gitweb's configuration:\n> - IMHO it would make sense to move the general gitweb-configuration\n>   (where are the repositories, where are the binaries, etc) out of the\n>   script.  As far as I know the Debian maintainer of the `gitweb'\n>   package has asked for this before but was refused for some reason..\n\nSounds like a reasonable request. I would make it rely on env vars,\n$ENV{GITWEB_CONFIG} can generally point to /etc/gitweb.conf, and that\nwould override the config values we have.\n\nThis is trivial, and it means we buy a lot of flexibility from\napache's httpd.conf being able to point to different config files\ndepending on arbitrarty conditions.\n\nBTW, I haven't seen the debian maintainer's request, was that on the list?\n\n> - If `GIT_DIR/description' is only used by gitweb it may be more\n>   consistent to use the git-repo-config option `gitweb.description' in\n>   the future.\n\nNot sure how git-repo configurations deal with long entries. Right now\nthe description may contain html for instance.\n\n\n\nmartin\n"},{"id":"21638","messageId":"20060612084056.GA29220@spearce.org","threadId":"4467","inReplyTo":"46a038f90606120134n21c269bbj3e8c7e31d4d93a23@mail.gmail.com","subject":"Re: [PATCH] gitweb: Adding a `blame' interface.","fromName":"Shawn Pearce","fromEmail":"spearce@spearce.org","sentAt":"2006-06-12T08:40:56Z","receivedAt":"2006-06-12T08:40:56Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"Martin Langhoff <martin.langhoff@gmail.com> wrote:\n> >- If `GIT_DIR/description' is only used by gitweb it may be more\n> >  consistent to use the git-repo-config option `gitweb.description' in\n> >  the future.\n> \n> Not sure how git-repo configurations deal with long entries. Right now\n> the description may contain html for instance.\n\nIt has to be escaped, which could be ugly with HTML.  For example:\n\n  [gitweb]\n    description=<div class=\\\"description\\\">\\n\\\nThis is a chunk of text which describes this repository.  Some\\n\\\nof this text might be rather long, and might need many lines to\\n\\\nreally be able to describe the repository in a nice editor such as\\n\\\nvi running in an 80 character wide xterm.\\n\\\n</div>\n\nForget a \\ in front of a double quote (\") or an LF and the entry is\ncorrupt.  So as nice as it sounds it might not be the best way to\nobtain a description for gitweb.\n\n-- \nShawn.\n"},{"id":"21639","messageId":"Pine.LNX.4.63.0606121107520.21813@wbgn013.biozentrum.uni-wuerzburg.de","threadId":"4467","inReplyTo":"20060612084056.GA29220@spearce.org","subject":"Re: [PATCH] gitweb: Adding a `blame' interface.","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2006-06-12T09:08:45Z","receivedAt":"2006-06-12T09:08:45Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Mon, 12 Jun 2006, Shawn Pearce wrote:\n\n>   [gitweb]\n>     description=<div class=\\\"description\\\">\\n\\\n> This is a chunk of text which describes this repository.  Some\\n\\\n> of this text might be rather long, and might need many lines to\\n\\\n> really be able to describe the repository in a nice editor such as\\n\\\n> vi running in an 80 character wide xterm.\\n\\\n> </div>\n\nAFAIK the trailing \"\\\" will not work.\n\nCiao,\nDscho\n"},{"id":"21640","messageId":"20060612091949.GB29220@spearce.org","threadId":"4467","inReplyTo":"Pine.LNX.4.63.0606121107520.21813@wbgn013.biozentrum.uni-wuerzburg.de","subject":"Re: [PATCH] gitweb: Adding a `blame' interface.","fromName":"Shawn Pearce","fromEmail":"spearce@spearce.org","sentAt":"2006-06-12T09:19:49Z","receivedAt":"2006-06-12T09:19:49Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:\n> Hi,\n> \n> On Mon, 12 Jun 2006, Shawn Pearce wrote:\n> \n> >   [gitweb]\n> >     description=<div class=\\\"description\\\">\\n\\\n> > This is a chunk of text which describes this repository.  Some\\n\\\n> > of this text might be rather long, and might need many lines to\\n\\\n> > really be able to describe the repository in a nice editor such as\\n\\\n> > vi running in an 80 character wide xterm.\\n\\\n> > </div>\n> \n> AFAIK the trailing \"\\\" will not work.\n\nActually it does.  I figured out that it works (and why it works)\nwhen I implemented the GIT repository parser in Java for my pure\nJava version of GIT...\n\nFor example:\n\n  [spearce@spearce-pb15 bob]$ cat .git/config \n  [core]\n          repositoryformatversion = 0\n          filemode = true\n  [gitweb]\n          description = This is a very\\nlong line to put into GIT\\n\\\n  repo config.\\n\\\n  I hope it works.\n          on = true\n  [spearce@spearce-pb15 bob]$ git repo-config gitweb.description\n  This is a very\n  long line to put into GIT\n  repo config.\n  I hope it works.\n  [spearce@spearce-pb15 bob]$ git repo-config gitweb.on\n  true\n\nThe use of a trailing \\ makes sense; the collapsing of multiple\nspaces into one space unless quoted inside of \"\" doesn't.\nBut whatever...\n\n-- \nShawn.\n"},{"id":"21645","messageId":"Pine.LNX.4.64.0606120754460.5498@g5.osdl.org","threadId":"4467","inReplyTo":"20060612082448.GA11857@verplant.org","subject":"Re: [PATCH] gitweb: Adding a `blame' interface.","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2006-06-12T14:59:39Z","receivedAt":"2006-06-12T14:59:39Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Mon, 12 Jun 2006, Florian Forster wrote:\n> \n> Would it help to cache `git-annotate's output, e.g. using one of the\n> `Cache::Cache' modules? Or is browsing of blobs too sparse for this to\n> result in a performance gain? I'm sure the modules could be integrated\n> as a weak precondition.\n\nThe apache setup at least on kernel.org is already set up to do caching, \nas long as the generated headers for the page allow it in the first place.\n\nSo caching inside gitweb is generally pointless, at least when it's at the \nlevel of one result page. At a higher level, if the internal caching might \nimprove performance of _other_ pages because it caches the result of some \nintermediate important thing, it might be a different issue.\n\n\t\tLinus\n"},{"id":"21660","messageId":"20060612175735.GA13432@verplant.org","threadId":"4467","inReplyTo":"Pine.LNX.4.64.0606120754460.5498@g5.osdl.org","subject":"Re: [PATCH] gitweb: Supporting caches (was: Adding a `blame' interface.)","fromName":"Florian Forster","fromEmail":"octo@verplant.org","sentAt":"2006-06-12T17:57:35Z","receivedAt":"2006-06-12T17:57:35Z","isPatch":true,"sender":{"key":"octo@verplant.org","avatar":null},"body":"On Mon, Jun 12, 2006 at 07:59:39AM -0700, Linus Torvalds wrote:\n> The apache setup at least on kernel.org is already set up to do\n> caching, as long as the generated headers for the page allow it in the\n> first place.\n\nI've actually looked into improving native HTTP caching (mostly for\nsmall site without revers proxying) by providing a `Last-Modified'\nheader where possible and sending a `304 Not Modified' whenever\nappropriate.\n\nWhile it doesn't sound hard it's next to impossible: A commit's\ntimestamp doesn't change when head a points to it (or does not longer\npoint to it). Also displaying the timestamps as `Modified xy\n{seconds,minutes, hours,...} ago' possess a big problem.\n\n(I guess the webserver could use the `If-Modified-Since' header to check\nif the displayed time needs to be updated, but if you ask me it's not\nworth the effort.)\n\nIn short, the `blob', `blob_plain', and `blobdiff' pages could profit\nfrom that because they don't display the head(s) pointing to the current\ncommit. On the other hand, this is a little inconsistent and could be\nconsidered a bug. So I'll give up on that unless someone has a great\nidea how to handle this.\n\nRegards,\n-octo\n-- \nFlorian octo Forster\nHacker in training\nGnuPG: 0x91523C3D\nhttp://verplant.org/\n"},{"id":"21662","messageId":"20060612181110.GB13432@verplant.org","threadId":"4467","inReplyTo":"46a038f90606120134n21c269bbj3e8c7e31d4d93a23@mail.gmail.com","subject":"Re: gitweb: Config file support (was: Adding a `blame' interface.)","fromName":"Florian Forster","fromEmail":"octo@verplant.org","sentAt":"2006-06-12T18:11:11Z","receivedAt":"2006-06-12T18:11:11Z","isPatch":false,"sender":{"key":"octo@verplant.org","avatar":null},"body":"Hi Martin,\n\nOn Mon, Jun 12, 2006 at 08:34:43PM +1200, Martin Langhoff wrote:\n> > As far as I know the Debian maintainer of the `gitweb' package has\n> > asked for this before but was refused for some reason..\n> BTW, I haven't seen the debian maintainer's request, was that on the list?\n\nYes, it was a mail by Andres Salomon on May 20th, 2005 with the subject\n`add conf file support to gitweb'. A friend of mine asked him if he had\nsent the patch upstream and he pointed to this message and explained he\nhad gotten a private reply saying that gitweb `only covers the special\nneeds on kernel.org'.\n\nRegards,\n-octo\n-- \nFlorian octo Forster\nHacker in training\nGnuPG: 0x91523C3D\nhttp://verplant.org/\n"},{"id":"21683","messageId":"1150147770.23938.373.camel@cashmere.sps.mot.com","threadId":"4467","inReplyTo":"20060612082448.GA11857@verplant.org","subject":"Re: [PATCH] gitweb: Adding a `blame' interface.","fromName":"Jon Loeliger","fromEmail":"jdl@freescale.com","sentAt":"2006-06-12T21:29:30Z","receivedAt":"2006-06-12T21:29:30Z","isPatch":true,"sender":{"key":"jdl@jdl.com","avatar":"https://gravatar.com/avatar/75ce9a10b151acd2c28ec4ab2136dba7b2ff1634530bd04b155981a749d08a64?d=mp&s=160"},"body":"On Mon, 2006-06-12 at 03:24, Florian Forster wrote:\n\n> I have two more points regarding gitweb's configuration:\n> - IMHO it would make sense to move the general gitweb-configuration\n>   (where are the repositories, where are the binaries, etc) out of the\n>   script.  As far as I know the Debian maintainer of the `gitweb'\n>   package has asked for this before but was refused for some reason..\n>   Possibly a file `gitweb.conf' in the same directory as the script\n>   could be read and overwrite the builtin defaults..?\n\nI already submitted a patch down this line on 22-Mar-2006:\n\n    http://marc.theaimsgroup.com/?l=git&m=114308224922372&w=2\n\nThanks,\njdl\n"},{"id":"21684","messageId":"20060612213826.GC4705@c165.ib.student.liu.se","threadId":"4467","inReplyTo":"11500407193506-git-send-email-octo@verplant.org","subject":"Re: [PATCH] gitweb: Adding a `blame' interface.","fromName":"Fredrik Kuivinen","fromEmail":"freku045@student.liu.se","sentAt":"2006-06-12T21:38:26Z","receivedAt":"2006-06-12T21:38:26Z","isPatch":true,"sender":{"key":"frekui@gmail.com","avatar":"https://avatars.githubusercontent.com/u/13770967?v=4"},"body":"On Sun, Jun 11, 2006 at 05:45:19PM +0200, Florian Forster wrote:\n> This patch adds an interface for `git-blame' to `gitweb.cgi'. Links to it are\n> place in `git_blob'.\n> Internally the code uses `git-annotate' because `git-blame's output differs for\n> files that have been renamed in the past. However, I like the term `blame'\n> better.\n> \n\nYou can pass \"--compatibility\" to git-blame to get output which is\nidentical to git-annotates output. However, \"--time\" is not\nimplemented in git-blame yet. I will send a patch in a separate mail.\n\ngit-blame is a bit faster than git-annotate and, as far as I know, it\nproduces output which is correct.\n\n- Fredrik\n"},{"id":"21688","messageId":"Pine.LNX.4.63.0606130041260.25422@wbgn013.biozentrum.uni-wuerzburg.de","threadId":"4467","inReplyTo":"20060612213826.GC4705@c165.ib.student.liu.se","subject":"Re: [PATCH] gitweb: Adding a `blame' interface.","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2006-06-12T22:42:14Z","receivedAt":"2006-06-12T22:42:14Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Mon, 12 Jun 2006, Fredrik Kuivinen wrote:\n\n> git-blame is a bit faster than git-annotate and, as far as I know, it \n> produces output which is correct.\n\nYeah: Bring It On(tm)! I already waited for ages for this war to begin!\n\nCiao,\nDscho\n"},{"id":"21690","messageId":"Pine.LNX.4.64.0606121546320.5498@g5.osdl.org","threadId":"4467","inReplyTo":"Pine.LNX.4.63.0606130041260.25422@wbgn013.biozentrum.uni-wuerzburg.de","subject":"Re: [PATCH] gitweb: Adding a `blame' interface.","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2006-06-12T22:49:56Z","receivedAt":"2006-06-12T22:49:56Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Tue, 13 Jun 2006, Johannes Schindelin wrote:\n> \n> On Mon, 12 Jun 2006, Fredrik Kuivinen wrote:\n> \n> > git-blame is a bit faster than git-annotate and, as far as I know, it \n> > produces output which is correct.\n> \n> Yeah: Bring It On(tm)! I already waited for ages for this war to begin!\n\nSadly, I don't think either of you can really do much about the fact that \nannotate/blame is simply the wrong model for git.\n\nThe war _I_d like to see is the GUI thing which does the \"show when this \nsection changed last\" by following the history down only so far that the \nselected section shows up in the diff against the most current thing.\n\nTHAT is what I want. It also fits the git model much better, since you \ngenerally don't have to go back all the way.\n\nSomebody? \"Here's a nickel saying you can't do it!\" (if somebody needs the \nmotivation ;)\n\n\t\tLinus\n"},{"id":"21691","messageId":"Pine.LNX.4.63.0606130053400.25682@wbgn013.biozentrum.uni-wuerzburg.de","threadId":"4467","inReplyTo":"Pine.LNX.4.64.0606121546320.5498@g5.osdl.org","subject":"Re: [PATCH] gitweb: Adding a `blame' interface.","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2006-06-12T22:55:34Z","receivedAt":"2006-06-12T22:55:34Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Mon, 12 Jun 2006, Linus Torvalds wrote:\n\n> On Tue, 13 Jun 2006, Johannes Schindelin wrote:\n> > \n> > On Mon, 12 Jun 2006, Fredrik Kuivinen wrote:\n> > \n> > > git-blame is a bit faster than git-annotate and, as far as I know, it \n> > > produces output which is correct.\n> > \n> > Yeah: Bring It On(tm)! I already waited for ages for this war to begin!\n> \n> Sadly, I don't think either of you can really do much about the fact that \n> annotate/blame is simply the wrong model for git.\n> \n> The war _I_d like to see is the GUI thing which does the \"show when this \n> section changed last\" by following the history down only so far that the \n> selected section shows up in the diff against the most current thing.\n\nBut this is just the next step! Nothing prevents you -- once everybody \nagrees that blame/annotate does the right thing -- to restrict the lines \nof interest. And AFAICT both blame and annotate are good at stopping when \nall lines are accounted for.\n\nCiao,\nDscho\n"},{"id":"21692","messageId":"Pine.LNX.4.64.0606121619510.5498@g5.osdl.org","threadId":"4467","inReplyTo":"Pine.LNX.4.63.0606130053400.25682@wbgn013.biozentrum.uni-wuerzburg.de","subject":"Re: [PATCH] gitweb: Adding a `blame' interface.","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2006-06-12T23:21:44Z","receivedAt":"2006-06-12T23:21:44Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Tue, 13 Jun 2006, Johannes Schindelin wrote:\n> > \n> > The war _I_d like to see is the GUI thing which does the \"show when this \n> > section changed last\" by following the history down only so far that the \n> > selected section shows up in the diff against the most current thing.\n> \n> But this is just the next step! Nothing prevents you -- once everybody \n> agrees that blame/annotate does the right thing -- to restrict the lines \n> of interest. And AFAICT both blame and annotate are good at stopping when \n> all lines are accounted for.\n\nYou misunderstand. It's not \"all\", it's \"any\" (in fact, it would be even \nbetter if it would be on a byte-range basis, not on a line-based diff \nbasis).\n\nAnd it needs the GUI to make it useful, because nobody in their right mind \nwill say \"git showchange fs/inode.c 77-89\" (and then do it iteratively if \nthe first one wasn't actually the interesting case).\n\n\t\tLinus\n"},{"id":"21798","messageId":"7vr71rcwk6.fsf@assigned-by-dhcp.cox.net","threadId":"4467","inReplyTo":"46a038f90606111502g607be3cfnf83ce81764a5f909@mail.gmail.com","subject":"Re: [PATCH] gitweb: Adding a `blame' interface.","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-06-14T20:27:21Z","receivedAt":"2006-06-14T20:27:21Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Martin Langhoff\" <martin.langhoff@gmail.com> writes:\n\n> Florian,\n>\n> Looks good! git-blame/git-annotate are quite expensive to run. Do you\n> think it would make sense making it conditional on a git-repo-config\n> option (gitweb.blame=1)?\n>\n> kernel.org is the flagship user for gitweb, so expensive options\n> should default to off :-/\n\nSeconded.  Thanks Florian and Martin.\n"},{"id":"21841","messageId":"e5bfff550606151246x39295ec7kf5081feec8c4e2f@mail.gmail.com","threadId":"4467","inReplyTo":"Pine.LNX.4.64.0606121546320.5498@g5.osdl.org","subject":"Re: [PATCH] gitweb: Adding a `blame' interface.","fromName":"Marco Costalba","fromEmail":"mcostalba@gmail.com","sentAt":"2006-06-15T19:46:18Z","receivedAt":"2006-06-15T19:46:18Z","isPatch":true,"sender":{"key":"mcostalba@gmail.com","avatar":null},"body":"On 6/13/06, Linus Torvalds <torvalds@osdl.org> wrote:\n>\n>\n> On Tue, 13 Jun 2006, Johannes Schindelin wrote:\n> >\n> > On Mon, 12 Jun 2006, Fredrik Kuivinen wrote:\n> >\n> > > git-blame is a bit faster than git-annotate and, as far as I know, it\n> > > produces output which is correct.\n> >\n> > Yeah: Bring It On(tm)! I already waited for ages for this war to begin!\n>\n> Sadly, I don't think either of you can really do much about the fact that\n> annotate/blame is simply the wrong model for git.\n>\n> The war _I_d like to see is the GUI thing which does the \"show when this\n> section changed last\" by following the history down only so far that the\n> selected section shows up in the diff against the most current thing.\n>\n\nProbably I have misunderstood the request, but in qgit you can (from\nabout one month ago) mouse select some lines in file content then\npress the filter button and see only the revisions that modify the\nselected text.\n\nAlso selected text is highlighted so to better view differences among revisions.\n\nIt is not clear to me in what the requested feature differs from this\nimplementation.\n\n    Marco\n"}]}