{"thread":{"id":"5038","subject":"[PATCH 0] Some gitweb patches","startedAt":"2006-07-29T20:39:04Z","lastAt":"2006-08-01T20:10:00Z","messageCount":54,"participants":["Jakub Narebski","Junio C Hamano","Matthias Lederhofer","Luben Tuikov"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"24347","messageId":"200607292239.11034.jnareb@gmail.com","threadId":"5038","inReplyTo":null,"subject":"[PATCH 0] Some gitweb patches","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-07-29T20:39:04Z","receivedAt":"2006-07-29T20:39:04Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"This series of patches, based on 'next' branch (v1.4.2-rc2-g688a750 or \n688a75071490101dbc660e3304aafb7a13e28807) is the beginning of gitweb \ncleanup. It would hopefully introduce no new features.\n\nOpen-ended series...\n\n-- \nJakub Narebski\nPoland\n"},{"id":"24348","messageId":"200607292243.41264.jnareb@gmail.com","threadId":"5038","inReplyTo":"200607292239.11034.jnareb@gmail.com","subject":"[PATCH 1] gitweb: whitespace cleanup","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-07-29T20:43:40Z","receivedAt":"2006-07-29T20:43:40Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Signed-off-by: Jakub Narebski <jnareb@gmail.com>\n---\nUse tab for indenting commands, spaces for align\n(because the fact that some elements are aligned \nshould not depend on the tab width).\n\n gitweb/gitweb.cgi |   58 +++++++++++++++++++++++++++--------------------------\n 1 files changed, 30 insertions(+), 28 deletions(-)\n\ndiff --git a/gitweb/gitweb.cgi b/gitweb/gitweb.cgi\nindex e5fca63..f92eeab 100755\n--- a/gitweb/gitweb.cgi\n+++ b/gitweb/gitweb.cgi\n@@ -36,7 +36,7 @@ our $git_version = qx($GIT --version) =~\n # location for temporary files needed for diffs\n our $git_temp = \"/tmp/gitweb\";\n if (! -d $git_temp) {\n-    mkdir($git_temp, 0700) || die_error(\"Couldn't mkdir $git_temp\");\n+\tmkdir($git_temp, 0700) || die_error(\"Couldn't mkdir $git_temp\");\n }\n \n # target of the home link on top of all pages\n@@ -104,7 +104,7 @@ if (defined $project) {\n \t\tdie_error(undef, \"No such project.\");\n \t}\n \t$rss_link = \"<link rel=\\\"alternate\\\" title=\\\"\" . esc_param($project) . \" log\\\" href=\\\"\" .\n-\t\t    \"$my_uri?\" . esc_param(\"p=$project;a=rss\") . \"\\\" type=\\\"application/rss+xml\\\"/>\";\n+\t            \"$my_uri?\" . esc_param(\"p=$project;a=rss\") . \"\\\" type=\\\"application/rss+xml\\\"/>\";\n \t$ENV{'GIT_DIR'} = \"$projectroot/$project\";\n } else {\n \tgit_project_list();\n@@ -303,7 +303,7 @@ sub git_header_html {\n \t} else {\n \t\t$content_type = 'text/html';\n \t}\n-\tprint $cgi->header(-type=>$content_type,  -charset => 'utf-8', -status=> $status, -expires => $expires);\n+\tprint $cgi->header(-type=>$content_type, -charset => 'utf-8', -status=> $status, -expires => $expires);\n \tprint <<EOF;\n <?xml version=\"1.0\" encoding=\"utf-8\"?>\n <!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n@@ -1138,17 +1138,17 @@ sub git_summary {\n \t\t\t\t      \"</td>\\n\" .\n \t\t\t\t      \"<td>\";\n \t\t\t\tif (defined($comment)) {\n-\t\t\t\t      print $cgi->a({-class => \"list\", -href => \"$my_uri?\" . esc_param(\"p=$project;a=tag;h=$tag{'id'}\")}, esc_html($comment));\n+\t\t\t\t\tprint $cgi->a({-class => \"list\", -href => \"$my_uri?\" . esc_param(\"p=$project;a=tag;h=$tag{'id'}\")}, esc_html($comment));\n \t\t\t\t}\n \t\t\t\tprint \"</td>\\n\" .\n \t\t\t\t      \"<td class=\\\"link\\\">\";\n \t\t\t\tif ($tag{'type'} eq \"tag\") {\n-\t\t\t\t      print $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=tag;h=$tag{'id'}\")}, \"tag\") . \" | \";\n+\t\t\t\t\tprint $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=tag;h=$tag{'id'}\")}, \"tag\") . \" | \";\n \t\t\t\t}\n \t\t\t\tprint $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=$tag{'reftype'};h=$tag{'refid'}\")}, $tag{'reftype'});\n \t\t\t\tif ($tag{'reftype'} eq \"commit\") {\n-\t\t\t\t      print \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=shortlog;h=$tag{'name'}\")}, \"shortlog\") .\n-\t\t\t\t\t    \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=log;h=$tag{'refid'}\")}, \"log\");\n+\t\t\t\t\tprint \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=shortlog;h=$tag{'name'}\")}, \"shortlog\") .\n+\t\t\t\t\t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=log;h=$tag{'refid'}\")}, \"log\");\n \t\t\t\t}\n \t\t\t\tprint \"</td>\\n\" .\n \t\t\t\t      \"</tr>\";\n@@ -1457,17 +1457,17 @@ sub git_tags {\n \t\t\t      \"</td>\\n\" .\n \t\t\t      \"<td>\";\n \t\t\tif (defined($comment)) {\n-\t\t\t      print $cgi->a({-class => \"list\", -href => \"$my_uri?\" . esc_param(\"p=$project;a=tag;h=$tag{'id'}\")}, $comment);\n+\t\t\t\tprint $cgi->a({-class => \"list\", -href => \"$my_uri?\" . esc_param(\"p=$project;a=tag;h=$tag{'id'}\")}, $comment);\n \t\t\t}\n \t\t\tprint \"</td>\\n\" .\n \t\t\t      \"<td class=\\\"link\\\">\";\n \t\t\tif ($tag{'type'} eq \"tag\") {\n-\t\t\t      print $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=tag;h=$tag{'id'}\")}, \"tag\") . \" | \";\n+\t\t\t\tprint $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=tag;h=$tag{'id'}\")}, \"tag\") . \" | \";\n \t\t\t}\n \t\t\tprint $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=$tag{'reftype'};h=$tag{'refid'}\")}, $tag{'reftype'});\n \t\t\tif ($tag{'reftype'} eq \"commit\") {\n-\t\t\t      print \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=shortlog;h=$tag{'name'}\")}, \"shortlog\") .\n-\t\t\t\t    \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=log;h=$tag{'refid'}\")}, \"log\");\n+\t\t\t\tprint \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=shortlog;h=$tag{'name'}\")}, \"shortlog\") .\n+\t\t\t\t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=log;h=$tag{'refid'}\")}, \"log\");\n \t\t\t}\n \t\t\tprint \"</td>\\n\" .\n \t\t\t      \"</tr>\";\n@@ -1613,13 +1613,14 @@ sub git_blob_plain_mimetype {\n \n sub git_blob_plain {\n \tif (!defined $hash) {\n-                if (defined $file_name) {\n-                        my $base = $hash_base || git_read_head($project);\n-                        $hash = git_get_hash_by_path($base, $file_name, \"blob\") || die_error(undef, \"Error lookup file.\");\n-                } else {\n-                        die_error(undef, \"No file name defined.\");\n-                }\n-        }\n+\t\tif (defined $file_name) {\n+\t\t\tmy $base = $hash_base || git_read_head($project);\n+\t\t\t$hash = git_get_hash_by_path($base, $file_name, \"blob\") \n+\t\t\t\tor die_error(undef, \"Error lookup file.\");\n+\t\t} else {\n+\t\t\tdie_error(undef, \"No file name defined.\");\n+\t\t}\n+\t}\n \tmy $type = shift;\n \topen my $fd, \"-|\", \"$GIT cat-file blob $hash\" or die_error(\"Couldn't cat $file_name, $hash\");\n \n@@ -1644,13 +1645,14 @@ sub git_blob_plain {\n \n sub git_blob {\n \tif (!defined $hash) {\n-                if (defined $file_name) {\n-                        my $base = $hash_base || git_read_head($project);\n-                        $hash = git_get_hash_by_path($base, $file_name, \"blob\") || die_error(undef, \"Error lookup file.\");\n-                } else {\n-                        die_error(undef, \"No file name defined.\");\n-                }\n-        }\n+\t\tif (defined $file_name) {\n+\t\t\tmy $base = $hash_base || git_read_head($project);\n+\t\t\t$hash = git_get_hash_by_path($base, $file_name, \"blob\") \n+\t\t\t\tor die_error(undef, \"Error lookup file.\");\n+\t\t} else {\n+\t\t\tdie_error(undef, \"No file name defined.\");\n+\t\t}\n+\t}\n \tmy $have_blame = git_get_project_config_bool ('blame');\n \topen my $fd, \"-|\", \"$GIT cat-file blob $hash\" or die_error(undef, \"Open failed.\");\n \tmy $mimetype = git_blob_plain_mimetype($fd, $file_name);\n@@ -1677,7 +1679,7 @@ sub git_blob {\n \t\t\tprint $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=blob_plain;h=$hash\")}, \"plain\") . \"<br/>\\n\";\n \t\t}\n \t\tprint \"</div>\\n\".\n-\t\t       \"<div>\" .\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 \t} else {\n@@ -2305,7 +2307,7 @@ sub git_commitdiff {\n \t\tmy $status = $5;\n \t\tmy $file = validate_input(unquote($6));\n \t\tif ($status eq \"A\") {\n-\t\t\tprint \"<div class=\\\"diff_info\\\">\" .  file_type($to_mode) . \":\" .\n+\t\t\tprint \"<div class=\\\"diff_info\\\">\" . file_type($to_mode) . \":\" .\n \t\t\t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=blob;h=$to_id;hb=$hash;f=$file\")}, $to_id) . \"(new)\" .\n \t\t\t      \"</div>\\n\";\n \t\t\tgit_diff_print(undef, \"/dev/null\", $to_id, \"b/$file\");\n@@ -2359,7 +2361,7 @@ sub git_commitdiff_plain {\n \t      \"Date: $ad{'rfc2822'} ($ad{'tz_local'})\\n\".\n \t      \"Subject: $co{'title'}\\n\";\n \tif (defined $tagname) {\n-\t      print \"X-Git-Tag: $tagname\\n\";\n+\t\tprint \"X-Git-Tag: $tagname\\n\";\n \t}\n \tprint \"X-Git-Url: $my_url?p=$project;a=commitdiff;h=$hash\\n\" .\n \t      \"\\n\";\n-- \n1.4.0\n"},{"id":"24349","messageId":"200607292251.21072.jnareb@gmail.com","threadId":"5038","inReplyTo":"200607292239.11034.jnareb@gmail.com","subject":"[PATCH 2] gitweb: Use list for of open for running git commands, thorougly.","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-07-29T20:51:17Z","receivedAt":"2006-07-29T20:51:17Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Use list form of open for running git commands and reading their\noutput through pipe, for example\n  open my $fd, \"-|\", $GIT, \"rev-list\", \"--header\", \"--parents\", $hash\ninstead of\n  open my $fd, \"-|\", \"$GIT rev-list --header --parents $hash\"\nSingle letter options use ' instead of \" as quotes, according to style\nused in list form of magic \"-|\" open.\n\nSigned-off-by: Jakub Narebski <jnareb@gmail.com>\n---\nThe correct solution would be to use safe_pipe_capture or, \nwhat's better, use Git.pm, when it will be in released version.\n\nShould have no impact on speed. Using ' instead of \" could bring\ninsignificant speedup.\n\n gitweb/gitweb.cgi |   45 +++++++++++++++++++++++++--------------------\n 1 files changed, 25 insertions(+), 20 deletions(-)\n\ndiff --git a/gitweb/gitweb.cgi b/gitweb/gitweb.cgi\nindex f92eeab..9a17f87 100755\n--- a/gitweb/gitweb.cgi\n+++ b/gitweb/gitweb.cgi\n@@ -388,7 +388,7 @@ sub die_error {\n sub git_get_type {\n \tmy $hash = shift;\n \n-\topen my $fd, \"-|\", \"$GIT cat-file -t $hash\" or return;\n+\topen my $fd, \"-|\", $GIT, \"cat-file\", '-t', $hash or return;\n \tmy $type = <$fd>;\n \tclose $fd or return;\n \tchomp $type;\n@@ -440,7 +440,7 @@ sub git_read_tag {\n \tmy %tag;\n \tmy @comment;\n \n-\topen my $fd, \"-|\", \"$GIT cat-file tag $tag_id\" or return;\n+\topen my $fd, \"-|\", $GIT, \"cat-file\", \"tag\", $tag_id or return;\n \t$tag{'id'} = $tag_id;\n \twhile (my $line = <$fd>) {\n \t\tchomp $line;\n@@ -512,7 +512,7 @@ sub git_read_commit {\n \t\t@commit_lines = @$commit_text;\n \t} else {\n \t\t$/ = \"\\0\";\n-\t\topen my $fd, \"-|\", \"$GIT rev-list --header --parents --max-count=1 $commit_id\" or return;\n+\t\topen my $fd, \"-|\", $GIT, \"rev-list\", \"--header\", \"--parents\", \"--max-count=1\", $commit_id or return;\n \t\t@commit_lines = split '\\n', <$fd>;\n \t\tclose $fd or return;\n \t\t$/ = \"\\n\";\n@@ -610,7 +610,7 @@ sub git_diff_print {\n \tif (defined $from) {\n \t\t$from_tmp = \"$git_temp/gitweb_\" . $$ . \"_from\";\n \t\topen my $fd2, \"> $from_tmp\";\n-\t\topen my $fd, \"-|\", \"$GIT cat-file blob $from\";\n+\t\topen my $fd, \"-|\", $GIT, \"cat-file\", \"blob\", $from;\n \t\tmy @file = <$fd>;\n \t\tprint $fd2 @file;\n \t\tclose $fd2;\n@@ -621,7 +621,7 @@ sub git_diff_print {\n \tif (defined $to) {\n \t\t$to_tmp = \"$git_temp/gitweb_\" . $$ . \"_to\";\n \t\topen my $fd2, \"> $to_tmp\";\n-\t\topen my $fd, \"-|\", \"$GIT cat-file blob $to\";\n+\t\topen my $fd, \"-|\", $GIT, \"cat-file\", \"blob\", $to;\n \t\tmy @file = <$fd>;\n \t\tprint $fd2 @file;\n \t\tclose $fd2;\n@@ -1062,7 +1062,8 @@ sub git_summary {\n \t      \"<tr><td>owner</td><td>$owner</td></tr>\\n\" .\n \t      \"<tr><td>last change</td><td>$cd{'rfc2822'}</td></tr>\\n\" .\n \t      \"</table>\\n\";\n-\topen my $fd, \"-|\", \"$GIT rev-list --max-count=17 \" . git_read_head($project) or die_error(undef, \"Open failed.\");\n+\topen my $fd, \"-|\", $GIT, \"rev-list\", \"--max-count=17\", git_read_head($project) \n+\t\tor die_error(undef, \"Open failed.\");\n \tmy (@revlist) = map { chomp; $_ } <$fd>;\n \tclose $fd;\n \tprint \"<div>\\n\" .\n@@ -1526,7 +1527,7 @@ sub git_get_hash_by_path {\n \tmy $tree = $base;\n \tmy @parts = split '/', $path;\n \twhile (my $part = shift @parts) {\n-\t\topen my $fd, \"-|\", \"$GIT ls-tree $tree\" or die_error(undef, \"Open git-ls-tree failed.\");\n+\t\topen my $fd, \"-|\", $GIT, \"ls-tree\", $tree or die_error(undef, \"Open git-ls-tree failed.\");\n \t\tmy (@entries) = map { chomp; $_ } <$fd>;\n \t\tclose $fd or return undef;\n \t\tforeach my $line (@entries) {\n@@ -1622,7 +1623,7 @@ sub git_blob_plain {\n \t\t}\n \t}\n \tmy $type = shift;\n-\topen my $fd, \"-|\", \"$GIT cat-file blob $hash\" or die_error(\"Couldn't cat $file_name, $hash\");\n+\topen my $fd, \"-|\", $GIT, \"cat-file\", \"blob\", $hash or die_error(\"Couldn't cat $file_name, $hash\");\n \n \t$type ||= git_blob_plain_mimetype($fd, $file_name);\n \n@@ -1654,7 +1655,7 @@ sub git_blob {\n \t\t}\n \t}\n \tmy $have_blame = git_get_project_config_bool ('blame');\n-\topen my $fd, \"-|\", \"$GIT cat-file blob $hash\" or die_error(undef, \"Open failed.\");\n+\topen my $fd, \"-|\", $GIT, \"cat-file\", \"blob\", $hash or die_error(undef, \"Open failed.\");\n \tmy $mimetype = git_blob_plain_mimetype($fd, $file_name);\n \tif ($mimetype !~ m/^text\\//) {\n \t\tclose $fd;\n@@ -1718,7 +1719,7 @@ sub git_tree {\n \t\t}\n \t}\n \t$/ = \"\\0\";\n-\topen my $fd, \"-|\", \"$GIT ls-tree -z $hash\" or die_error(undef, \"Open git-ls-tree failed.\");\n+\topen my $fd, \"-|\", $GIT, \"ls-tree\", '-z', $hash or die_error(undef, \"Open git-ls-tree failed.\");\n \tchomp (my (@entries) = <$fd>);\n \tclose $fd or die_error(undef, \"Reading tree failed.\");\n \t$/ = \"\\n\";\n@@ -1799,7 +1800,8 @@ #\t\t\t      \" | \" . $cgi->a({-href => \"$my\n \n sub git_rss {\n \t# http://www.notestips.com/80256B3A007F2692/1/NAMO5P9UPQ\n-\topen my $fd, \"-|\", \"$GIT rev-list --max-count=150 \" . git_read_head($project) or die_error(undef, \"Open failed.\");\n+\topen my $fd, \"-|\", $GIT, \"rev-list\", \"--max-count=150\", git_read_head($project) \n+\t\tor die_error(undef, \"Open failed.\");\n \tmy (@revlist) = map { chomp; $_ } <$fd>;\n \tclose $fd or die_error(undef, \"Reading rev-list failed.\");\n \tprint $cgi->header(-type => 'text/xml', -charset => 'utf-8');\n@@ -1819,7 +1821,7 @@ sub git_rss {\n \t\t\tlast;\n \t\t}\n \t\tmy %cd = date_str($co{'committer_epoch'});\n-\t\topen $fd, \"-|\", \"$GIT diff-tree -r $co{'parent'} $co{'id'}\" or next;\n+\t\topen $fd, \"-|\", $GIT, \"diff-tree\", '-r', $co{'parent'}, $co{'id'} or next;\n \t\tmy @difftree = map { chomp; $_ } <$fd>;\n \t\tclose $fd or next;\n \t\tprint \"<item>\\n\" .\n@@ -1907,7 +1909,7 @@ sub git_log {\n \t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=tree;h=$hash;hb=$hash\")}, \"tree\") . \"<br/>\\n\";\n \n \tmy $limit = sprintf(\"--max-count=%i\", (100 * ($page+1)));\n-\topen my $fd, \"-|\", \"$GIT rev-list $limit $hash\" or die_error(undef, \"Open failed.\");\n+\topen my $fd, \"-|\", $GIT, \"rev-list\", $limit, $hash or die_error(undef, \"Open failed.\");\n \tmy (@revlist) = map { chomp; $_ } <$fd>;\n \tclose $fd;\n \n@@ -1998,7 +2000,8 @@ sub git_commit {\n \t\t$root = \" --root\";\n \t\t$parent = \"\";\n \t}\n-\topen my $fd, \"-|\", \"$GIT diff-tree -r -M $root $parent $hash\" or die_error(undef, \"Open failed.\");\n+\topen my $fd, \"-|\", $GIT, \"diff-tree\", '-r', '-M', $root, $parent, $hash \n+\t\tor die_error(undef, \"Open failed.\");\n \t@difftree = map { chomp; $_ } <$fd>;\n \tclose $fd or die_error(undef, \"Reading diff-tree failed.\");\n \n@@ -2244,7 +2247,8 @@ sub git_commitdiff {\n \tif (!defined $hash_parent) {\n \t\t$hash_parent = $co{'parent'};\n \t}\n-\topen my $fd, \"-|\", \"$GIT diff-tree -r $hash_parent $hash\" or die_error(undef, \"Open failed.\");\n+\topen my $fd, \"-|\", $GIT, \"diff-tree\", '-r', $hash_parent, $hash\n+\t\tor die_error(undef, \"Open failed.\");\n \tmy (@difftree) = map { chomp; $_ } <$fd>;\n \tclose $fd or die_error(undef, \"Reading diff-tree failed.\");\n \n@@ -2334,14 +2338,15 @@ sub git_commitdiff {\n \n sub git_commitdiff_plain {\n \tmkdir($git_temp, 0700);\n-\topen my $fd, \"-|\", \"$GIT diff-tree -r $hash_parent $hash\" or die_error(undef, \"Open failed.\");\n+\topen my $fd, \"-|\", $GIT, \"diff-tree\", '-r', $hash_parent, $hash \n+\t\tor die_error(undef, \"Open failed.\");\n \tmy (@difftree) = map { chomp; $_ } <$fd>;\n \tclose $fd or die_error(undef, \"Reading diff-tree failed.\");\n \n \t# try to figure out the next tag after this commit\n \tmy $tagname;\n \tmy $refs = read_info_ref(\"tags\");\n-\topen $fd, \"-|\", \"$GIT rev-list HEAD\";\n+\topen $fd, \"-|\", $GIT, \"rev-list\", \"HEAD\";\n \tchomp (my (@commits) = <$fd>);\n \tclose $fd;\n \tforeach my $commit (@commits) {\n@@ -2419,7 +2424,7 @@ sub git_history {\n \tgit_print_page_path($file_name, $ftype);\n \n \topen my $fd, \"-|\",\n-\t\t\"$GIT rev-list --full-history $hash_base -- \\'$file_name\\'\";\n+\t\t$GIT, \"rev-list\", \"--full-history\", $hash_base, \"--\", \"\\'$file_name\\'\";\n \tprint \"<table cellspacing=\\\"0\\\">\\n\";\n \tmy $alternate = 0;\n \twhile (my $line = <$fd>) {\n@@ -2506,7 +2511,7 @@ sub git_search {\n \tmy $alternate = 0;\n \tif ($commit_search) {\n \t\t$/ = \"\\0\";\n-\t\topen my $fd, \"-|\", \"$GIT rev-list --header --parents $hash\" or next;\n+\t\topen my $fd, \"-|\", $GIT, \"rev-list\", \"--header\", \"--parents\", $hash or next;\n \t\twhile (my $commit_text = <$fd>) {\n \t\t\tif (!grep m/$searchtext/i, $commit_text) {\n \t\t\t\tnext;\n@@ -2627,7 +2632,7 @@ sub git_shortlog {\n \t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=tree;h=$hash;hb=$hash\")}, \"tree\") . \"<br/>\\n\";\n \n \tmy $limit = sprintf(\"--max-count=%i\", (100 * ($page+1)));\n-\topen my $fd, \"-|\", \"$GIT rev-list $limit $hash\" or die_error(undef, \"Open failed.\");\n+\topen my $fd, \"-|\", $GIT, \"rev-list\", $limit, $hash or die_error(undef, \"Open failed.\");\n \tmy (@revlist) = map { chomp; $_ } <$fd>;\n \tclose $fd;\n \n-- \n1.4.0\n"},{"id":"24350","messageId":"200607292255.01425.jnareb@gmail.com","threadId":"5038","inReplyTo":"200607292239.11034.jnareb@gmail.com","subject":"[PATCH 3] gitweb: simplify git_get_hash_by_path","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-07-29T20:55:01Z","receivedAt":"2006-07-29T20:55:01Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Simplify git_get_hash_by_path by using git-ls-tree to do path\nlimiting, instead of finding correct ttree and parsing unconstrained\ngit-ls-tree output.\n\n_Should_ be slightly faster.\n\nSigned-off-by: Jakub Narebski <jnareb@gmail.com>\n---\nTesting speed before and after this patch using ApacheBench \non git.git repository has shown speedup withing error. Perhaps\nsample size was too small...\n\nSpeedup should be larger for deeper nested projects with larger number\nof files in a directory.\n\nNot extensively tested!\n\n gitweb/gitweb.cgi |   32 +++++++++-----------------------\n 1 files changed, 9 insertions(+), 23 deletions(-)\n\ndiff --git a/gitweb/gitweb.cgi b/gitweb/gitweb.cgi\nindex 9a17f87..e1a817b 100755\n--- a/gitweb/gitweb.cgi\n+++ b/gitweb/gitweb.cgi\n@@ -1525,29 +1525,15 @@ sub git_get_hash_by_path {\n \tmy $path = shift || return undef;\n \n \tmy $tree = $base;\n-\tmy @parts = split '/', $path;\n-\twhile (my $part = shift @parts) {\n-\t\topen my $fd, \"-|\", $GIT, \"ls-tree\", $tree or die_error(undef, \"Open git-ls-tree failed.\");\n-\t\tmy (@entries) = map { chomp; $_ } <$fd>;\n-\t\tclose $fd or return undef;\n-\t\tforeach my $line (@entries) {\n-\t\t\t#'100644\tblob\t0fa3f3a66fb6a137f6ec2c19351ed4d807070ffa\tpanic.c'\n-\t\t\t$line =~ m/^([0-9]+) (.+) ([0-9a-fA-F]{40})\\t(.+)$/;\n-\t\t\tmy $t_mode = $1;\n-\t\t\tmy $t_type = $2;\n-\t\t\tmy $t_hash = $3;\n-\t\t\tmy $t_name = validate_input(unquote($4));\n-\t\t\tif ($t_name eq $part) {\n-\t\t\t\tif (!(@parts)) {\n-\t\t\t\t\treturn $t_hash;\n-\t\t\t\t}\n-\t\t\t\tif ($t_type eq \"tree\") {\n-\t\t\t\t\t$tree = $t_hash;\n-\t\t\t\t}\n-\t\t\t\tlast;\n-\t\t\t}\n-\t\t}\n-\t}\n+\n+\topen my $fd, \"-|\", $GIT, \"ls-tree\", $base, \"--\", $path\n+\t\tor die_error(undef, \"Open git-ls-tree failed.\");\n+\tmy $line = <$fd>;\n+\tclose $fd or return undef;\n+\n+\t#'100644 blob 0fa3f3a66fb6a137f6ec2c19351ed4d807070ffa\tpanic.c'\n+\t$line =~ m/^([0-9]+) (.+) ([0-9a-fA-F]{40})\\t(.+)$/;\n+\treturn $3;\n }\n \n sub mimetype_guess_file {\n-- \n1.4.0\n"},{"id":"24351","messageId":"200607292301.01236.jnareb@gmail.com","threadId":"5038","inReplyTo":"200607292239.11034.jnareb@gmail.com","subject":"[PATCH 4] gitweb: More explicit error messages for open \"-|\"","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-07-29T21:01:00Z","receivedAt":"2006-07-29T21:01:00Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Use more explicit error messages when failing magical \"-|\" open,\nstating at least the name of the git command that failed.\n\nSigned-off-by: Jakub Narebski <jnareb@gmail.com>\n---\nShould not affect web security.\n\n gitweb/gitweb.cgi |   29 +++++++++++++++++------------\n 1 files changed, 17 insertions(+), 12 deletions(-)\n\ndiff --git a/gitweb/gitweb.cgi b/gitweb/gitweb.cgi\nindex e1a817b..2c67df0 100755\n--- a/gitweb/gitweb.cgi\n+++ b/gitweb/gitweb.cgi\n@@ -1063,7 +1063,7 @@ sub git_summary {\n \t      \"<tr><td>last change</td><td>$cd{'rfc2822'}</td></tr>\\n\" .\n \t      \"</table>\\n\";\n \topen my $fd, \"-|\", $GIT, \"rev-list\", \"--max-count=17\", git_read_head($project) \n-\t\tor die_error(undef, \"Open failed.\");\n+\t\tor die_error(undef, \"Open git-rev-list failed.\");\n \tmy (@revlist) = map { chomp; $_ } <$fd>;\n \tclose $fd;\n \tprint \"<div>\\n\" .\n@@ -1271,7 +1271,7 @@ sub git_blame2 {\n \t\tdie_error(\"400 Bad Request\", \"object is not a blob\");\n \t}\n \topen ($fd, \"-|\", $GIT, \"blame\", '-l', $file_name, $hash_base)\n-\t\tor die_error(undef, \"Open failed\");\n+\t\tor die_error(undef, \"Open git-blame 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@@ -1333,7 +1333,7 @@ sub git_blame {\n \t\t\tor die_error(undef, \"Error lookup file.\");\n \t}\n \topen ($fd, \"-|\", $GIT, \"annotate\", '-l', '-t', '-r', $file_name, $hash_base)\n-\t\tor die_error(undef, \"Open failed.\");\n+\t\tor die_error(undef, \"Open git-annotate 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@@ -1609,7 +1609,8 @@ sub git_blob_plain {\n \t\t}\n \t}\n \tmy $type = shift;\n-\topen my $fd, \"-|\", $GIT, \"cat-file\", \"blob\", $hash or die_error(\"Couldn't cat $file_name, $hash\");\n+\topen my $fd, \"-|\", $GIT, \"cat-file\", \"blob\", $hash \n+\t\tor die_error(\"Couldn't cat $file_name, $hash\");\n \n \t$type ||= git_blob_plain_mimetype($fd, $file_name);\n \n@@ -1641,7 +1642,8 @@ sub git_blob {\n \t\t}\n \t}\n \tmy $have_blame = git_get_project_config_bool ('blame');\n-\topen my $fd, \"-|\", $GIT, \"cat-file\", \"blob\", $hash or die_error(undef, \"Open failed.\");\n+\topen my $fd, \"-|\", $GIT, \"cat-file\", \"blob\", $hash \n+\t\tor die_error(undef, \"Couldn't cat $file_name, $hash.\");\n \tmy $mimetype = git_blob_plain_mimetype($fd, $file_name);\n \tif ($mimetype !~ m/^text\\//) {\n \t\tclose $fd;\n@@ -1705,7 +1707,8 @@ sub git_tree {\n \t\t}\n \t}\n \t$/ = \"\\0\";\n-\topen my $fd, \"-|\", $GIT, \"ls-tree\", '-z', $hash or die_error(undef, \"Open git-ls-tree failed.\");\n+\topen my $fd, \"-|\", $GIT, \"ls-tree\", '-z', $hash \n+\t\tor die_error(undef, \"Open git-ls-tree failed.\");\n \tchomp (my (@entries) = <$fd>);\n \tclose $fd or die_error(undef, \"Reading tree failed.\");\n \t$/ = \"\\n\";\n@@ -1787,7 +1790,7 @@ #\t\t\t      \" | \" . $cgi->a({-href => \"$my\n sub git_rss {\n \t# http://www.notestips.com/80256B3A007F2692/1/NAMO5P9UPQ\n \topen my $fd, \"-|\", $GIT, \"rev-list\", \"--max-count=150\", git_read_head($project) \n-\t\tor die_error(undef, \"Open failed.\");\n+\t\tor die_error(undef, \"Open git-rev-list failed.\");\n \tmy (@revlist) = map { chomp; $_ } <$fd>;\n \tclose $fd or die_error(undef, \"Reading rev-list failed.\");\n \tprint $cgi->header(-type => 'text/xml', -charset => 'utf-8');\n@@ -1895,7 +1898,8 @@ sub git_log {\n \t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=tree;h=$hash;hb=$hash\")}, \"tree\") . \"<br/>\\n\";\n \n \tmy $limit = sprintf(\"--max-count=%i\", (100 * ($page+1)));\n-\topen my $fd, \"-|\", $GIT, \"rev-list\", $limit, $hash or die_error(undef, \"Open failed.\");\n+\topen my $fd, \"-|\", $GIT, \"rev-list\", $limit, $hash \n+\t\tor die_error(undef, \"Open git-rev-list failed.\");\n \tmy (@revlist) = map { chomp; $_ } <$fd>;\n \tclose $fd;\n \n@@ -1987,7 +1991,7 @@ sub git_commit {\n \t\t$parent = \"\";\n \t}\n \topen my $fd, \"-|\", $GIT, \"diff-tree\", '-r', '-M', $root, $parent, $hash \n-\t\tor die_error(undef, \"Open failed.\");\n+\t\tor die_error(undef, \"Open git-diff-tree failed.\");\n \t@difftree = map { chomp; $_ } <$fd>;\n \tclose $fd or die_error(undef, \"Reading diff-tree failed.\");\n \n@@ -2234,7 +2238,7 @@ sub git_commitdiff {\n \t\t$hash_parent = $co{'parent'};\n \t}\n \topen my $fd, \"-|\", $GIT, \"diff-tree\", '-r', $hash_parent, $hash\n-\t\tor die_error(undef, \"Open failed.\");\n+\t\tor die_error(undef, \"Open git-diff-tree failed.\");\n \tmy (@difftree) = map { chomp; $_ } <$fd>;\n \tclose $fd or die_error(undef, \"Reading diff-tree failed.\");\n \n@@ -2325,7 +2329,7 @@ sub git_commitdiff {\n sub git_commitdiff_plain {\n \tmkdir($git_temp, 0700);\n \topen my $fd, \"-|\", $GIT, \"diff-tree\", '-r', $hash_parent, $hash \n-\t\tor die_error(undef, \"Open failed.\");\n+\t\tor die_error(undef, \"Open git-diff-tree failed.\");\n \tmy (@difftree) = map { chomp; $_ } <$fd>;\n \tclose $fd or die_error(undef, \"Reading diff-tree failed.\");\n \n@@ -2618,7 +2622,8 @@ sub git_shortlog {\n \t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=tree;h=$hash;hb=$hash\")}, \"tree\") . \"<br/>\\n\";\n \n \tmy $limit = sprintf(\"--max-count=%i\", (100 * ($page+1)));\n-\topen my $fd, \"-|\", $GIT, \"rev-list\", $limit, $hash or die_error(undef, \"Open failed.\");\n+\topen my $fd, \"-|\", $GIT, \"rev-list\", $limit, $hash \n+\t\tor die_error(undef, \"Open git-rev-list failed.\");\n \tmy (@revlist) = map { chomp; $_ } <$fd>;\n \tclose $fd;\n \n-- \n1.4.0\n"},{"id":"24360","messageId":"200607300408.32459.jnareb@gmail.com","threadId":"5038","inReplyTo":"200607292239.11034.jnareb@gmail.com","subject":"[PATCH 5] gitweb: Cleanup - chomp $line in consistent style","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-07-30T02:08:17Z","receivedAt":"2006-07-30T02:08:17Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Signed-off-by: Jakub Narebski <jnareb@gmail.com>\n---\n gitweb/gitweb.cgi |    4 ++--\n 1 files changed, 2 insertions(+), 2 deletions(-)\n\ndiff --git a/gitweb/gitweb.cgi b/gitweb/gitweb.cgi\nindex 2c67df0..e1f0e26 100755\n--- a/gitweb/gitweb.cgi\n+++ b/gitweb/gitweb.cgi\n@@ -635,7 +635,7 @@ sub git_diff_print {\n \t\t$/ = \"\\n\";\n \t} else {\n \t\twhile (my $line = <$fd>) {\n-\t\t\tchomp($line);\n+\t\t\tchomp $line;\n \t\t\tmy $char = substr($line, 0, 1);\n \t\t\tmy $diff_class = \"\";\n \t\t\tif ($char eq '+') {\n@@ -944,7 +944,7 @@ sub read_info_ref {\n \t# c39ae07f393806ccf406ef966e9a15afc43cc36a\trefs/tags/v2.6.11^{}\n \topen my $fd, \"$projectroot/$project/info/refs\" or return;\n \twhile (my $line = <$fd>) {\n-\t\tchomp($line);\n+\t\tchomp $line;\n \t\tif ($line =~ m/^([0-9a-fA-F]{40})\\t.*$type\\/([^\\^]+)/) {\n \t\t\tif (defined $refs{$1}) {\n \t\t\t\t$refs{$1} .= \" / $2\";\n-- \n1.4.0\n"},{"id":"24361","messageId":"200607300411.12766.jnareb@gmail.com","threadId":"5038","inReplyTo":"200607292239.11034.jnareb@gmail.com","subject":"[PATCH 6] gitweb: Correct error from changing \"-|\" open to list form in git_commit","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-07-30T02:11:10Z","receivedAt":"2006-07-30T02:11:10Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Correct error in moving to list form of open for running git commands\nand reading their output through pipe (PATCH 2 in series) in\ngit_commit subroutine.\n\nSigned-off-by: Jakub Narebski <jnareb@gmail.com>\n---\nIt also simplifies git_commit a tiny bit.\n\n gitweb/gitweb.cgi |    8 +++-----\n 1 files changed, 3 insertions(+), 5 deletions(-)\n\ndiff --git a/gitweb/gitweb.cgi b/gitweb/gitweb.cgi\nindex e1f0e26..86b9547 100755\n--- a/gitweb/gitweb.cgi\n+++ b/gitweb/gitweb.cgi\n@@ -1984,16 +1984,14 @@ sub git_commit {\n \tmy %cd = date_str($co{'committer_epoch'}, $co{'committer_tz'});\n \n \tmy @difftree;\n-\tmy $root = \"\";\n \tmy $parent = $co{'parent'};\n \tif (!defined $parent) {\n-\t\t$root = \" --root\";\n-\t\t$parent = \"\";\n+\t\t$parent = \"--root\";\n \t}\n-\topen my $fd, \"-|\", $GIT, \"diff-tree\", '-r', '-M', $root, $parent, $hash \n+\topen my $fd, \"-|\", $GIT, \"diff-tree\", '-r', '-M', $parent, $hash \n \t\tor die_error(undef, \"Open git-diff-tree failed.\");\n \t@difftree = map { chomp; $_ } <$fd>;\n-\tclose $fd or die_error(undef, \"Reading diff-tree failed.\");\n+\tclose $fd or die_error(undef, \"Reading git-diff-tree failed.\");\n \n \t# non-textual hash id's can be cached\n \tmy $expires;\n-- \n1.4.0\n"},{"id":"24362","messageId":"200607300412.04545.jnareb@gmail.com","threadId":"5038","inReplyTo":"200607292251.21072.jnareb@gmail.com","subject":"Re: [PATCH 2] gitweb: Use list for of open for running git commands, thorougly.","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-07-30T02:12:04Z","receivedAt":"2006-07-30T02:12:04Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"This patch introduces error in git_commit, corrected in [PATCH 6].\n-- \nJakub Narebski\n"},{"id":"24367","messageId":"200607301458.13848.jnareb@gmail.com","threadId":"5038","inReplyTo":"200607292239.11034.jnareb@gmail.com","subject":"[PATCH 7] gitweb: Cleanup - chomp @lines in consistent style","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-07-30T12:58:11Z","receivedAt":"2006-07-30T12:58:11Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Use 'my @lines = map { chomp; $_ } <$fd>;' form to read all lines of\ngit command output into array without trailing newlines.\n\nIt has advantage over 'chomp (my (@lines) = <$fd>);' in that it does\nnot modify array.\n\nSigned-off-by: Jakub Narebski <jnareb@gmail.com>\n---\n gitweb/gitweb.cgi |   19 +++++++++----------\n 1 files changed, 9 insertions(+), 10 deletions(-)\n\ndiff --git a/gitweb/gitweb.cgi b/gitweb/gitweb.cgi\nindex 86b9547..d5248fe 100755\n--- a/gitweb/gitweb.cgi\n+++ b/gitweb/gitweb.cgi\n@@ -1064,7 +1064,7 @@ sub git_summary {\n \t      \"</table>\\n\";\n \topen my $fd, \"-|\", $GIT, \"rev-list\", \"--max-count=17\", git_read_head($project) \n \t\tor die_error(undef, \"Open git-rev-list failed.\");\n-\tmy (@revlist) = map { chomp; $_ } <$fd>;\n+\tmy @revlist = map { chomp; $_ } <$fd>;\n \tclose $fd;\n \tprint \"<div>\\n\" .\n \t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=shortlog\"), -class => \"title\"}, \"shortlog\") .\n@@ -1709,7 +1709,7 @@ sub git_tree {\n \t$/ = \"\\0\";\n \topen my $fd, \"-|\", $GIT, \"ls-tree\", '-z', $hash \n \t\tor die_error(undef, \"Open git-ls-tree failed.\");\n-\tchomp (my (@entries) = <$fd>);\n+\tmy @entries = map { chomp; $_ } <$fd>;\n \tclose $fd or die_error(undef, \"Reading tree failed.\");\n \t$/ = \"\\n\";\n \n@@ -1791,7 +1791,7 @@ sub git_rss {\n \t# http://www.notestips.com/80256B3A007F2692/1/NAMO5P9UPQ\n \topen my $fd, \"-|\", $GIT, \"rev-list\", \"--max-count=150\", git_read_head($project) \n \t\tor die_error(undef, \"Open git-rev-list failed.\");\n-\tmy (@revlist) = map { chomp; $_ } <$fd>;\n+\tmy @revlist = map { chomp; $_ } <$fd>;\n \tclose $fd or die_error(undef, \"Reading rev-list failed.\");\n \tprint $cgi->header(-type => 'text/xml', -charset => 'utf-8');\n \tprint \"<?xml version=\\\"1.0\\\" encoding=\\\"utf-8\\\"?>\\n\".\n@@ -1900,7 +1900,7 @@ sub git_log {\n \tmy $limit = sprintf(\"--max-count=%i\", (100 * ($page+1)));\n \topen my $fd, \"-|\", $GIT, \"rev-list\", $limit, $hash \n \t\tor die_error(undef, \"Open git-rev-list failed.\");\n-\tmy (@revlist) = map { chomp; $_ } <$fd>;\n+\tmy @revlist = map { chomp; $_ } <$fd>;\n \tclose $fd;\n \n \tif ($hash ne $head || $page) {\n@@ -1983,14 +1983,13 @@ sub git_commit {\n \tmy %ad = date_str($co{'author_epoch'}, $co{'author_tz'});\n \tmy %cd = date_str($co{'committer_epoch'}, $co{'committer_tz'});\n \n-\tmy @difftree;\n \tmy $parent = $co{'parent'};\n \tif (!defined $parent) {\n \t\t$parent = \"--root\";\n \t}\n \topen my $fd, \"-|\", $GIT, \"diff-tree\", '-r', '-M', $parent, $hash \n \t\tor die_error(undef, \"Open git-diff-tree failed.\");\n-\t@difftree = map { chomp; $_ } <$fd>;\n+\tmy @difftree = map { chomp; $_ } <$fd>;\n \tclose $fd or die_error(undef, \"Reading git-diff-tree failed.\");\n \n \t# non-textual hash id's can be cached\n@@ -2237,7 +2236,7 @@ sub git_commitdiff {\n \t}\n \topen my $fd, \"-|\", $GIT, \"diff-tree\", '-r', $hash_parent, $hash\n \t\tor die_error(undef, \"Open git-diff-tree failed.\");\n-\tmy (@difftree) = map { chomp; $_ } <$fd>;\n+\tmy @difftree = map { chomp; $_ } <$fd>;\n \tclose $fd or die_error(undef, \"Reading diff-tree failed.\");\n \n \t# non-textual hash id's can be cached\n@@ -2328,14 +2327,14 @@ sub git_commitdiff_plain {\n \tmkdir($git_temp, 0700);\n \topen my $fd, \"-|\", $GIT, \"diff-tree\", '-r', $hash_parent, $hash \n \t\tor die_error(undef, \"Open git-diff-tree failed.\");\n-\tmy (@difftree) = map { chomp; $_ } <$fd>;\n+\tmy @difftree = map { chomp; $_ } <$fd>;\n \tclose $fd or die_error(undef, \"Reading diff-tree failed.\");\n \n \t# try to figure out the next tag after this commit\n \tmy $tagname;\n \tmy $refs = read_info_ref(\"tags\");\n \topen $fd, \"-|\", $GIT, \"rev-list\", \"HEAD\";\n-\tchomp (my (@commits) = <$fd>);\n+\tmy @commits = map { chomp; $_ } <$fd>;\n \tclose $fd;\n \tforeach my $commit (@commits) {\n \t\tif (defined $refs->{$commit}) {\n@@ -2622,7 +2621,7 @@ sub git_shortlog {\n \tmy $limit = sprintf(\"--max-count=%i\", (100 * ($page+1)));\n \topen my $fd, \"-|\", $GIT, \"rev-list\", $limit, $hash \n \t\tor die_error(undef, \"Open git-rev-list failed.\");\n-\tmy (@revlist) = map { chomp; $_ } <$fd>;\n+\tmy @revlist = map { chomp; $_ } <$fd>;\n \tclose $fd;\n \n \tif ($hash ne $head || $page) {\n-- \n1.4.0\n"},{"id":"24368","messageId":"200607301459.58032.jnareb@gmail.com","threadId":"5038","inReplyTo":"200607292239.11034.jnareb@gmail.com","subject":"[PATCH 8] gitweb: Add git_page_nav for later use","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-07-30T12:59:57Z","receivedAt":"2006-07-30T12:59:57Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Adds git_page_nav subroutine to factors out the generation of the\nnavigation bar.  Based on Sven Verdoolaege code\n  Message-Id: <20050618113121.GA13122@pc117b.liacs.nl>\n  http://marc.theaimsgroup.com/?l=git&m=111909432415478&w=2\n\nI tried for the refactored navbar generate the same result.\n\nSigned-off-by: Jakub Narebski <jnareb@gmail.com>\n---\n gitweb/gitweb.cgi |   34 ++++++++++++++++++++++++++++++++++\n 1 files changed, 34 insertions(+), 0 deletions(-)\n\ndiff --git a/gitweb/gitweb.cgi b/gitweb/gitweb.cgi\nindex d5248fe..2bc3445 100755\n--- a/gitweb/gitweb.cgi\n+++ b/gitweb/gitweb.cgi\n@@ -385,6 +385,40 @@ sub die_error {\n \texit;\n }\n \n+sub git_page_nav {\n+\tmy ($current, $suppress, $head, $treehead, $treebase, $extra) = @_;\n+\t$extra = '' if !defined $extra; # pager or formats\n+\n+\tmy @navs = qw(summary shortlog log commit commitdiff tree);\n+\tif ($suppress) {\n+\t\t@navs = grep { $_ ne $suppress } @navs;\n+\t}\n+\n+\tmy %arg = map { $_, ''} @navs;\n+\tif (defined $head) {\n+\t\tfor (qw(commit commitdiff)) {\n+\t\t\t$arg{$_} = \";h=$head\";\n+\t\t}\n+\t\tif ($current =~ m/^(tree | log | shortlog | commit | commitdiff | search)$/x) {\n+\t\t\tfor (qw(shortlog log)) {\n+\t\t\t\t$arg{$_} = \";h=$head\";\n+\t\t\t}\n+\t\t}\n+\t}\n+\t$arg{tree} .= \";h=$treehead\" if defined $treehead;\n+\t$arg{tree} .= \";hb=$treebase\" if defined $treebase;\n+\n+\tprint \"<div class=\\\"page_nav\\\">\\n\" .\n+\t\t(join \" | \",\n+\t\t map { $_ eq $current\n+\t\t\t\t\t ? $_\n+\t\t\t\t\t : $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=$_$arg{$_}\")}, \"$_\")\n+\t\t\t\t }\n+\t\t @navs);\n+\tprint \"<br/>$extra<br/>\\n\" .\n+\t      \"</div>\\n\";\n+}\n+\n sub git_get_type {\n \tmy $hash = shift;\n \n-- \n1.4.0\n"},{"id":"24369","messageId":"200607301501.08175.jnareb@gmail.com","threadId":"5038","inReplyTo":"200607292239.11034.jnareb@gmail.com","subject":"[PATCH 9] gitweb: Navbar refactoring - use git_page_nav to generate navigation bar","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-07-30T13:01:07Z","receivedAt":"2006-07-30T13:01:07Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Use git_page_nav subroutine to generate navigation bar.  Additional\nnavigation (either formats or pager/pagination) is put into variables.\n\nCorrects error in git_search where hash parameter was added to\n\"summary\" link instead of to \"log\" link.  Might differ from previous\nversion by additional \"<br/>\" in navigation bar.\n\nSigned-off-by: Jakub Narebski <jnareb@gmail.com>\n---\n gitweb/gitweb.cgi |  235 +++++++++++++++--------------------------------------\n 1 files changed, 66 insertions(+), 169 deletions(-)\n\ndiff --git a/gitweb/gitweb.cgi b/gitweb/gitweb.cgi\nindex 2bc3445..6c72d33 100755\n--- a/gitweb/gitweb.cgi\n+++ b/gitweb/gitweb.cgi\n@@ -1081,15 +1081,7 @@ sub git_summary {\n \n \tmy $refs = read_info_ref();\n \tgit_header_html();\n-\tprint \"<div class=\\\"page_nav\\\">\\n\" .\n-\t      \"summary\".\n-\t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=shortlog\")}, \"shortlog\") .\n-\t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=log\")}, \"log\") .\n-\t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=commit;h=$head\")}, \"commit\") .\n-\t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=commitdiff;h=$head\")}, \"commitdiff\") .\n-\t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=tree\")}, \"tree\") .\n-\t      \"<br/><br/>\\n\" .\n-\t      \"</div>\\n\";\n+\tgit_page_nav('summary','', $head);\n \tprint \"<div class=\\\"title\\\">&nbsp;</div>\\n\";\n \tprint \"<table cellspacing=\\\"0\\\">\\n\" .\n \t      \"<tr><td>description</td><td>\" . esc_html($descr) . \"</td></tr>\\n\" .\n@@ -1251,15 +1243,7 @@ sub git_print_page_path {\n sub git_tag {\n \tmy $head = git_read_head($project);\n \tgit_header_html();\n-\tprint \"<div class=\\\"page_nav\\\">\\n\" .\n-\t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=summary\")}, \"summary\") .\n-\t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=shortlog\")}, \"shortlog\") .\n-\t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=log\")}, \"log\") .\n-\t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=commit;h=$head\")}, \"commit\") .\n-\t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=commitdiff;h=$head\")}, \"commitdiff\") .\n-\t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=tree;hb=$head\")}, \"tree\") . \"<br/>\\n\" .\n-\t      \"<br/>\\n\" .\n-\t      \"</div>\\n\";\n+\tgit_page_nav('','', $head,undef,$head);\n \tmy %tag = git_read_tag($hash);\n \tprint \"<div>\\n\" .\n \t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=commit;h=$hash\"), -class => \"title\"}, esc_html($tag{'name'})) . \"\\n\" .\n@@ -1307,19 +1291,13 @@ sub git_blame2 {\n \topen ($fd, \"-|\", $GIT, \"blame\", '-l', $file_name, $hash_base)\n \t\tor die_error(undef, \"Open git-blame 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+\tmy $formats_nav = \n+\t\t$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\");\n+\tgit_page_nav('','', $hash_base,$co{'tree'},$hash_base, $formats_nav);\n+\tprint \"<div>\" .\n+\t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=commit;h=$hash_base\"), -class => \"title\"}, esc_html($co{'title'})) .\n+\t      \"</div>\\n\";\n \tgit_print_page_path($file_name, $ftype);\n \tmy @rev_color = (qw(light dark));\n \tmy $num_colors = scalar(@rev_color);\n@@ -1369,19 +1347,13 @@ sub git_blame {\n \topen ($fd, \"-|\", $GIT, \"annotate\", '-l', '-t', '-r', $file_name, $hash_base)\n \t\tor die_error(undef, \"Open git-annotate 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+\tmy $formats_nav = \n+\t\t$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\");\n+\tgit_page_nav('','', $hash_base,$co{'tree'},$hash_base, $formats_nav);\n+\tprint \"<div>\" .\n+\t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=commit;h=$hash_base\"), -class => \"title\"}, esc_html($co{'title'})) .\n+\t      \"</div>\\n\";\n \tgit_print_page_path($file_name);\n \tprint \"<div class=\\\"page_body\\\">\\n\";\n \tprint <<HTML;\n@@ -1456,15 +1428,7 @@ HTML\n sub git_tags {\n \tmy $head = git_read_head($project);\n \tgit_header_html();\n-\tprint \"<div class=\\\"page_nav\\\">\\n\" .\n-\t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=summary\")}, \"summary\") .\n-\t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=shortlog\")}, \"shortlog\") .\n-\t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=log\")}, \"log\") .\n-\t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=commit;h=$head\")}, \"commit\") .\n-\t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=commitdiff;h=$head\")}, \"commitdiff\") .\n-\t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=tree;hb=$head\")}, \"tree\") . \"<br/>\\n\" .\n-\t      \"<br/>\\n\" .\n-\t      \"</div>\\n\";\n+\tgit_page_nav('','', $head,undef,$head);\n \tmy $taglist = git_read_refs(\"refs/tags\");\n \tprint \"<div>\\n\" .\n \t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=summary\"), -class => \"title\"}, \"&nbsp;\") .\n@@ -1515,15 +1479,7 @@ sub git_tags {\n sub git_heads {\n \tmy $head = git_read_head($project);\n \tgit_header_html();\n-\tprint \"<div class=\\\"page_nav\\\">\\n\" .\n-\t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=summary\")}, \"summary\") .\n-\t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=shortlog\")}, \"shortlog\") .\n-\t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=log\")}, \"log\") .\n-\t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=commit;h=$head\")}, \"commit\") .\n-\t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=commitdiff;h=$head\")}, \"commitdiff\") .\n-\t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=tree;hb=$head\")}, \"tree\") . \"<br/>\\n\" .\n-\t      \"<br/>\\n\" .\n-\t      \"</div>\\n\";\n+\tgit_page_nav('','', $head,undef,$head);\n \tmy $taglist = git_read_refs(\"refs/heads\");\n \tprint \"<div>\\n\" .\n \t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=summary\"), -class => \"title\"}, \"&nbsp;\") .\n@@ -1684,25 +1640,20 @@ sub git_blob {\n \t\treturn git_blob_plain($mimetype);\n \t}\n \tgit_header_html();\n+\tmy $formats_nav = '';\n \tif (defined $hash_base && (my %co = git_read_commit($hash_base))) {\n-\t\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 \t\tif (defined $file_name) {\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\t$formats_nav .= $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\t$formats_nav .=\n+\t\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\t\" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=blob;hb=HEAD;f=$file_name\")}, \"head\");\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+\t\t\t$formats_nav .= $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=blob_plain;h=$hash\")}, \"plain\");\n \t\t}\n-\t\tprint \"</div>\\n\".\n-\t\t      \"<div>\" .\n+\t\tgit_page_nav('','', $hash_base,$co{'tree'},$hash_base, $formats_nav);\n+\t\tprint \"<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 \t} else {\n@@ -1757,15 +1708,7 @@ sub git_tree {\n \tmy $base = \"\";\n \tif (defined $hash_base && (my %co = git_read_commit($hash_base))) {\n \t\t$base_key = \";hb=$hash_base\";\n-\t\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;h=$hash_base\")}, \"shortlog\") .\n-\t\t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=log;h=$hash_base\")}, \"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      \" | tree\" .\n-\t\t      \"<br/><br/>\\n\" .\n-\t\t      \"</div>\\n\";\n+\t\tgit_page_nav('tree','', $hash_base);\n \t\tprint \"<div>\\n\" .\n \t\t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=commit;h=$hash_base\"), -class => \"title\"}, esc_html($co{'title'}) . $ref) . \"\\n\" .\n \t\t      \"</div>\\n\";\n@@ -1922,14 +1865,6 @@ sub git_log {\n \t\t$page = 0;\n \t}\n \tmy $refs = read_info_ref();\n-\tgit_header_html();\n-\tprint \"<div class=\\\"page_nav\\\">\\n\";\n-\tprint $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=summary\")}, \"summary\") .\n-\t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=shortlog;h=$hash\")}, \"shortlog\") .\n-\t      \" | log\" .\n-\t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=commit;h=$hash\")}, \"commit\") .\n-\t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=commitdiff;h=$hash\")}, \"commitdiff\") .\n-\t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=tree;h=$hash;hb=$hash\")}, \"tree\") . \"<br/>\\n\";\n \n \tmy $limit = sprintf(\"--max-count=%i\", (100 * ($page+1)));\n \topen my $fd, \"-|\", $GIT, \"rev-list\", $limit, $hash \n@@ -1937,25 +1872,28 @@ sub git_log {\n \tmy @revlist = map { chomp; $_ } <$fd>;\n \tclose $fd;\n \n+\tmy $paging_nav = '';\n \tif ($hash ne $head || $page) {\n-\t\tprint $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=log\")}, \"HEAD\");\n+\t\t$paging_nav .= $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=log\")}, \"HEAD\");\n \t} else {\n-\t\tprint \"HEAD\";\n+\t\t$paging_nav .= \"HEAD\";\n \t}\n \tif ($page > 0) {\n-\t\tprint \" &sdot; \" .\n-\t\t$cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=log;h=$hash;pg=\" . ($page-1)), -accesskey => \"p\", -title => \"Alt-p\"}, \"prev\");\n+\t\t$paging_nav .= \" &sdot; \" .\n+\t\t\t$cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=log;h=$hash;pg=\" . ($page-1)), -accesskey => \"p\", -title => \"Alt-p\"}, \"prev\");\n \t} else {\n-\t\tprint \" &sdot; prev\";\n+\t\t$paging_nav .= \" &sdot; prev\";\n \t}\n \tif ($#revlist >= (100 * ($page+1)-1)) {\n-\t\tprint \" &sdot; \" .\n-\t\t$cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=log;h=$hash;pg=\" . ($page+1)), -accesskey => \"n\", -title => \"Alt-n\"}, \"next\");\n+\t\t$paging_nav .= \" &sdot; \" .\n+\t\t\t$cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=log;h=$hash;pg=\" . ($page+1)), -accesskey => \"n\", -title => \"Alt-n\"}, \"next\");\n \t} else {\n-\t\tprint \" &sdot; next\";\n+\t\t$paging_nav .= \" &sdot; next\";\n \t}\n-\tprint \"<br/>\\n\" .\n-\t      \"</div>\\n\";\n+\n+\tgit_header_html();\n+\tgit_page_nav('log','', $hash,undef,undef, $paging_nav);\n+\n \tif (!@revlist) {\n \t\tprint \"<div>\\n\" .\n \t\t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=summary\"), -class => \"title\"}, \"&nbsp;\") .\n@@ -2037,21 +1975,14 @@ sub git_commit {\n \t\t$ref = \" <span class=\\\"tag\\\">\" . esc_html($refs->{$co{'id'}}) . \"</span>\";\n \t}\n \tgit_header_html(undef, $expires);\n-\tprint \"<div class=\\\"page_nav\\\">\\n\" .\n-\t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=summary\")}, \"summary\") .\n-\t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=shortlog;h=$hash\")}, \"shortlog\") .\n-\t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=log;h=$hash\")}, \"log\") .\n-\t      \" | commit\";\n-\tif (defined $co{'parent'}) {\n-\t\tprint \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=commitdiff;h=$hash\")}, \"commitdiff\");\n-\t}\n-\tprint \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=tree;h=$co{'tree'};hb=$hash\")}, \"tree\") . \"\\n\" .\n-\t\t\"<br/>\\n\";\n+\tmy $formats_nav = '';\n \tif (defined $file_name && defined $co{'parent'}) {\n \t\tmy $parent = $co{'parent'};\n-\t\tprint $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=blame;hb=$parent;f=$file_name\")}, \"blame\") . \"\\n\";\n+\t\t$formats_nav .= $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=blame;hb=$parent;f=$file_name\")}, \"blame\");\n \t}\n-\tprint \"<br/></div>\\n\";\n+\tgit_page_nav('commit', defined $co{'parent'} ? '' : 'commitdiff', \n+\t\t\t\t\t\t\t $hash, $co{'tree'}, $hash,\n+\t\t\t\t\t\t\t $formats_nav);\n \n \tif (defined $co{'parent'}) {\n \t\tprint \"<div>\\n\" .\n@@ -2223,16 +2154,9 @@ sub git_blobdiff {\n \tmkdir($git_temp, 0700);\n \tgit_header_html();\n \tif (defined $hash_base && (my %co = git_read_commit($hash_base))) {\n-\t\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\") .\n-\t\t      \"<br/>\\n\";\n-\t\tprint $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=blobdiff_plain;h=$hash;hp=$hash_parent\")}, \"plain\") .\n-\t\t      \"</div>\\n\";\n+\t\tmy $formats_nav = \n+\t\t\t$cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=blobdiff_plain;h=$hash;hp=$hash_parent\")}, \"plain\");\n+\t\tgit_page_nav('','', $hash_base,$co{'tree'},$hash_base, $formats_nav);\n \t\tprint \"<div>\\n\" .\n \t\t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=commit;h=$hash_base\"), -class => \"title\"}, esc_html($co{'title'})) . \"\\n\" .\n \t\t      \"</div>\\n\";\n@@ -2284,15 +2208,9 @@ sub git_commitdiff {\n \t\t$ref = \" <span class=\\\"tag\\\">\" . esc_html($refs->{$co{'id'}}) . \"</span>\";\n \t}\n \tgit_header_html(undef, $expires);\n-\tprint \"<div class=\\\"page_nav\\\">\\n\" .\n-\t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=summary\")}, \"summary\") .\n-\t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=shortlog;h=$hash\")}, \"shortlog\") .\n-\t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=log;h=$hash\")}, \"log\") .\n-\t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=commit;h=$hash\")}, \"commit\") .\n-\t      \" | commitdiff\" .\n-\t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=tree;h=$co{'tree'};hb=$hash\")}, \"tree\") . \"<br/>\\n\";\n-\tprint $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=commitdiff_plain;h=$hash;hp=$hash_parent\")}, \"plain\") . \"\\n\" .\n-\t      \"</div>\\n\";\n+\tmy $formats_nav =\n+\t\t$cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=commitdiff_plain;h=$hash;hp=$hash_parent\")}, \"plain\");\n+\tgit_page_nav('commitdiff','', $hash,$co{'tree'},$hash, $formats_nav);\n \tprint \"<div>\\n\" .\n \t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=commit;h=$hash\"), -class => \"title\"}, esc_html($co{'title'}) . $ref) . \"\\n\" .\n \t      \"</div>\\n\";\n@@ -2424,15 +2342,7 @@ sub git_history {\n \t}\n \tmy $refs = read_info_ref();\n \tgit_header_html();\n-\tprint \"<div class=\\\"page_nav\\\">\\n\" .\n-\t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=summary\")}, \"summary\") .\n-\t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=shortlog\")}, \"shortlog\") .\n-\t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=log\")}, \"log\") .\n-\t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=commit;h=$hash_base\")}, \"commit\") .\n-\t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=commitdiff;h=$hash_base\")}, \"commitdiff\") .\n-\t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=tree;h=$co{'tree'};hb=$hash_base\")}, \"tree\") .\n-\t      \"<br/><br/>\\n\" .\n-\t      \"</div>\\n\";\n+\tgit_page_nav('','', $hash_base,$co{'tree'},$hash_base);\n \tprint \"<div>\\n\" .\n \t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=commit;h=$hash_base\"), -class => \"title\"}, esc_html($co{'title'})) . \"\\n\" .\n \t      \"</div>\\n\";\n@@ -2515,15 +2425,7 @@ sub git_search {\n \t\t$pickaxe_search = 1;\n \t}\n \tgit_header_html();\n-\tprint \"<div class=\\\"page_nav\\\">\\n\" .\n-\t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=summary;h=$hash\")}, \"summary\") .\n-\t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=shortlog\")}, \"shortlog\") .\n-\t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=log;h=$hash\")}, \"log\") .\n-\t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=commit;h=$hash\")}, \"commit\") .\n-\t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=commitdiff;h=$hash\")}, \"commitdiff\") .\n-\t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=tree;h=$co{'tree'};hb=$hash\")}, \"tree\") .\n-\t      \"<br/><br/>\\n\" .\n-\t      \"</div>\\n\";\n+\tgit_page_nav('','', $hash,$co{'tree'},$hash);\n \n \tprint \"<div>\\n\" .\n \t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=commit;h=$hash\"), -class => \"title\"}, esc_html($co{'title'})) . \"\\n\" .\n@@ -2643,14 +2545,6 @@ sub git_shortlog {\n \t\t$page = 0;\n \t}\n \tmy $refs = read_info_ref();\n-\tgit_header_html();\n-\tprint \"<div class=\\\"page_nav\\\">\\n\" .\n-\t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=summary\")}, \"summary\") .\n-\t      \" | shortlog\" .\n-\t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=log;h=$hash\")}, \"log\") .\n-\t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=commit;h=$hash\")}, \"commit\") .\n-\t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=commitdiff;h=$hash\")}, \"commitdiff\") .\n-\t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=tree;h=$hash;hb=$hash\")}, \"tree\") . \"<br/>\\n\";\n \n \tmy $limit = sprintf(\"--max-count=%i\", (100 * ($page+1)));\n \topen my $fd, \"-|\", $GIT, \"rev-list\", $limit, $hash \n@@ -2658,25 +2552,28 @@ sub git_shortlog {\n \tmy @revlist = map { chomp; $_ } <$fd>;\n \tclose $fd;\n \n+\tmy $paging_nav = '';\n \tif ($hash ne $head || $page) {\n-\t\tprint $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=shortlog\")}, \"HEAD\");\n+\t\t$paging_nav .= $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=shortlog\")}, \"HEAD\");\n \t} else {\n-\t\tprint \"HEAD\";\n+\t\t$paging_nav .= \"HEAD\";\n \t}\n \tif ($page > 0) {\n-\t\tprint \" &sdot; \" .\n-\t\t$cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=shortlog;h=$hash;pg=\" . ($page-1)), -accesskey => \"p\", -title => \"Alt-p\"}, \"prev\");\n+\t\t$paging_nav .= \" &sdot; \" .\n+\t\t\t$cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=shortlog;h=$hash;pg=\" . ($page-1)), -accesskey => \"p\", -title => \"Alt-p\"}, \"prev\");\n \t} else {\n-\t\tprint \" &sdot; prev\";\n+\t\t$paging_nav .= \" &sdot; prev\";\n \t}\n \tif ($#revlist >= (100 * ($page+1)-1)) {\n-\t\tprint \" &sdot; \" .\n-\t\t$cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=shortlog;h=$hash;pg=\" . ($page+1)), -accesskey => \"n\", -title => \"Alt-n\"}, \"next\");\n+\t\t$paging_nav .= \" &sdot; \" .\n+\t\t\t$cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=shortlog;h=$hash;pg=\" . ($page+1)), -accesskey => \"n\", -title => \"Alt-n\"}, \"next\");\n \t} else {\n-\t\tprint \" &sdot; next\";\n+\t\t$paging_nav .= \" &sdot; next\";\n \t}\n-\tprint \"<br/>\\n\" .\n-\t      \"</div>\\n\";\n+\n+\tgit_header_html();\n+\tgit_page_nav('shortlog','', $hash,$hash,$hash, $paging_nav);\n+\n \tprint \"<div>\\n\" .\n \t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=summary\"), -class => \"title\"}, \"&nbsp;\") .\n \t      \"</div>\\n\";\n-- \n1.4.0\n"},{"id":"24370","messageId":"200607301502.28142.jnareb@gmail.com","threadId":"5038","inReplyTo":"200607292239.11034.jnareb@gmail.com","subject":"[PATCH 10] gitweb: Replace form-feed character by ^L","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-07-30T13:02:27Z","receivedAt":"2006-07-30T13:02:27Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":">From 2be5cab10486cba804ccae063e93b146288054fe Mon Sep 17 00:00:00 2001\nFrom: Jakub Narebski <jnareb@gmail.com>\nDate: Sun, 30 Jul 2006 13:11:56 +0200\nSubject: [PATCH] \n\nReplace FORM FEED (FF) character (014, 12, 0xc) by it's textual\nrepresentation '^L'.  This character is used for example in GNU GPL\n'COPYING' file.  With this patch \"blob\" output for COPYING passes\nXHTML validation.\n\nSigned-off-by: Jakub Narebski <jnareb@gmail.com>\n---\n gitweb/gitweb.cgi |    1 +\n 1 files changed, 1 insertions(+), 0 deletions(-)\n\ndiff --git a/gitweb/gitweb.cgi b/gitweb/gitweb.cgi\nindex 6c72d33..d39af82 100755\n--- a/gitweb/gitweb.cgi\n+++ b/gitweb/gitweb.cgi\n@@ -250,6 +250,7 @@ sub esc_html {\n \tmy $str = shift;\n \t$str = decode(\"utf8\", $str, Encode::FB_DEFAULT);\n \t$str = escapeHTML($str);\n+\t$str =~ s/\\014/^L/g; # escape FORM FEED (FF) character (e.g. in COPYING file)\n \treturn $str;\n }\n \n-- \n1.4.0\n"},{"id":"24371","messageId":"200607301613.49947.jnareb@gmail.com","threadId":"5038","inReplyTo":"200607292239.11034.jnareb@gmail.com","subject":"[PATCH 11] gitweb: Read project description using utf-8 encoding","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-07-30T14:13:47Z","receivedAt":"2006-07-30T14:13:47Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Signed-off-by: Jakub Narebski <jnareb@gmail.com>\n---\n gitweb/gitweb.cgi |    2 +-\n 1 files changed, 1 insertions(+), 1 deletions(-)\n\ndiff --git a/gitweb/gitweb.cgi b/gitweb/gitweb.cgi\nindex d39af82..7d52a2c 100755\n--- a/gitweb/gitweb.cgi\n+++ b/gitweb/gitweb.cgi\n@@ -463,7 +463,7 @@ sub git_read_hash {\n sub git_read_description {\n \tmy $path = shift;\n \n-\topen my $fd, \"$projectroot/$path/description\" or return undef;\n+\topen (my $fd, \"<:utf8\", \"$projectroot/$path/description\") or return undef;\n \tmy $descr = <$fd>;\n \tclose $fd;\n \tchomp $descr;\n-- \n1.4.0\n"},{"id":"24372","messageId":"200607301614.43476.jnareb@gmail.com","threadId":"5038","inReplyTo":"200607292239.11034.jnareb@gmail.com","subject":"[PATCH 12] gitweb: Add \"\\n\" after <br/> in git_page_nav","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-07-30T14:14:43Z","receivedAt":"2006-07-30T14:14:43Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Signed-off-by: Jakub Narebski <jnareb@gmail.com>\n---\n gitweb/gitweb.cgi |    2 +-\n 1 files changed, 1 insertions(+), 1 deletions(-)\n\ndiff --git a/gitweb/gitweb.cgi b/gitweb/gitweb.cgi\nindex 7d52a2c..df152c3 100755\n--- a/gitweb/gitweb.cgi\n+++ b/gitweb/gitweb.cgi\n@@ -416,7 +416,7 @@ sub git_page_nav {\n \t\t\t\t\t : $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=$_$arg{$_}\")}, \"$_\")\n \t\t\t\t }\n \t\t @navs);\n-\tprint \"<br/>$extra<br/>\\n\" .\n+\tprint \"<br/>\\n$extra<br/>\\n\" .\n \t      \"</div>\\n\";\n }\n \n-- \n1.4.0\n"},{"id":"24374","messageId":"eaiino$oo2$1@sea.gmane.org","threadId":"5038","inReplyTo":"200607301613.49947.jnareb@gmail.com","subject":"Re: [PATCH 11] gitweb: Read project description using utf-8 encoding","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-07-30T15:20:33Z","receivedAt":"2006-07-30T15:20:33Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Disregard this patch for now. It corrects error in project_list page, but\nintroduces errors on other pages:\n\n  Software error: Cannot decode string with wide characters \n  at Encode.pm line 166.\n\nCorrected patch to follow.\n-- \nJakub Narebski\nWarsaw, Poland\nShadeHawk on #git\n"},{"id":"24375","messageId":"200607301747.25589.jnareb@gmail.com","threadId":"5038","inReplyTo":"200607301613.49947.jnareb@gmail.com","subject":"[PATCH 11] gitweb: Show project descriptions with utf-8 characters in project list correctly","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-07-30T15:47:22Z","receivedAt":"2006-07-30T15:47:22Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Signed-off-by: Jakub Narebski <jnareb@gmail.com>\n---\nThis supersedes previous patch.\n\n gitweb/gitweb.cgi |    2 +-\n 1 files changed, 1 insertions(+), 1 deletions(-)\n\ndiff --git a/gitweb/gitweb.cgi b/gitweb/gitweb.cgi\nindex 3884ffd..1befa7d 100755\n--- a/gitweb/gitweb.cgi\n+++ b/gitweb/gitweb.cgi\n@@ -988,7 +988,7 @@ sub git_project_list {\n \t\t}\n \t\t$alternate ^= 1;\n \t\tprint \"<td>\" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$pr->{'path'};a=summary\"), -class => \"list\"}, esc_html($pr->{'path'})) . \"</td>\\n\" .\n-\t\t      \"<td>$pr->{'descr'}</td>\\n\" .\n+\t\t      \"<td>\" . esc_html($pr->{'descr'}) . \"</td>\\n\" .\n \t\t      \"<td><i>\" . chop_str($pr->{'owner'}, 15) . \"</i></td>\\n\";\n \t\tprint \"<td class=\\\"\". age_class($pr->{'commit'}{'age'}) . \"\\\">\" . $pr->{'commit'}{'age_string'} . \"</td>\\n\" .\n \t\t      \"<td class=\\\"link\\\">\" .\n-- \n1.4.0\n"},{"id":"24376","messageId":"200607301749.00999.jnareb@gmail.com","threadId":"5038","inReplyTo":"200607292239.11034.jnareb@gmail.com","subject":"[PATCH 13] gitweb: Pager refactoring - use git_get_paging_nav for pagination","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-07-30T15:49:00Z","receivedAt":"2006-07-30T15:49:00Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Add git_get_paging_nav subroutine which returns string with pager\n(paging nav) for shortlog and log actions.\n\nSigned-off-by: Jakub Narebski <jnareb@gmail.com>\n---\nIt would make no sense to split this patch into two, I think.\n\n gitweb/gitweb.cgi |   68 +++++++++++++++++++++++++----------------------------\n 1 files changed, 32 insertions(+), 36 deletions(-)\n\ndiff --git a/gitweb/gitweb.cgi b/gitweb/gitweb.cgi\nindex df152c3..0ed3ad2 100755\n--- a/gitweb/gitweb.cgi\n+++ b/gitweb/gitweb.cgi\n@@ -420,6 +420,36 @@ sub git_page_nav {\n \t      \"</div>\\n\";\n }\n \n+sub git_get_paging_nav {\n+\tmy ($project, $action, $hash, $head, $page, $nrevs) = @_;\n+\tmy $paging_nav;\n+\n+\n+\tif ($hash ne $head || $page) {\n+\t\t$paging_nav .= $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=$action\")}, \"HEAD\");\n+\t} else {\n+\t\t$paging_nav .= \"HEAD\";\n+\t}\n+\n+\tif ($page > 0) {\n+\t\t$paging_nav .= \" &sdot; \" .\n+\t\t\t$cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=$action;h=$hash;pg=\" . ($page-1)),\n+\t\t\t\t\t\t\t -accesskey => \"p\", -title => \"Alt-p\"}, \"prev\");\n+\t} else {\n+\t\t$paging_nav .= \" &sdot; prev\";\n+\t}\n+\n+\tif ($nrevs >= (100 * ($page+1)-1)) {\n+\t\t$paging_nav .= \" &sdot; \" .\n+\t\t\t$cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=$action;h=$hash;pg=\" . ($page+1)),\n+\t\t\t\t\t\t\t -accesskey => \"n\", -title => \"Alt-n\"}, \"next\");\n+\t} else {\n+\t\t$paging_nav .= \" &sdot; next\";\n+\t}\n+\n+\treturn $paging_nav;\n+}\n+\n sub git_get_type {\n \tmy $hash = shift;\n \n@@ -1873,24 +1903,7 @@ sub git_log {\n \tmy @revlist = map { chomp; $_ } <$fd>;\n \tclose $fd;\n \n-\tmy $paging_nav = '';\n-\tif ($hash ne $head || $page) {\n-\t\t$paging_nav .= $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=log\")}, \"HEAD\");\n-\t} else {\n-\t\t$paging_nav .= \"HEAD\";\n-\t}\n-\tif ($page > 0) {\n-\t\t$paging_nav .= \" &sdot; \" .\n-\t\t\t$cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=log;h=$hash;pg=\" . ($page-1)), -accesskey => \"p\", -title => \"Alt-p\"}, \"prev\");\n-\t} else {\n-\t\t$paging_nav .= \" &sdot; prev\";\n-\t}\n-\tif ($#revlist >= (100 * ($page+1)-1)) {\n-\t\t$paging_nav .= \" &sdot; \" .\n-\t\t\t$cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=log;h=$hash;pg=\" . ($page+1)), -accesskey => \"n\", -title => \"Alt-n\"}, \"next\");\n-\t} else {\n-\t\t$paging_nav .= \" &sdot; next\";\n-\t}\n+\tmy $paging_nav = git_get_paging_nav($project, 'log', $hash, $head, $page, $#revlist);\n \n \tgit_header_html();\n \tgit_page_nav('log','', $hash,undef,undef, $paging_nav);\n@@ -2553,24 +2566,7 @@ sub git_shortlog {\n \tmy @revlist = map { chomp; $_ } <$fd>;\n \tclose $fd;\n \n-\tmy $paging_nav = '';\n-\tif ($hash ne $head || $page) {\n-\t\t$paging_nav .= $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=shortlog\")}, \"HEAD\");\n-\t} else {\n-\t\t$paging_nav .= \"HEAD\";\n-\t}\n-\tif ($page > 0) {\n-\t\t$paging_nav .= \" &sdot; \" .\n-\t\t\t$cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=shortlog;h=$hash;pg=\" . ($page-1)), -accesskey => \"p\", -title => \"Alt-p\"}, \"prev\");\n-\t} else {\n-\t\t$paging_nav .= \" &sdot; prev\";\n-\t}\n-\tif ($#revlist >= (100 * ($page+1)-1)) {\n-\t\t$paging_nav .= \" &sdot; \" .\n-\t\t\t$cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=shortlog;h=$hash;pg=\" . ($page+1)), -accesskey => \"n\", -title => \"Alt-n\"}, \"next\");\n-\t} else {\n-\t\t$paging_nav .= \" &sdot; next\";\n-\t}\n+\tmy $paging_nav = git_get_paging_nav($project, 'shortlog', $hash, $head, $page, $#revlist);\n \n \tgit_header_html();\n \tgit_page_nav('shortlog','', $hash,$hash,$hash, $paging_nav);\n-- \n1.4.0\n"},{"id":"24384","messageId":"200607302031.01937.jnareb@gmail.com","threadId":"5038","inReplyTo":"200607292239.11034.jnareb@gmail.com","subject":"[PATCH 14] gitweb: Remove $project from git_get_paging_nav arguments","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-07-30T18:31:00Z","receivedAt":"2006-07-30T18:31:00Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Remove $project from arguments passed to git_get_paging_nav\nsubroutine: it did not depend only on arguments, using $my_uri global\nvariable (and now $project global variable).\n\nSigned-off-by: Jakub Narebski <jnareb@gmail.com>\n---\n gitweb/gitweb.cgi |    6 +++---\n 1 files changed, 3 insertions(+), 3 deletions(-)\n\ndiff --git a/gitweb/gitweb.cgi b/gitweb/gitweb.cgi\nindex 1befa7d..bfb01de 100755\n--- a/gitweb/gitweb.cgi\n+++ b/gitweb/gitweb.cgi\n@@ -421,7 +421,7 @@ sub git_page_nav {\n }\n \n sub git_get_paging_nav {\n-\tmy ($project, $action, $hash, $head, $page, $nrevs) = @_;\n+\tmy ($action, $hash, $head, $page, $nrevs) = @_;\n \tmy $paging_nav;\n \n \n@@ -1903,7 +1903,7 @@ sub git_log {\n \tmy @revlist = map { chomp; $_ } <$fd>;\n \tclose $fd;\n \n-\tmy $paging_nav = git_get_paging_nav($project, 'log', $hash, $head, $page, $#revlist);\n+\tmy $paging_nav = git_get_paging_nav('log', $hash, $head, $page, $#revlist);\n \n \tgit_header_html();\n \tgit_page_nav('log','', $hash,undef,undef, $paging_nav);\n@@ -2566,7 +2566,7 @@ sub git_shortlog {\n \tmy @revlist = map { chomp; $_ } <$fd>;\n \tclose $fd;\n \n-\tmy $paging_nav = git_get_paging_nav($project, 'shortlog', $hash, $head, $page, $#revlist);\n+\tmy $paging_nav = git_get_paging_nav('shortlog', $hash, $head, $page, $#revlist);\n \n \tgit_header_html();\n \tgit_page_nav('shortlog','', $hash,$hash,$hash, $paging_nav);\n-- \n1.4.0\n"},{"id":"24385","messageId":"200607302032.01623.jnareb@gmail.com","threadId":"5038","inReplyTo":"200607292239.11034.jnareb@gmail.com","subject":"[PATCH 15] gitweb: Headers refactoring - use git_header_div for header divs","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-07-30T18:32:01Z","receivedAt":"2006-07-30T18:32:01Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Add git_header_div subroutine which prints \"header\" divs, now with\nclass \"header\" (class \"title\" is taken, and has set CSS style,\nchanging appereance and maing layout wrong), and use it thorough\ngitweb.cgi.  Change header linking to project summary from empty\n(&nbsp; as a contents of link) to having $project as contents/name\nof link.  Sometimes a little reordering.\n\nSigned-off-by: Jakub Narebski <jnareb@gmail.com>\n---\n gitweb/gitweb.cgi |  100 +++++++++++++++++++++--------------------------------\n 1 files changed, 40 insertions(+), 60 deletions(-)\n\ndiff --git a/gitweb/gitweb.cgi b/gitweb/gitweb.cgi\nindex bfb01de..06a6930 100755\n--- a/gitweb/gitweb.cgi\n+++ b/gitweb/gitweb.cgi\n@@ -420,6 +420,19 @@ sub git_page_nav {\n \t      \"</div>\\n\";\n }\n \n+sub git_header_div {\n+\tmy ($action, $title, $hash, $hash_base) = @_;\n+\tmy $rest = '';\n+\n+\t$rest .= \";h=$hash\" if $hash;\n+\t$rest .= \";hb=$hash_base\" if $hash_base;\n+\n+\tprint \"<div class=\\\"header\\\">\\n\" .\n+\t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=$action$rest\"),\n+\t               -class => \"title\"}, $title ? $title : $action) . \"\\n\" .\n+\t      \"</div>\\n\";\n+}\n+\n sub git_get_paging_nav {\n \tmy ($action, $hash, $head, $page, $nrevs) = @_;\n \tmy $paging_nav;\n@@ -1123,9 +1136,7 @@ sub git_summary {\n \t\tor die_error(undef, \"Open git-rev-list failed.\");\n \tmy @revlist = map { chomp; $_ } <$fd>;\n \tclose $fd;\n-\tprint \"<div>\\n\" .\n-\t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=shortlog\"), -class => \"title\"}, \"shortlog\") .\n-\t      \"</div>\\n\";\n+\tgit_header_div('shortlog');\n \tmy $i = 16;\n \tprint \"<table cellspacing=\\\"0\\\">\\n\";\n \tmy $alternate = 0;\n@@ -1169,9 +1180,7 @@ sub git_summary {\n \n \tmy $taglist = git_read_refs(\"refs/tags\");\n \tif (defined @$taglist) {\n-\t\tprint \"<div>\\n\" .\n-\t\t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=tags\"), -class => \"title\"}, \"tags\") .\n-\t\t      \"</div>\\n\";\n+\t\tgit_header_div('tags');\n \t\tmy $i = 16;\n \t\tprint \"<table cellspacing=\\\"0\\\">\\n\";\n \t\tmy $alternate = 0;\n@@ -1221,9 +1230,7 @@ sub git_summary {\n \n \tmy $headlist = git_read_refs(\"refs/heads\");\n \tif (defined @$headlist) {\n-\t\tprint \"<div>\\n\" .\n-\t\t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=heads\"), -class => \"title\"}, \"heads\") .\n-\t\t      \"</div>\\n\";\n+\t\tgit_header_div('heads');\n \t\tmy $i = 16;\n \t\tprint \"<table cellspacing=\\\"0\\\">\\n\";\n \t\tmy $alternate = 0;\n@@ -1276,9 +1283,7 @@ sub git_tag {\n \tgit_header_html();\n \tgit_page_nav('','', $head,undef,$head);\n \tmy %tag = git_read_tag($hash);\n-\tprint \"<div>\\n\" .\n-\t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=commit;h=$hash\"), -class => \"title\"}, esc_html($tag{'name'})) . \"\\n\" .\n-\t      \"</div>\\n\";\n+\tgit_header_div('commit', esc_html($tag{'name'}), $hash);\n \tprint \"<div class=\\\"title_text\\\">\\n\" .\n \t      \"<table cellspacing=\\\"0\\\">\\n\" .\n \t      \"<tr>\\n\" .\n@@ -1326,9 +1331,7 @@ sub git_blame2 {\n \t\t$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\");\n \tgit_page_nav('','', $hash_base,$co{'tree'},$hash_base, $formats_nav);\n-\tprint \"<div>\" .\n-\t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=commit;h=$hash_base\"), -class => \"title\"}, esc_html($co{'title'})) .\n-\t      \"</div>\\n\";\n+\tgit_header_div('commit', esc_html($co{'title'}), $hash_base);\n \tgit_print_page_path($file_name, $ftype);\n \tmy @rev_color = (qw(light dark));\n \tmy $num_colors = scalar(@rev_color);\n@@ -1382,9 +1385,7 @@ sub git_blame {\n \t\t$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\");\n \tgit_page_nav('','', $hash_base,$co{'tree'},$hash_base, $formats_nav);\n-\tprint \"<div>\" .\n-\t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=commit;h=$hash_base\"), -class => \"title\"}, esc_html($co{'title'})) .\n-\t      \"</div>\\n\";\n+\tgit_header_div('commit', esc_html($co{'title'}), $hash_base);\n \tgit_print_page_path($file_name);\n \tprint \"<div class=\\\"page_body\\\">\\n\";\n \tprint <<HTML;\n@@ -1460,11 +1461,10 @@ sub git_tags {\n \tmy $head = git_read_head($project);\n \tgit_header_html();\n \tgit_page_nav('','', $head,undef,$head);\n-\tmy $taglist = git_read_refs(\"refs/tags\");\n-\tprint \"<div>\\n\" .\n-\t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=summary\"), -class => \"title\"}, \"&nbsp;\") .\n-\t      \"</div>\\n\";\n+\tgit_header_div('summary', $project);\n \tprint \"<table cellspacing=\\\"0\\\">\\n\";\n+\n+\tmy $taglist = git_read_refs(\"refs/tags\");\n \tmy $alternate = 0;\n \tif (defined @$taglist) {\n \t\tforeach my $entry (@$taglist) {\n@@ -1511,11 +1511,10 @@ sub git_heads {\n \tmy $head = git_read_head($project);\n \tgit_header_html();\n \tgit_page_nav('','', $head,undef,$head);\n-\tmy $taglist = git_read_refs(\"refs/heads\");\n-\tprint \"<div>\\n\" .\n-\t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=summary\"), -class => \"title\"}, \"&nbsp;\") .\n-\t      \"</div>\\n\";\n+\thit_header_div('summary', $project);\n \tprint \"<table cellspacing=\\\"0\\\">\\n\";\n+\n+\tmy $taglist = git_read_refs(\"refs/heads\");\n \tmy $alternate = 0;\n \tif (defined @$taglist) {\n \t\tforeach my $entry (@$taglist) {\n@@ -1684,9 +1683,7 @@ sub git_blob {\n \t\t\t$formats_nav .= $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=blob_plain;h=$hash\")}, \"plain\");\n \t\t}\n \t\tgit_page_nav('','', $hash_base,$co{'tree'},$hash_base, $formats_nav);\n-\t\tprint \"<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+\t\tgit_header_div('commit', esc_html($co{'title'}), $hash_base);\n \t} else {\n \t\tprint \"<div class=\\\"page_nav\\\">\\n\" .\n \t\t      \"<br/><br/></div>\\n\" .\n@@ -1740,9 +1737,7 @@ sub git_tree {\n \tif (defined $hash_base && (my %co = git_read_commit($hash_base))) {\n \t\t$base_key = \";hb=$hash_base\";\n \t\tgit_page_nav('tree','', $hash_base);\n-\t\tprint \"<div>\\n\" .\n-\t\t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=commit;h=$hash_base\"), -class => \"title\"}, esc_html($co{'title'}) . $ref) . \"\\n\" .\n-\t\t      \"</div>\\n\";\n+\t\tgit_header_div('commit', esc_html($co{'title'}) . $ref, $hash_base);\n \t} else {\n \t\tprint \"<div class=\\\"page_nav\\\">\\n\";\n \t\tprint \"<br/><br/></div>\\n\";\n@@ -1909,10 +1904,9 @@ sub git_log {\n \tgit_page_nav('log','', $hash,undef,undef, $paging_nav);\n \n \tif (!@revlist) {\n-\t\tprint \"<div>\\n\" .\n-\t\t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=summary\"), -class => \"title\"}, \"&nbsp;\") .\n-\t\t      \"</div>\\n\";\n \t\tmy %co = git_read_commit($hash);\n+\n+\t\tgit_header_div('summary', $project);\n \t\tprint \"<div class=\\\"page_body\\\"> Last change $co{'age_string'}.<br/><br/></div>\\n\";\n \t}\n \tfor (my $i = ($page * 100); $i <= $#revlist; $i++) {\n@@ -1924,10 +1918,10 @@ sub git_log {\n \t\tmy %co = git_read_commit($commit);\n \t\tnext if !%co;\n \t\tmy %ad = date_str($co{'author_epoch'});\n-\t\tprint \"<div>\\n\" .\n-\t\t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=commit;h=$commit\"), -class => \"title\"},\n-\t\t      \"<span class=\\\"age\\\">$co{'age_string'}</span>\" . esc_html($co{'title'}) . $ref) . \"\\n\";\n-\t\tprint \"</div>\\n\";\n+\t\tgit_header_div('commit',\n+\t\t\t\t\t\t\t\t\t \"<span class=\\\"age\\\">$co{'age_string'}</span>\" .\n+\t\t\t\t\t\t\t\t\t esc_html($co{'title'}) . $ref,\n+\t\t\t\t\t\t\t\t\t $commit);\n \t\tprint \"<div class=\\\"title_text\\\">\\n\" .\n \t\t      \"<div class=\\\"log_link\\\">\\n\" .\n \t\t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=commit;h=$commit\")}, \"commit\") .\n@@ -1999,13 +1993,9 @@ sub git_commit {\n \t\t\t\t\t\t\t $formats_nav);\n \n \tif (defined $co{'parent'}) {\n-\t\tprint \"<div>\\n\" .\n-\t\t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=commitdiff;h=$hash\"), -class => \"title\"}, esc_html($co{'title'}) . $ref) . \"\\n\" .\n-\t\t      \"</div>\\n\";\n+\t\tgit_header_div('commitdiff', esc_html($co{'title'}) . $ref, $hash);\n \t} else {\n-\t\tprint \"<div>\\n\" .\n-\t\t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=tree;h=$co{'tree'};hb=$hash\"), -class => \"title\"}, esc_html($co{'title'})) . \"\\n\" .\n-\t\t      \"</div>\\n\";\n+\t\tgit_header_div('tree', esc_html($co{'title'}), $co{'tree'}, $hash);\n \t}\n \tprint \"<div class=\\\"title_text\\\">\\n\" .\n \t      \"<table cellspacing=\\\"0\\\">\\n\";\n@@ -2171,9 +2161,7 @@ sub git_blobdiff {\n \t\tmy $formats_nav = \n \t\t\t$cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=blobdiff_plain;h=$hash;hp=$hash_parent\")}, \"plain\");\n \t\tgit_page_nav('','', $hash_base,$co{'tree'},$hash_base, $formats_nav);\n-\t\tprint \"<div>\\n\" .\n-\t\t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=commit;h=$hash_base\"), -class => \"title\"}, esc_html($co{'title'})) . \"\\n\" .\n-\t\t      \"</div>\\n\";\n+\t\tgit_header_div('commit', esc_html($co{'title'}), $hash_base);\n \t} else {\n \t\tprint \"<div class=\\\"page_nav\\\">\\n\" .\n \t\t      \"<br/><br/></div>\\n\" .\n@@ -2225,9 +2213,7 @@ sub git_commitdiff {\n \tmy $formats_nav =\n \t\t$cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=commitdiff_plain;h=$hash;hp=$hash_parent\")}, \"plain\");\n \tgit_page_nav('commitdiff','', $hash,$co{'tree'},$hash, $formats_nav);\n-\tprint \"<div>\\n\" .\n-\t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=commit;h=$hash\"), -class => \"title\"}, esc_html($co{'title'}) . $ref) . \"\\n\" .\n-\t      \"</div>\\n\";\n+\tgit_header_div('commit', esc_html($co{'title'}) . $ref, $hash);\n \tprint \"<div class=\\\"page_body\\\">\\n\";\n \tmy $comment = $co{'comment'};\n \tmy $empty = 0;\n@@ -2357,9 +2343,7 @@ sub git_history {\n \tmy $refs = read_info_ref();\n \tgit_header_html();\n \tgit_page_nav('','', $hash_base,$co{'tree'},$hash_base);\n-\tprint \"<div>\\n\" .\n-\t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=commit;h=$hash_base\"), -class => \"title\"}, esc_html($co{'title'})) . \"\\n\" .\n-\t      \"</div>\\n\";\n+\tgit_header_div('commit', esc_html($co{'title'}), $hash_base);\n \tif (!defined $hash && defined $file_name) {\n \t\t$hash = git_get_hash_by_path($hash_base, $file_name);\n \t}\n@@ -2440,10 +2424,8 @@ sub git_search {\n \t}\n \tgit_header_html();\n \tgit_page_nav('','', $hash,$co{'tree'},$hash);\n+\tgit_header_div('commit', esc_html($co{'title'}), $hash);\n \n-\tprint \"<div>\\n\" .\n-\t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=commit;h=$hash\"), -class => \"title\"}, esc_html($co{'title'})) . \"\\n\" .\n-\t      \"</div>\\n\";\n \tprint \"<table cellspacing=\\\"0\\\">\\n\";\n \tmy $alternate = 0;\n \tif ($commit_search) {\n@@ -2570,10 +2552,8 @@ sub git_shortlog {\n \n \tgit_header_html();\n \tgit_page_nav('shortlog','', $hash,$hash,$hash, $paging_nav);\n+\tgit_header_div('summary', $project);\n \n-\tprint \"<div>\\n\" .\n-\t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=summary\"), -class => \"title\"}, \"&nbsp;\") .\n-\t      \"</div>\\n\";\n \tprint \"<table cellspacing=\\\"0\\\">\\n\";\n \tmy $alternate = 0;\n \tfor (my $i = ($page * 100); $i <= $#revlist; $i++) {\n-- \n1.4.0\n"},{"id":"24387","messageId":"200607302236.06686.jnareb@gmail.com","threadId":"5038","inReplyTo":"200607292239.11034.jnareb@gmail.com","subject":"[PATCH 16] gitweb: Remove characters entities entirely when shortening string","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-07-30T20:36:04Z","receivedAt":"2006-07-30T20:36:04Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Signed-off-by: Jakub Narebski <jnareb@gmail.com>\n---\nYet another error noticed due to strict validation \nof application/xhtml+xml by Mozilla.\n\n gitweb/gitweb.cgi |    1 +\n 1 files changed, 1 insertions(+), 0 deletions(-)\n\ndiff --git a/gitweb/gitweb.cgi b/gitweb/gitweb.cgi\nindex 06a6930..83ea97a 100755\n--- a/gitweb/gitweb.cgi\n+++ b/gitweb/gitweb.cgi\n@@ -776,6 +776,7 @@ sub chop_str {\n \tmy $tail = $2;\n \tif (length($tail) > 4) {\n \t\t$tail = \" ...\";\n+\t\t$body =~ s/&[^;]$//; # remove chopped character entities\n \t}\n \treturn \"$body$tail\";\n }\n-- \n1.4.0\n"},{"id":"24394","messageId":"200607310221.55445.jnareb@gmail.com","threadId":"5038","inReplyTo":"200607292239.11034.jnareb@gmail.com","subject":"[PATCH 17] gitweb: Ref refactoring - use git_get_referencing for marking tagged/head commits","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-07-31T00:21:52Z","receivedAt":"2006-07-31T00:21:52Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Use git_get_referencing to get HTML code for markers showing which\nrefs (tags and heads) point to current commit.  It would be much\neasier to change format of markers in one or two places than thorough\nthe gitweb.cgi file.\n\nAdded comment about read_info_ref subroutine: for $type == \"\" (empty\nargument) it saves only last path part of ref name e.g. from\n'refs/heads/jn/gitweb' it would leave only 'gitweb'.\n\nSome reordering.  Added $ref in one place.\n\nSigned-off-by: Jakub Narebski <jnareb@gmail.com>\n---\n gitweb/gitweb.cgi |   53 ++++++++++++++++++++++-------------------------------\n 1 files changed, 22 insertions(+), 31 deletions(-)\n\ndiff --git a/gitweb/gitweb.cgi b/gitweb/gitweb.cgi\nindex 83ea97a..dab6068 100755\n--- a/gitweb/gitweb.cgi\n+++ b/gitweb/gitweb.cgi\n@@ -1024,6 +1024,8 @@ sub read_info_ref {\n \topen my $fd, \"$projectroot/$project/info/refs\" or return;\n \twhile (my $line = <$fd>) {\n \t\tchomp $line;\n+\t\t# attention: for $type == \"\" it saves only last path part of ref name\n+\t\t# e.g. from 'refs/heads/jn/gitweb' it would leave only 'gitweb'\n \t\tif ($line =~ m/^([0-9a-fA-F]{40})\\t.*$type\\/([^\\^]+)/) {\n \t\t\tif (defined $refs{$1}) {\n \t\t\t\t$refs{$1} .= \" / $2\";\n@@ -1036,6 +1038,16 @@ sub read_info_ref {\n \treturn \\%refs;\n }\n \n+sub git_get_referencing {\n+\tmy ($refs, $id) = @_;\n+\n+\tif (defined $refs->{$id}) {\n+\t\treturn ' <span class=\"tag\">' . esc_html($refs->{$id}) . '</span>';\n+\t} else {\n+\t\treturn \"\";\n+\t}\n+}\n+\n sub git_read_refs {\n \tmy $ref_dir = shift;\n \tmy @reflist;\n@@ -1151,10 +1163,7 @@ sub git_summary {\n \t\t}\n \t\t$alternate ^= 1;\n \t\tif ($i-- > 0) {\n-\t\t\tmy $ref = \"\";\n-\t\t\tif (defined $refs->{$commit}) {\n-\t\t\t\t$ref = \" <span class=\\\"tag\\\">\" . esc_html($refs->{$commit}) . \"</span>\";\n-\t\t\t}\n+\t\t\tmy $ref = git_get_referencing($refs, $commit);\n \t\t\tprint \"<td><i>$co{'age_string'}</i></td>\\n\" .\n \t\t\t      \"<td><i>\" . esc_html(chop_str($co{'author_name'}, 10)) . \"</i></td>\\n\" .\n \t\t\t      \"<td>\";\n@@ -1728,10 +1737,7 @@ sub git_tree {\n \t$/ = \"\\n\";\n \n \tmy $refs = read_info_ref();\n-\tmy $ref = \"\";\n-\tif (defined $refs->{$hash_base}) {\n-\t\t$ref = \" <span class=\\\"tag\\\">\" . esc_html($refs->{$hash_base}) . \"</span>\";\n-\t}\n+\tmy $ref = git_get_referencing($refs, $hash_base);\n \tgit_header_html();\n \tmy $base_key = \"\";\n \tmy $base = \"\";\n@@ -1912,10 +1918,7 @@ sub git_log {\n \t}\n \tfor (my $i = ($page * 100); $i <= $#revlist; $i++) {\n \t\tmy $commit = $revlist[$i];\n-\t\tmy $ref = \"\";\n-\t\tif (defined $refs->{$commit}) {\n-\t\t\t$ref = \" <span class=\\\"tag\\\">\" . esc_html($refs->{$commit}) . \"</span>\";\n-\t\t}\n+\t\tmy $ref = git_get_referencing($refs, $commit);\n \t\tmy %co = git_read_commit($commit);\n \t\tnext if !%co;\n \t\tmy %ad = date_str($co{'author_epoch'});\n@@ -1979,16 +1982,13 @@ sub git_commit {\n \t\t$expires = \"+1d\";\n \t}\n \tmy $refs = read_info_ref();\n-\tmy $ref = \"\";\n-\tif (defined $refs->{$co{'id'}}) {\n-\t\t$ref = \" <span class=\\\"tag\\\">\" . esc_html($refs->{$co{'id'}}) . \"</span>\";\n-\t}\n-\tgit_header_html(undef, $expires);\n+\tmy $ref = git_get_referencing($refs, $co{'id'});\n \tmy $formats_nav = '';\n \tif (defined $file_name && defined $co{'parent'}) {\n \t\tmy $parent = $co{'parent'};\n \t\t$formats_nav .= $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=blame;hb=$parent;f=$file_name\")}, \"blame\");\n \t}\n+\tgit_header_html(undef, $expires);\n \tgit_page_nav('commit', defined $co{'parent'} ? '' : 'commitdiff', \n \t\t\t\t\t\t\t $hash, $co{'tree'}, $hash,\n \t\t\t\t\t\t\t $formats_nav);\n@@ -1996,7 +1996,7 @@ sub git_commit {\n \tif (defined $co{'parent'}) {\n \t\tgit_header_div('commitdiff', esc_html($co{'title'}) . $ref, $hash);\n \t} else {\n-\t\tgit_header_div('tree', esc_html($co{'title'}), $co{'tree'}, $hash);\n+\t\tgit_header_div('tree', esc_html($co{'title'}) . $ref, $co{'tree'}, $hash);\n \t}\n \tprint \"<div class=\\\"title_text\\\">\\n\" .\n \t      \"<table cellspacing=\\\"0\\\">\\n\";\n@@ -2206,13 +2206,10 @@ sub git_commitdiff {\n \t\t$expires = \"+1d\";\n \t}\n \tmy $refs = read_info_ref();\n-\tmy $ref = \"\";\n-\tif (defined $refs->{$co{'id'}}) {\n-\t\t$ref = \" <span class=\\\"tag\\\">\" . esc_html($refs->{$co{'id'}}) . \"</span>\";\n-\t}\n-\tgit_header_html(undef, $expires);\n+\tmy $ref = git_get_referencing($refs, $co{'id'});\n \tmy $formats_nav =\n \t\t$cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=commitdiff_plain;h=$hash;hp=$hash_parent\")}, \"plain\");\n+\tgit_header_html(undef, $expires);\n \tgit_page_nav('commitdiff','', $hash,$co{'tree'},$hash, $formats_nav);\n \tgit_header_div('commit', esc_html($co{'title'}) . $ref, $hash);\n \tprint \"<div class=\\\"page_body\\\">\\n\";\n@@ -2364,10 +2361,7 @@ sub git_history {\n \t\t\tif (!%co) {\n \t\t\t\tnext;\n \t\t\t}\n-\t\t\tmy $ref = \"\";\n-\t\t\tif (defined $refs->{$commit}) {\n-\t\t\t\t$ref = \" <span class=\\\"tag\\\">\" . esc_html($refs->{$commit}) . \"</span>\";\n-\t\t\t}\n+\t\t\tmy $ref = git_get_referencing($refs, $commit);\n \t\t\tif ($alternate) {\n \t\t\t\tprint \"<tr class=\\\"dark\\\">\\n\";\n \t\t\t} else {\n@@ -2559,10 +2553,7 @@ sub git_shortlog {\n \tmy $alternate = 0;\n \tfor (my $i = ($page * 100); $i <= $#revlist; $i++) {\n \t\tmy $commit = $revlist[$i];\n-\t\tmy $ref = \"\";\n-\t\tif (defined $refs->{$commit}) {\n-\t\t\t$ref = \" <span class=\\\"tag\\\">\" . esc_html($refs->{$commit}) . \"</span>\";\n-\t\t}\n+\t\tmy $ref = git_get_referencing($refs, $commit);\n \t\tmy %co = git_read_commit($commit);\n \t\tmy %ad = date_str($co{'author_epoch'});\n \t\tif ($alternate) {\n-- \n1.4.0\n"},{"id":"24418","messageId":"200607311122.17417.jnareb@gmail.com","threadId":"5038","inReplyTo":"200607292239.11034.jnareb@gmail.com","subject":"[PATCH 18] gitweb: Refactor generation of shortlog, tags and heads body","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-07-31T09:22:13Z","receivedAt":"2006-07-31T09:22:13Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Add git_shortlog_body, git_tags_body and git_heads_body to generate\ntable with shortlog, tags and heads respectively in git_summary and\ngit_shortlog, git_tags, git_heads respectively.\n\nBetter support for lightweight tags in git_read_refs; currently only\nlightweight tag pointing to tag object is not resolved fully.\n\nShortlog, tags and heads body tables have proper class now (we could\nuse id instead of class).\n\nAdd support for showing full comment on mouseover to tags list when\ncomment is shortened, similar to how full title of commit was/is\nshown on mouseover when title was shortened.  Changed layout of tags\ntable to better show lightweight tags.\n\nAdd showing which branch (head) is current branch (current head),\nusing \"current_head\" class (we could use id instead).\n\nCorrected \"</table\\n>\" and hit_header_div instead of git_header_div.\n\n\nSigned-off-by: Jakub Narebski <jnareb@gmail.com>\n---\nLargest patch in the series. Refactoring and unification.\nNew features (table classes, current head) are fairly unintrusive.\n\n gitweb/gitweb.cgi |  383 ++++++++++++++++++++++++-----------------------------\n gitweb/gitweb.css |   10 +\n 2 files changed, 184 insertions(+), 209 deletions(-)\n\ndiff --git a/gitweb/gitweb.cgi b/gitweb/gitweb.cgi\nindex dab6068..d209af0 100755\n--- a/gitweb/gitweb.cgi\n+++ b/gitweb/gitweb.cgi\n@@ -1102,6 +1102,10 @@ sub git_read_refs {\n \t\t\t$ref_item{'refid'} = $ref_id;\n \t\t\t$ref_item{'epoch'} = $co{'committer_epoch'};\n \t\t\t$ref_item{'age'} = $co{'age_string'};\n+\t\t} else {\n+\t\t\t$ref_item{'reftype'} = $type;\n+\t\t\t$ref_item{'name'} = $ref_file;\n+\t\t\t$ref_item{'refid'} = $ref_id;\n \t\t}\n \n \t\tpush @reflist, \\%ref_item;\n@@ -1111,6 +1115,156 @@ sub git_read_refs {\n \treturn \\@reflist;\n }\n \n+sub git_shortlog_body {\n+\t# uses global variable $project\n+\tmy ($revlist, $from, $to, $refs, $extra) = @_;\n+\t$from = 0 unless defined $from;\n+\t$to = $#{$revlist} if (!defined $to || $#{$revlist} < $to);\n+\n+\tprint \"<table class=\\\"shortlog\\\" cellspacing=\\\"0\\\">\\n\";\n+\tmy $alternate = 0;\n+\tfor (my $i = $from; $i <= $to; $i++) {\n+\t\tmy $commit = $revlist->[$i];\n+\t\t#my $ref = defined $refs ? git_get_referencing($refs, $commit) : '';\n+\t\tmy $ref = git_get_referencing($refs, $commit);\n+\t\tmy %co = git_read_commit($commit);\n+\t\tmy %ad = date_str($co{'author_epoch'});\n+\t\tif ($alternate) {\n+\t\t\tprint \"<tr class=\\\"dark\\\">\\n\";\n+\t\t} else {\n+\t\t\tprint \"<tr class=\\\"light\\\">\\n\";\n+\t\t}\n+\t\t$alternate ^= 1;\n+\t\t# git_summary() used print \"<td><i>$co{'age_string'}</i></td>\\n\" .\n+\t\tprint \"<td title=\\\"$co{'age_string_age'}\\\"><i>$co{'age_string_date'}</i></td>\\n\" .\n+\t\t      \"<td><i>\" . esc_html(chop_str($co{'author_name'}, 10)) . \"</i></td>\\n\" .\n+\t\t      \"<td>\";\n+\t\tif (length($co{'title_short'}) < length($co{'title'})) {\n+\t\t\tprint $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=commit;h=$commit\"),\n+\t\t\t               -class => \"list\", -title => \"$co{'title'}\"},\n+\t\t\t      \"<b>\" . esc_html($co{'title_short'}) . \"$ref</b>\");\n+\t\t} else {\n+\t\t\tprint $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=commit;h=$commit\"),\n+\t\t\t               -class => \"list\"},\n+\t\t\t      \"<b>\" . esc_html($co{'title'}) . \"$ref</b>\");\n+\t\t}\n+\t\tprint \"</td>\\n\" .\n+\t\t      \"<td class=\\\"link\\\">\" .\n+\t\t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=commit;h=$commit\")}, \"commit\") . \" | \" .\n+\t\t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=commitdiff;h=$commit\")}, \"commitdiff\") .\n+\t\t      \"</td>\\n\" .\n+\t\t      \"</tr>\\n\";\n+\t}\n+\tif (defined $extra) {\n+\t\tprint \"<tr>\\n\" .\n+\t\t      \"<td colspan=\\\"4\\\">$extra</td>\\n\" .\n+\t\t      \"</tr>\\n\";\n+\t}\n+\tprint \"</table>\\n\";\n+}\n+\n+sub git_tags_body {\n+\t# uses global variable $project\n+\tmy ($taglist, $from, $to, $extra) = @_;\n+\t$from = 0 unless defined $from;\n+\t$to = $#{$taglist} if (!defined $to || $#{$taglist} < $to);\n+\n+\tprint \"<table class=\\\"tags\\\" cellspacing=\\\"0\\\">\\n\";\n+\tmy $alternate = 0;\n+\tfor (my $i = $from; $i <= $to; $i++) {\n+\t\tmy $entry = $taglist->[$i];\n+\t\tmy %tag = %$entry;\n+\t\tmy $comment_lines = $tag{'comment'};\n+\t\tmy $comment = shift @$comment_lines;\n+\t\tmy $comment_short;\n+\t\tif (defined $comment) {\n+\t\t\t$comment_short = chop_str($comment, 30, 5);\n+\t\t}\n+\t\tif ($alternate) {\n+\t\t\tprint \"<tr class=\\\"dark\\\">\\n\";\n+\t\t} else {\n+\t\t\tprint \"<tr class=\\\"light\\\">\\n\";\n+\t\t}\n+\t\t$alternate ^= 1;\n+\t\tprint \"<td><i>$tag{'age'}</i></td>\\n\" .\n+\t\t      \"<td>\" .\n+\t\t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=$tag{'reftype'};h=$tag{'refid'}\"),\n+\t\t               -class => \"list\"}, \"<b>\" . esc_html($tag{'name'}) . \"</b>\") .\n+\t\t      \"</td>\\n\" .\n+\t\t      \"<td>\";\n+\t\tif (defined $comment) {\n+\t\t\tif (length($comment_short) < length($comment)) {\n+\t\t\t\tprint $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=tag;h=$tag{'id'}\"),\n+\t\t\t\t               -class => \"list\", -title => $comment}, $comment_short);\n+\t\t\t} else {\n+\t\t\t\tprint $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=tag;h=$tag{'id'}\"),\n+\t\t\t\t               -class => \"list\"}, $comment);\n+\t\t\t}\n+\t\t}\n+\t\tprint \"</td>\\n\" .\n+\t\t      \"<td class=\\\"selflink\\\">\";\n+\t\tif ($tag{'type'} eq \"tag\") {\n+\t\t\tprint $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=tag;h=$tag{'id'}\")}, \"tag\");\n+\t\t} else {\n+\t\t\tprint \"&nbsp;\";\n+\t\t}\n+\t\tprint \"</td>\\n\" .\n+\t\t      \"<td class=\\\"link\\\">\" . \" | \" .\n+\t\t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=$tag{'reftype'};h=$tag{'refid'}\")}, $tag{'reftype'});\n+\t\tif ($tag{'reftype'} eq \"commit\") {\n+\t\t\tprint \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=shortlog;h=$tag{'name'}\")}, \"shortlog\") .\n+\t\t\t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=log;h=$tag{'refid'}\")}, \"log\");\n+\t\t} elsif ($tag{'reftype'} eq \"blob\") {\n+\t\t\tprint \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=blob_plain;h=$tag{'refid'}\")}, \"raw\");\n+\t\t}\n+\t\tprint \"</td>\\n\" .\n+\t\t      \"</tr>\";\n+\t}\n+\tif (defined $extra) {\n+\t\tprint \"<tr>\\n\" .\n+\t\t      \"<td colspan=\\\"5\\\">$extra</td>\\n\" .\n+\t\t      \"</tr>\\n\";\n+\t}\n+\tprint \"</table>\\n\";\n+}\n+\n+sub git_heads_body {\n+\t# uses global variable $project\n+\tmy ($taglist, $head, $from, $to, $extra) = @_;\n+\t$from = 0 unless defined $from;\n+\t$to = $#{$taglist} if (!defined $to || $#{$taglist} < $to);\n+\n+\tprint \"<table class=\\\"heads\\\" cellspacing=\\\"0\\\">\\n\";\n+\tmy $alternate = 0;\n+\tfor (my $i = $from; $i <= $to; $i++) {\n+\t\tmy $entry = $taglist->[$i];\n+\t\tmy %tag = %$entry;\n+\t\tmy $curr = $tag{'id'} eq $head;\n+\t\tif ($alternate) {\n+\t\t\tprint \"<tr class=\\\"dark\\\">\\n\";\n+\t\t} else {\n+\t\t\tprint \"<tr class=\\\"light\\\">\\n\";\n+\t\t}\n+\t\t$alternate ^= 1;\n+\t\tprint \"<td><i>$tag{'age'}</i></td>\\n\" .\n+\t\t      ($tag{'id'} eq $head ? \"<td class=\\\"current_head\\\">\" : \"<td>\") .\n+\t\t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=shortlog;h=$tag{'name'}\"),\n+\t\t               -class => \"list\"}, \"<b>\" . esc_html($tag{'name'}) . \"</b>\") .\n+\t\t      \"</td>\\n\" .\n+\t\t      \"<td class=\\\"link\\\">\" .\n+\t\t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=shortlog;h=$tag{'name'}\")}, \"shortlog\") . \" | \" .\n+\t\t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=log;h=$tag{'name'}\")}, \"log\") .\n+\t\t      \"</td>\\n\" .\n+\t\t      \"</tr>\";\n+\t}\n+\tif (defined $extra) {\n+\t\tprint \"<tr>\\n\" .\n+\t\t      \"<td colspan=\\\"3\\\">$extra</td>\\n\" .\n+\t\t      \"</tr>\\n\";\n+\t}\n+\tprint \"</table>\\n\";\n+}\n+\n sub git_summary {\n \tmy $descr = git_read_description($project) || \"none\";\n \tmy $head = git_read_head($project);\n@@ -1139,138 +1293,36 @@ sub git_summary {\n \tmy $refs = read_info_ref();\n \tgit_header_html();\n \tgit_page_nav('summary','', $head);\n+\n \tprint \"<div class=\\\"title\\\">&nbsp;</div>\\n\";\n \tprint \"<table cellspacing=\\\"0\\\">\\n\" .\n \t      \"<tr><td>description</td><td>\" . esc_html($descr) . \"</td></tr>\\n\" .\n \t      \"<tr><td>owner</td><td>$owner</td></tr>\\n\" .\n \t      \"<tr><td>last change</td><td>$cd{'rfc2822'}</td></tr>\\n\" .\n \t      \"</table>\\n\";\n+\n \topen my $fd, \"-|\", $GIT, \"rev-list\", \"--max-count=17\", git_read_head($project) \n \t\tor die_error(undef, \"Open git-rev-list failed.\");\n \tmy @revlist = map { chomp; $_ } <$fd>;\n \tclose $fd;\n \tgit_header_div('shortlog');\n-\tmy $i = 16;\n-\tprint \"<table cellspacing=\\\"0\\\">\\n\";\n-\tmy $alternate = 0;\n-\tforeach my $commit (@revlist) {\n-\t\tmy %co = git_read_commit($commit);\n-\t\tmy %ad = date_str($co{'author_epoch'});\n-\t\tif ($alternate) {\n-\t\t\tprint \"<tr class=\\\"dark\\\">\\n\";\n-\t\t} else {\n-\t\t\tprint \"<tr class=\\\"light\\\">\\n\";\n-\t\t}\n-\t\t$alternate ^= 1;\n-\t\tif ($i-- > 0) {\n-\t\t\tmy $ref = git_get_referencing($refs, $commit);\n-\t\t\tprint \"<td><i>$co{'age_string'}</i></td>\\n\" .\n-\t\t\t      \"<td><i>\" . esc_html(chop_str($co{'author_name'}, 10)) . \"</i></td>\\n\" .\n-\t\t\t      \"<td>\";\n-\t\t\tif (length($co{'title_short'}) < length($co{'title'})) {\n-\t\t\t\tprint $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=commit;h=$commit\"), -class => \"list\", -title => \"$co{'title'}\"},\n-\t\t\t\t      \"<b>\" . esc_html($co{'title_short'}) . \"$ref</b>\");\n-\t\t\t} else {\n-\t\t\t\tprint $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=commit;h=$commit\"), -class => \"list\"},\n-\t\t\t\t      \"<b>\" . esc_html($co{'title'}) . \"$ref</b>\");\n-\t\t\t}\n-\t\t\tprint \"</td>\\n\" .\n-\t\t\t      \"<td class=\\\"link\\\">\" .\n-\t\t\t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=commit;h=$commit\")}, \"commit\") .\n-\t\t\t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=commitdiff;h=$commit\")}, \"commitdiff\") .\n-\t\t\t      \"</td>\\n\" .\n-\t\t\t      \"</tr>\";\n-\t\t} else {\n-\t\t\tprint \"<td>\" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=shortlog\")}, \"...\") . \"</td>\\n\" .\n-\t\t\t\"</tr>\";\n-\t\t\tlast;\n-\t\t}\n-\t}\n-\tprint \"</table\\n>\";\n+\tgit_shortlog_body(\\@revlist, 0, 15, $refs,\n+\t                  $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=shortlog\")}, \"...\"));\n \n \tmy $taglist = git_read_refs(\"refs/tags\");\n \tif (defined @$taglist) {\n \t\tgit_header_div('tags');\n-\t\tmy $i = 16;\n-\t\tprint \"<table cellspacing=\\\"0\\\">\\n\";\n-\t\tmy $alternate = 0;\n-\t\tforeach my $entry (@$taglist) {\n-\t\t\tmy %tag = %$entry;\n-\t\t\tmy $comment_lines = $tag{'comment'};\n-\t\t\tmy $comment = shift @$comment_lines;\n-\t\t\tif (defined($comment)) {\n-\t\t\t\t$comment = chop_str($comment, 30, 5);\n-\t\t\t}\n-\t\t\tif ($alternate) {\n-\t\t\t\tprint \"<tr class=\\\"dark\\\">\\n\";\n-\t\t\t} else {\n-\t\t\t\tprint \"<tr class=\\\"light\\\">\\n\";\n-\t\t\t}\n-\t\t\t$alternate ^= 1;\n-\t\t\tif ($i-- > 0) {\n-\t\t\t\tprint \"<td><i>$tag{'age'}</i></td>\\n\" .\n-\t\t\t\t      \"<td>\" .\n-\t\t\t\t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=$tag{'reftype'};h=$tag{'refid'}\"), -class => \"list\"},\n-\t\t\t\t      \"<b>\" . esc_html($tag{'name'}) . \"</b>\") .\n-\t\t\t\t      \"</td>\\n\" .\n-\t\t\t\t      \"<td>\";\n-\t\t\t\tif (defined($comment)) {\n-\t\t\t\t\tprint $cgi->a({-class => \"list\", -href => \"$my_uri?\" . esc_param(\"p=$project;a=tag;h=$tag{'id'}\")}, esc_html($comment));\n-\t\t\t\t}\n-\t\t\t\tprint \"</td>\\n\" .\n-\t\t\t\t      \"<td class=\\\"link\\\">\";\n-\t\t\t\tif ($tag{'type'} eq \"tag\") {\n-\t\t\t\t\tprint $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=tag;h=$tag{'id'}\")}, \"tag\") . \" | \";\n-\t\t\t\t}\n-\t\t\t\tprint $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=$tag{'reftype'};h=$tag{'refid'}\")}, $tag{'reftype'});\n-\t\t\t\tif ($tag{'reftype'} eq \"commit\") {\n-\t\t\t\t\tprint \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=shortlog;h=$tag{'name'}\")}, \"shortlog\") .\n-\t\t\t\t\t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=log;h=$tag{'refid'}\")}, \"log\");\n-\t\t\t\t}\n-\t\t\t\tprint \"</td>\\n\" .\n-\t\t\t\t      \"</tr>\";\n-\t\t\t} else {\n-\t\t\t\tprint \"<td>\" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=tags\")}, \"...\") . \"</td>\\n\" .\n-\t\t\t\t\"</tr>\";\n-\t\t\t\tlast;\n-\t\t\t}\n-\t\t}\n-\t\tprint \"</table\\n>\";\n+\t\tgit_tags_body($taglist, 0, 15,\n+\t\t              $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=tags\")}, \"...\"));\n \t}\n \n \tmy $headlist = git_read_refs(\"refs/heads\");\n \tif (defined @$headlist) {\n \t\tgit_header_div('heads');\n-\t\tmy $i = 16;\n-\t\tprint \"<table cellspacing=\\\"0\\\">\\n\";\n-\t\tmy $alternate = 0;\n-\t\tforeach my $entry (@$headlist) {\n-\t\t\tmy %tag = %$entry;\n-\t\t\tif ($alternate) {\n-\t\t\t\tprint \"<tr class=\\\"dark\\\">\\n\";\n-\t\t\t} else {\n-\t\t\t\tprint \"<tr class=\\\"light\\\">\\n\";\n-\t\t\t}\n-\t\t\t$alternate ^= 1;\n-\t\t\tif ($i-- > 0) {\n-\t\t\t\tprint \"<td><i>$tag{'age'}</i></td>\\n\" .\n-\t\t\t\t      \"<td>\" .\n-\t\t\t\t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=shortlog;h=$tag{'name'}\"), -class => \"list\"},\n-\t\t\t\t      \"<b>\" . esc_html($tag{'name'}) . \"</b>\") .\n-\t\t\t\t      \"</td>\\n\" .\n-\t\t\t\t      \"<td class=\\\"link\\\">\" .\n-\t\t\t\t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=shortlog;h=$tag{'name'}\")}, \"shortlog\") .\n-\t\t\t\t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=log;h=$tag{'name'}\")}, \"log\") .\n-\t\t\t\t      \"</td>\\n\" .\n-\t\t\t\t      \"</tr>\";\n-\t\t\t} else {\n-\t\t\t\tprint \"<td>\" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=heads\")}, \"...\") . \"</td>\\n\" .\n-\t\t\t\t\"</tr>\";\n-\t\t\t\tlast;\n-\t\t\t}\n-\t\t}\n-\t\tprint \"</table\\n>\";\n+\t\tgit_heads_body($taglist, $head, 0, 15,\n+\t\t               $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=heads\")}, \"...\"));\n \t}\n+\n \tgit_footer_html();\n }\n \n@@ -1472,48 +1524,11 @@ sub git_tags {\n \tgit_header_html();\n \tgit_page_nav('','', $head,undef,$head);\n \tgit_header_div('summary', $project);\n-\tprint \"<table cellspacing=\\\"0\\\">\\n\";\n \n \tmy $taglist = git_read_refs(\"refs/tags\");\n-\tmy $alternate = 0;\n \tif (defined @$taglist) {\n-\t\tforeach my $entry (@$taglist) {\n-\t\t\tmy %tag = %$entry;\n-\t\t\tmy $comment_lines = $tag{'comment'};\n-\t\t\tmy $comment = shift @$comment_lines;\n-\t\t\tif (defined($comment)) {\n-\t\t\t\t$comment = chop_str($comment, 30, 5);\n-\t\t\t}\n-\t\t\tif ($alternate) {\n-\t\t\t\tprint \"<tr class=\\\"dark\\\">\\n\";\n-\t\t\t} else {\n-\t\t\t\tprint \"<tr class=\\\"light\\\">\\n\";\n-\t\t\t}\n-\t\t\t$alternate ^= 1;\n-\t\t\tprint \"<td><i>$tag{'age'}</i></td>\\n\" .\n-\t\t\t      \"<td>\" .\n-\t\t\t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=$tag{'reftype'};h=$tag{'refid'}\"), -class => \"list\"},\n-\t\t\t      \"<b>\" . esc_html($tag{'name'}) . \"</b>\") .\n-\t\t\t      \"</td>\\n\" .\n-\t\t\t      \"<td>\";\n-\t\t\tif (defined($comment)) {\n-\t\t\t\tprint $cgi->a({-class => \"list\", -href => \"$my_uri?\" . esc_param(\"p=$project;a=tag;h=$tag{'id'}\")}, $comment);\n-\t\t\t}\n-\t\t\tprint \"</td>\\n\" .\n-\t\t\t      \"<td class=\\\"link\\\">\";\n-\t\t\tif ($tag{'type'} eq \"tag\") {\n-\t\t\t\tprint $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=tag;h=$tag{'id'}\")}, \"tag\") . \" | \";\n-\t\t\t}\n-\t\t\tprint $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=$tag{'reftype'};h=$tag{'refid'}\")}, $tag{'reftype'});\n-\t\t\tif ($tag{'reftype'} eq \"commit\") {\n-\t\t\t\tprint \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=shortlog;h=$tag{'name'}\")}, \"shortlog\") .\n-\t\t\t\t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=log;h=$tag{'refid'}\")}, \"log\");\n-\t\t\t}\n-\t\t\tprint \"</td>\\n\" .\n-\t\t\t      \"</tr>\";\n-\t\t}\n+\t\tgit_tags_body($taglist);\n \t}\n-\tprint \"</table\\n>\";\n \tgit_footer_html();\n }\n \n@@ -1521,32 +1536,13 @@ sub git_heads {\n \tmy $head = git_read_head($project);\n \tgit_header_html();\n \tgit_page_nav('','', $head,undef,$head);\n-\thit_header_div('summary', $project);\n-\tprint \"<table cellspacing=\\\"0\\\">\\n\";\n+\tgit_header_div('summary', $project);\n \n \tmy $taglist = git_read_refs(\"refs/heads\");\n \tmy $alternate = 0;\n \tif (defined @$taglist) {\n-\t\tforeach my $entry (@$taglist) {\n-\t\t\tmy %tag = %$entry;\n-\t\t\tif ($alternate) {\n-\t\t\t\tprint \"<tr class=\\\"dark\\\">\\n\";\n-\t\t\t} else {\n-\t\t\t\tprint \"<tr class=\\\"light\\\">\\n\";\n-\t\t\t}\n-\t\t\t$alternate ^= 1;\n-\t\t\tprint \"<td><i>$tag{'age'}</i></td>\\n\" .\n-\t\t\t      \"<td>\" .\n-\t\t\t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=shortlog;h=$tag{'name'}\"), -class => \"list\"}, \"<b>\" . esc_html($tag{'name'}) . \"</b>\") .\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=shortlog;h=$tag{'name'}\")}, \"shortlog\") .\n-\t\t\t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=log;h=$tag{'name'}\")}, \"log\") .\n-\t\t\t      \"</td>\\n\" .\n-\t\t\t      \"</tr>\";\n-\t\t}\n+\t\tgit_heads_body($taglist, $head);\n \t}\n-\tprint \"</table\\n>\";\n \tgit_footer_html();\n }\n \n@@ -2544,48 +2540,19 @@ sub git_shortlog {\n \tclose $fd;\n \n \tmy $paging_nav = git_get_paging_nav('shortlog', $hash, $head, $page, $#revlist);\n+\tmy $next_link = '';\n+\tif ($#revlist >= (100 * ($page+1)-1)) {\n+\t\t$next_link =\n+\t\t\t$cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=shortlog;h=$hash;pg=\" . ($page+1)),\n+\t\t\t         -title => \"Alt-n\"}, \"next\");\n+\t}\n+\n \n \tgit_header_html();\n \tgit_page_nav('shortlog','', $hash,$hash,$hash, $paging_nav);\n \tgit_header_div('summary', $project);\n \n-\tprint \"<table cellspacing=\\\"0\\\">\\n\";\n-\tmy $alternate = 0;\n-\tfor (my $i = ($page * 100); $i <= $#revlist; $i++) {\n-\t\tmy $commit = $revlist[$i];\n-\t\tmy $ref = git_get_referencing($refs, $commit);\n-\t\tmy %co = git_read_commit($commit);\n-\t\tmy %ad = date_str($co{'author_epoch'});\n-\t\tif ($alternate) {\n-\t\t\tprint \"<tr class=\\\"dark\\\">\\n\";\n-\t\t} else {\n-\t\t\tprint \"<tr class=\\\"light\\\">\\n\";\n-\t\t}\n-\t\t$alternate ^= 1;\n-\t\tprint \"<td title=\\\"$co{'age_string_age'}\\\"><i>$co{'age_string_date'}</i></td>\\n\" .\n-\t\t      \"<td><i>\" . esc_html(chop_str($co{'author_name'}, 10)) . \"</i></td>\\n\" .\n-\t\t      \"<td>\";\n-\t\tif (length($co{'title_short'}) < length($co{'title'})) {\n-\t\t\tprint $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=commit;h=$commit\"), -class => \"list\", -title => \"$co{'title'}\"},\n-\t\t\t      \"<b>\" . esc_html($co{'title_short'}) . \"$ref</b>\");\n-\t\t} else {\n-\t\t\tprint $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=commit;h=$commit\"), -class => \"list\"},\n-\t\t\t      \"<b>\" . esc_html($co{'title_short'}) . \"$ref</b>\");\n-\t\t}\n-\t\tprint \"</td>\\n\" .\n-\t\t      \"<td class=\\\"link\\\">\" .\n-\t\t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=commit;h=$commit\")}, \"commit\") .\n-\t\t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=commitdiff;h=$commit\")}, \"commitdiff\") .\n-\t\t      \"</td>\\n\" .\n-\t\t      \"</tr>\";\n-\t}\n-\tif ($#revlist >= (100 * ($page+1)-1)) {\n-\t\tprint \"<tr>\\n\" .\n-\t\t      \"<td>\" .\n-\t\t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=shortlog;h=$hash;pg=\" . ($page+1)), -title => \"Alt-n\"}, \"next\") .\n-\t\t      \"</td>\\n\" .\n-\t\t      \"</tr>\\n\";\n-\t}\n-\tprint \"</table\\n>\";\n+\tgit_shortlog_body(\\@revlist, ($page * 100), $#revlist, $refs, $next_link);\n+\n \tgit_footer_html();\n }\ndiff --git a/gitweb/gitweb.css b/gitweb/gitweb.css\nindex fffdb13..460e728 100644\n--- a/gitweb/gitweb.css\n+++ b/gitweb/gitweb.css\n@@ -181,12 +181,16 @@ td {\n \tvertical-align: top;\n }\n \n-td.link {\n+td.link, td.selflink {\n \tpadding: 2px 5px;\n \tfont-family: sans-serif;\n \tfont-size: 10px;\n }\n \n+td.selflink {\n+\tpadding-right: 0px;\n+}\n+\n td.sha1 {\n \tfont-family: monospace;\n }\n@@ -196,6 +200,10 @@ td.error {\n \tbackground-color: yellow;\n }\n \n+td.current_head {\n+\ttext-decoration: underline;\n+}\n+\n table.diff_tree span.file_status.new {\n \tcolor: #008000;\n }\n-- \n1.4.0\n"},{"id":"24424","messageId":"7virle6o5z.fsf@assigned-by-dhcp.cox.net","threadId":"5038","inReplyTo":"200607292251.21072.jnareb@gmail.com","subject":"Re: [PATCH 2] gitweb: Use list for of open for running git commands, thorougly.","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-07-31T10:53:28Z","receivedAt":"2006-07-31T10:53:28Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"This, together with PATCH 6, seems to break \"history\" link.\nVisit a repository (summary page), click on \"tree\" on the second\nline, and click on \"history\" (on any blob or tree).\n\nI might have made a merge mistake while squashing PATCH 2 and\nPATCH 6 into a single commit.\n\nBTW, please be careful on trailing whitespaces.\n\nI've wasted quite a lot of time yesterday just fixing up\ntrailing whitespaces from your patches (although the first in\nyour series was \"whitespace cleanup\" X-<).\n\nI usually apply patches with whitespace=strip, unless there is a\ncompelling reason not to (e.g. when the patch is to add a\ntestcase of diff output which would inevitably have trailing\nwhitespaces when a context contains an empty line), which means\nif you have a series of patches whose later patch updates lines\nwith trailing whitespaces an earlier patch introduced the patch\nwould not apply.\n"},{"id":"24429","messageId":"eakqaj$530$1@sea.gmane.org","threadId":"5038","inReplyTo":"7virle6o5z.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH 2] gitweb: Use list for of open for running git commands, thorougly.","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-07-31T11:42:26Z","receivedAt":"2006-07-31T11:42:26Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Junio C Hamano wrote:\n\n> This, together with PATCH 6, seems to break \"history\" link.\n> Visit a repository (summary page), click on \"tree\" on the second\n> line, and click on \"history\" (on any blob or tree).\n\nStrange... returning this part of git_history to previous version, i.e.\n\n  open my $fd, \"-|\",\n    \"$GIT rev-list --full-history $hash_base -- \\'$file_name\\'\";\n\nstill gives no history. Curious. Will examine that...\n\n> BTW, please be careful on trailing whitespaces.\n\nI'm sorry for that. I have forgot to turn-on default git pre-commit it clone\nof git repository I'm not working on...\n\n-- \nJakub Narebski\nWarsaw, Poland\nShadeHawk on #git\n"},{"id":"24430","messageId":"eakrub$99t$1@sea.gmane.org","threadId":"5038","inReplyTo":"eakqaj$530$1@sea.gmane.org","subject":"Re: [PATCH 2] gitweb: Use list for of open for running git commands, thorougly.","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-07-31T12:10:02Z","receivedAt":"2006-07-31T12:10:02Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Jakub Narebski wrote:\n\n> Junio C Hamano wrote:\n> \n>> This, together with PATCH 6, seems to break \"history\" link.\n>> Visit a repository (summary page), click on \"tree\" on the second\n>> line, and click on \"history\" (on any blob or tree).\n> \n> Strange... returning this part of git_history to previous version, i.e.\n> \n>   open my $fd, \"-|\",\n>     \"$GIT rev-list --full-history $hash_base -- \\'$file_name\\'\";\n> \n> still gives no history. Curious. Will examine that...\n\nCuriouser and curiouser. It seems that somehow --full-history option \n(which was never documented by the way) got lost somewhere.\n\n  ~/git> git merge-base --all next HEAD\n  688a75071490101dbc660e3304aafb7a13e28807\n\n  ~/git> git log --full-history HEAD -- gitweb/test/file+plus+sign\n  fatal: unrecognized argument: --full-history\n\n(same with 'git rev-list --full-history HEAD -- gitweb/test/file+plus+sign',\nbut it shows help instead of simply croaking like git-log).\n\n-- \nJakub Narebski\nWarsaw, Poland\nShadeHawk on #git\n"},{"id":"24433","messageId":"eaktj9$df1$1@sea.gmane.org","threadId":"5038","inReplyTo":"eakrub$99t$1@sea.gmane.org","subject":"Re: [PATCH 2] gitweb: Use list for of open for running git commands, thorougly.","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-07-31T12:38:15Z","receivedAt":"2006-07-31T12:38:15Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Jakub Narebski wrote:\n\n> Jakub Narebski wrote:\n> \n>> Junio C Hamano wrote:\n>> \n>>> This, together with PATCH 6, seems to break \"history\" link.\n>>> Visit a repository (summary page), click on \"tree\" on the second\n>>> line, and click on \"history\" (on any blob or tree).\n>> \n>> Strange... returning this part of git_history to previous version, i.e.\n>> \n>>   open my $fd, \"-|\",\n>>     \"$GIT rev-list --full-history $hash_base -- \\'$file_name\\'\";\n>> \n>> still gives no history. Curious. Will examine that...\n> \n> Curiouser and curiouser. It seems that somehow --full-history option \n> (which was never documented by the way) got lost somewhere.\n\nOoops. I've forgot that '--full-history' option was introduced after v1.4.0\n(which I use).\n\n-- \nJakub Narebski\nWarsaw, Poland\nShadeHawk on #git\n"},{"id":"24435","messageId":"eakuqs$hpc$1@sea.gmane.org","threadId":"5038","inReplyTo":"7virle6o5z.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH 2] gitweb: Use list for of open for running git commands, thorougly.","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-07-31T12:59:24Z","receivedAt":"2006-07-31T12:59:24Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Junio C Hamano wrote:\n\n> This, together with PATCH 6, seems to break \"history\" link.\n> Visit a repository (summary page), click on \"tree\" on the second\n> line, and click on \"history\" (on any blob or tree).\n\nIt works for me (both --full-history and gitweb) for git 1.4.1.1, although\n--full-history doesn't seem to add anything for this version of git:\n\n  ~/git> time git rev-list HEAD -- gitweb/test/file+plus+sign\n  0a8f4f0020cb35095005852c0797f0b90e9ebb74\n\n  real    0m2.562s\n  user    0m2.412s\n  sys     0m0.024s\n\n\n  ~/git> time git rev-list --full-history HEAD -- gitweb/test/file+plus+sign\n  0a8f4f0020cb35095005852c0797f0b90e9ebb74\n\n  real    0m8.564s\n  user    0m7.212s\n  sys     0m0.068s\n\nwhile correct result should be\n\n  ~/git> time git rev-list HEAD -- gitweb/test/file+plus+sign \\\n                                   test/file+plus+sign\n  0a8f4f0020cb35095005852c0797f0b90e9ebb74\n  85852d44e48c1d1c6d815cc5fccf1b580f2f2cad\n  cc3245b6512a01d74c0fd460d762ba8a1e8b968a\n\n  real    0m2.565s\n  user    0m2.452s\n  sys     0m0.008s\n\ngit version 1.4.1.1\n-- \nJakub Narebski\nWarsaw, Poland\nShadeHawk on #git\n"},{"id":"24438","messageId":"200607311833.39524.jnareb@gmail.com","threadId":"5038","inReplyTo":"200607292239.11034.jnareb@gmail.com","subject":"[PATCH 19] gitweb: No need to quote path for list version of open \"-|\"","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-07-31T16:33:37Z","receivedAt":"2006-07-31T16:33:37Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Signed-off-by: Jakub Narebski <jnareb@gmail.com>\n---\n gitweb/gitweb.cgi |    2 +-\n 1 files changed, 1 insertions(+), 1 deletions(-)\n\ndiff --git a/gitweb/gitweb.cgi b/gitweb/gitweb.cgi\nindex d209af0..f7fe28a 100755\n--- a/gitweb/gitweb.cgi\n+++ b/gitweb/gitweb.cgi\n@@ -2347,7 +2347,7 @@ sub git_history {\n \tgit_print_page_path($file_name, $ftype);\n \n \topen my $fd, \"-|\",\n-\t\t$GIT, \"rev-list\", \"--full-history\", $hash_base, \"--\", \"\\'$file_name\\'\";\n+\t\t$GIT, \"rev-list\", \"--full-history\", $hash_base, \"--\", $file_name;\n \tprint \"<table cellspacing=\\\"0\\\">\\n\";\n \tmy $alternate = 0;\n \twhile (my $line = <$fd>) {\n-- \n1.4.1.1\n"},{"id":"24441","messageId":"ealcsb$88c$1@sea.gmane.org","threadId":"5038","inReplyTo":"200607302236.06686.jnareb@gmail.com","subject":"Re: [PATCH 16] gitweb: Remove characters entities entirely when shortening string","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-07-31T16:59:08Z","receivedAt":"2006-07-31T16:59:08Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Jakub Narebski wrote:\n\n> --- a/gitweb/gitweb.cgi\n> +++ b/gitweb/gitweb.cgi\n> @@ -776,6 +776,7 @@ sub chop_str {\n>       my $tail = $2;\n>       if (length($tail) > 4) {\n>               $tail = \" ...\";\n> +             $body =~ s/&[^;]$//; # remove chopped character entities\n>       }\n>       return \"$body$tail\";\n>  }\n\nOf course it should be\n\n+               $body =~ s/&[^;]*$//; # remove chopped character entities\n\n-- \nJakub Narebski\nWarsaw, Poland\nShadeHawk on #git\n"},{"id":"24450","messageId":"200607312048.44075.jnareb@gmail.com","threadId":"5038","inReplyTo":"200607292239.11034.jnareb@gmail.com","subject":"[PATCH 20] gitweb: Reordering code and dividing it into categories","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-07-31T18:48:43Z","receivedAt":"2006-07-31T18:48:43Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Reorder gitweb code around, divide it into sections (categories) and\nadd some comments.\n\nSigned-off-by: Jakub Narebski <jnareb@gmail.com>\n---\nThis patch is superficially large, as it only moves code around,\nand add only a little.\n\n gitweb/gitweb.cgi | 1672 ++++++++++++++++++++++++++++-------------------------\n 1 files changed, 898 insertions(+), 774 deletions(-)\n\ndiff --git a/gitweb/gitweb.cgi b/gitweb/gitweb.cgi\nindex cb6af39..2d710ae 100755\n--- a/gitweb/gitweb.cgi\n+++ b/gitweb/gitweb.cgi\n@@ -160,19 +160,65 @@ if (defined $searchtext) {\n \t$searchtext = quotemeta $searchtext;\n }\n \n-sub validate_input {\n-\tmy $input = shift;\n-\n-\tif ($input =~ m/^[0-9a-fA-F]{40}$/) {\n-\t\treturn $input;\n-\t}\n-\tif ($input =~ m/(^|\\/)(|\\.|\\.\\.)($|\\/)/) {\n-\t\treturn undef;\n-\t}\n-\tif ($input =~ m/[^a-zA-Z0-9_\\x80-\\xff\\ \\t\\.\\/\\-\\+\\#\\~\\%]/) {\n-\t\treturn undef;\n-\t}\n-\treturn $input;\n+# dispatch\n+if (!defined $action || $action eq \"summary\") {\n+\tgit_summary();\n+\texit;\n+} elsif ($action eq \"heads\") {\n+\tgit_heads();\n+\texit;\n+} elsif ($action eq \"tags\") {\n+\tgit_tags();\n+\texit;\n+} elsif ($action eq \"blob\") {\n+\tgit_blob();\n+\texit;\n+} elsif ($action eq \"blob_plain\") {\n+\tgit_blob_plain();\n+\texit;\n+} elsif ($action eq \"tree\") {\n+\tgit_tree();\n+\texit;\n+} elsif ($action eq \"rss\") {\n+\tgit_rss();\n+\texit;\n+} elsif ($action eq \"commit\") {\n+\tgit_commit();\n+\texit;\n+} elsif ($action eq \"log\") {\n+\tgit_log();\n+\texit;\n+} elsif ($action eq \"blobdiff\") {\n+\tgit_blobdiff();\n+\texit;\n+} elsif ($action eq \"blobdiff_plain\") {\n+\tgit_blobdiff_plain();\n+\texit;\n+} elsif ($action eq \"commitdiff\") {\n+\tgit_commitdiff();\n+\texit;\n+} elsif ($action eq \"commitdiff_plain\") {\n+\tgit_commitdiff_plain();\n+\texit;\n+} elsif ($action eq \"history\") {\n+\tgit_history();\n+\texit;\n+} elsif ($action eq \"search\") {\n+\tgit_search();\n+\texit;\n+} elsif ($action eq \"shortlog\") {\n+\tgit_shortlog();\n+\texit;\n+} elsif ($action eq \"tag\") {\n+\tgit_tag();\n+\texit;\n+} elsif ($action eq \"blame\") {\n+\tgit_blame2();\n+\texit;\n+} else {\n+\tundef $action;\n+\tdie_error(undef, \"Unknown action.\");\n+\texit;\n }\n \n if (!defined $action || $action eq \"summary\") {\n@@ -235,6 +281,24 @@ if (!defined $action || $action eq \"summ\n \texit;\n }\n \n+## ======================================================================\n+## validation, quoting/unquoting and escaping\n+\n+sub validate_input {\n+\tmy $input = shift;\n+\n+\tif ($input =~ m/^[0-9a-fA-F]{40}$/) {\n+\t\treturn $input;\n+\t}\n+\tif ($input =~ m/(^|\\/)(|\\.|\\.\\.)($|\\/)/) {\n+\t\treturn undef;\n+\t}\n+\tif ($input =~ m/[^a-zA-Z0-9_\\x80-\\xff\\ \\t\\.\\/\\-\\+\\#\\~\\%]/) {\n+\t\treturn undef;\n+\t}\n+\treturn $input;\n+}\n+\n # quote unsafe chars, but keep the slash, even when it's not\n # correct, but quoted slashes look too horrible in bookmarks\n sub esc_param {\n@@ -264,6 +328,29 @@ sub unquote {\n \treturn $str;\n }\n \n+## ----------------------------------------------------------------------\n+## HTML aware string manipulation\n+\n+sub chop_str {\n+\tmy $str = shift;\n+\tmy $len = shift;\n+\tmy $add_len = shift || 10;\n+\n+\t# allow only $len chars, but don't cut a word if it would fit in $add_len\n+\t# if it doesn't fit, cut it if it's still longer than the dots we would add\n+\t$str =~ m/^(.{0,$len}[^ \\/\\-_:\\.@]{0,$add_len})(.*)/;\n+\tmy $body = $1;\n+\tmy $tail = $2;\n+\tif (length($tail) > 4) {\n+\t\t$tail = \" ...\";\n+\t\t$body =~ s/&[^;]*$//; # remove chopped character entities\n+\t}\n+\treturn \"$body$tail\";\n+}\n+\n+## ----------------------------------------------------------------------\n+## functions returning short strings\n+\n # CSS class for given age value (in seconds)\n sub age_class {\n \tmy $age = shift;\n@@ -277,202 +364,108 @@ sub age_class {\n \t}\n }\n \n-sub git_header_html {\n-\tmy $status = shift || \"200 OK\";\n-\tmy $expires = shift;\n+# convert age in seconds to \"nn units ago\" string\n+sub age_string {\n+\tmy $age = shift;\n+\tmy $age_str;\n \n-\tmy $title = \"$site_name git\";\n-\tif (defined $project) {\n-\t\t$title .= \" - $project\";\n-\t\tif (defined $action) {\n-\t\t\t$title .= \"/$action\";\n-\t\t\tif (defined $file_name) {\n-\t\t\t\t$title .= \" - $file_name\";\n-\t\t\t\tif ($action eq \"tree\" && $file_name !~ m|/$|) {\n-\t\t\t\t\t$title .= \"/\";\n-\t\t\t\t}\n-\t\t\t}\n-\t\t}\n-\t}\n-\tmy $content_type;\n-\t# require explicit support from the UA if we are to send the page as\n-\t# 'application/xhtml+xml', otherwise send it as plain old 'text/html'.\n-\t# we have to do this because MSIE sometimes globs '*/*', pretending to\n-\t# support xhtml+xml but choking when it gets what it asked for.\n-\tif ($cgi->http('HTTP_ACCEPT') =~ m/(,|;|\\s|^)application\\/xhtml\\+xml(,|;|\\s|$)/ && $cgi->Accept('application/xhtml+xml') != 0) {\n-\t\t$content_type = 'application/xhtml+xml';\n+\tif ($age > 60*60*24*365*2) {\n+\t\t$age_str = (int $age/60/60/24/365);\n+\t\t$age_str .= \" years ago\";\n+\t} elsif ($age > 60*60*24*(365/12)*2) {\n+\t\t$age_str = int $age/60/60/24/(365/12);\n+\t\t$age_str .= \" months ago\";\n+\t} elsif ($age > 60*60*24*7*2) {\n+\t\t$age_str = int $age/60/60/24/7;\n+\t\t$age_str .= \" weeks ago\";\n+\t} elsif ($age > 60*60*24*2) {\n+\t\t$age_str = int $age/60/60/24;\n+\t\t$age_str .= \" days ago\";\n+\t} elsif ($age > 60*60*2) {\n+\t\t$age_str = int $age/60/60;\n+\t\t$age_str .= \" hours ago\";\n+\t} elsif ($age > 60*2) {\n+\t\t$age_str = int $age/60;\n+\t\t$age_str .= \" min ago\";\n+\t} elsif ($age > 2) {\n+\t\t$age_str = int $age;\n+\t\t$age_str .= \" sec ago\";\n \t} else {\n-\t\t$content_type = 'text/html';\n-\t}\n-\tprint $cgi->header(-type=>$content_type, -charset => 'utf-8', -status=> $status, -expires => $expires);\n-\tprint <<EOF;\n-<?xml version=\"1.0\" encoding=\"utf-8\"?>\n-<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n-<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en-US\" lang=\"en-US\">\n-<!-- git web interface v$version, (C) 2005-2006, Kay Sievers <kay.sievers\\@vrfy.org>, Christian Gierke -->\n-<!-- git core binaries version $git_version -->\n-<head>\n-<meta http-equiv=\"content-type\" content=\"$content_type; charset=utf-8\"/>\n-<meta name=\"robots\" content=\"index, nofollow\"/>\n-<title>$title</title>\n-<link rel=\"stylesheet\" type=\"text/css\" href=\"$stylesheet\"/>\n-$rss_link\n-</head>\n-<body>\n-EOF\n-\tprint \"<div class=\\\"page_header\\\">\\n\" .\n-\t      \"<a href=\\\"http://www.kernel.org/pub/software/scm/git/docs/\\\" title=\\\"git documentation\\\">\" .\n-\t      \"<img src=\\\"$my_uri?\" . esc_param(\"a=git-logo.png\") . \"\\\" width=\\\"72\\\" height=\\\"27\\\" alt=\\\"git\\\" style=\\\"float:right; border-width:0px;\\\"/>\" .\n-\t      \"</a>\\n\";\n-\tprint $cgi->a({-href => esc_param($home_link)}, \"projects\") . \" / \";\n-\tif (defined $project) {\n-\t\tprint $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=summary\")}, esc_html($project));\n-\t\tif (defined $action) {\n-\t\t\tprint \" / $action\";\n-\t\t}\n-\t\tprint \"\\n\";\n-\t\tif (!defined $searchtext) {\n-\t\t\t$searchtext = \"\";\n-\t\t}\n-\t\tmy $search_hash;\n-\t\tif (defined $hash_base) {\n-\t\t\t$search_hash = $hash_base;\n-\t\t} elsif (defined $hash) {\n-\t\t\t$search_hash = $hash;\n-\t\t} else {\n-\t\t\t$search_hash = \"HEAD\";\n-\t\t}\n-\t\t$cgi->param(\"a\", \"search\");\n-\t\t$cgi->param(\"h\", $search_hash);\n-\t\tprint $cgi->startform(-method => \"get\", -action => $my_uri) .\n-\t\t      \"<div class=\\\"search\\\">\\n\" .\n-\t\t      $cgi->hidden(-name => \"p\") . \"\\n\" .\n-\t\t      $cgi->hidden(-name => \"a\") . \"\\n\" .\n-\t\t      $cgi->hidden(-name => \"h\") . \"\\n\" .\n-\t\t      $cgi->textfield(-name => \"s\", -value => $searchtext) . \"\\n\" .\n-\t\t      \"</div>\" .\n-\t\t      $cgi->end_form() . \"\\n\";\n+\t\t$age_str .= \" right now\";\n \t}\n-\tprint \"</div>\\n\";\n+\treturn $age_str;\n }\n \n-sub git_footer_html {\n-\tprint \"<div class=\\\"page_footer\\\">\\n\";\n-\tif (defined $project) {\n-\t\tmy $descr = git_read_description($project);\n-\t\tif (defined $descr) {\n-\t\t\tprint \"<div class=\\\"page_footer_text\\\">\" . esc_html($descr) . \"</div>\\n\";\n-\t\t}\n-\t\tprint $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=rss\"), -class => \"rss_logo\"}, \"RSS\") . \"\\n\";\n+# convert file mode in octal to symbolic file mode string\n+sub mode_str {\n+\tmy $mode = oct shift;\n+\n+\tif (S_ISDIR($mode & S_IFMT)) {\n+\t\treturn 'drwxr-xr-x';\n+\t} elsif (S_ISLNK($mode)) {\n+\t\treturn 'lrwxrwxrwx';\n+\t} elsif (S_ISREG($mode)) {\n+\t\t# git cares only about the executable bit\n+\t\tif ($mode & S_IXUSR) {\n+\t\t\treturn '-rwxr-xr-x';\n+\t\t} else {\n+\t\t\treturn '-rw-r--r--';\n+\t\t};\n \t} else {\n-\t\tprint $cgi->a({-href => \"$my_uri?\" . esc_param(\"a=opml\"), -class => \"rss_logo\"}, \"OPML\") . \"\\n\";\n+\t\treturn '----------';\n \t}\n-\tprint \"</div>\\n\" .\n-\t      \"</body>\\n\" .\n-\t      \"</html>\";\n }\n \n-sub die_error {\n-\tmy $status = shift || \"403 Forbidden\";\n-\tmy $error = shift || \"Malformed query, file missing or permission denied\";\n+# convert file mode in octal to file type string\n+sub file_type {\n+\tmy $mode = oct shift;\n \n-\tgit_header_html($status);\n-\tprint \"<div class=\\\"page_body\\\">\\n\" .\n-\t      \"<br/><br/>\\n\" .\n-\t      \"$status - $error\\n\" .\n-\t      \"<br/>\\n\" .\n-\t      \"</div>\\n\";\n-\tgit_footer_html();\n-\texit;\n+\tif (S_ISDIR($mode & S_IFMT)) {\n+\t\treturn \"directory\";\n+\t} elsif (S_ISLNK($mode)) {\n+\t\treturn \"symlink\";\n+\t} elsif (S_ISREG($mode)) {\n+\t\treturn \"file\";\n+\t} else {\n+\t\treturn \"unknown\";\n+\t}\n }\n \n-sub git_page_nav {\n-\tmy ($current, $suppress, $head, $treehead, $treebase, $extra) = @_;\n-\t$extra = '' if !defined $extra; # pager or formats\n+## ----------------------------------------------------------------------\n+## functions returning short HTML fragments, or transforming HTML fragments\n+## which don't beling to other sections\n \n-\tmy @navs = qw(summary shortlog log commit commitdiff tree);\n-\tif ($suppress) {\n-\t\t@navs = grep { $_ ne $suppress } @navs;\n-\t}\n+# format line of commit message or tag comment\n+sub format_log_line_html {\n+\tmy $line = shift;\n \n-\tmy %arg = map { $_, ''} @navs;\n-\tif (defined $head) {\n-\t\tfor (qw(commit commitdiff)) {\n-\t\t\t$arg{$_} = \";h=$head\";\n-\t\t}\n-\t\tif ($current =~ m/^(tree | log | shortlog | commit | commitdiff | search)$/x) {\n-\t\t\tfor (qw(shortlog log)) {\n-\t\t\t\t$arg{$_} = \";h=$head\";\n-\t\t\t}\n+\t$line = esc_html($line);\n+\t$line =~ s/ /&nbsp;/g;\n+\tif ($line =~ m/([0-9a-fA-F]{40})/) {\n+\t\tmy $hash_text = $1;\n+\t\tif (git_get_type($hash_text) eq \"commit\") {\n+\t\t\tmy $link = $cgi->a({-class => \"text\", -href => \"$my_uri?\" . esc_param(\"p=$project;a=commit;h=$hash_text\")}, $hash_text);\n+\t\t\t$line =~ s/$hash_text/$link/;\n \t\t}\n \t}\n-\t$arg{tree} .= \";h=$treehead\" if defined $treehead;\n-\t$arg{tree} .= \";hb=$treebase\" if defined $treebase;\n-\n-\tprint \"<div class=\\\"page_nav\\\">\\n\" .\n-\t\t(join \" | \",\n-\t\t map { $_ eq $current\n-\t\t\t\t\t ? $_\n-\t\t\t\t\t : $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=$_$arg{$_}\")}, \"$_\")\n-\t\t\t\t }\n-\t\t @navs);\n-\tprint \"<br/>\\n$extra<br/>\\n\" .\n-\t      \"</div>\\n\";\n-}\n-\n-sub git_header_div {\n-\tmy ($action, $title, $hash, $hash_base) = @_;\n-\tmy $rest = '';\n-\n-\t$rest .= \";h=$hash\" if $hash;\n-\t$rest .= \";hb=$hash_base\" if $hash_base;\n-\n-\tprint \"<div class=\\\"header\\\">\\n\" .\n-\t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=$action$rest\"),\n-\t               -class => \"title\"}, $title ? $title : $action) . \"\\n\" .\n-\t      \"</div>\\n\";\n+\treturn $line;\n }\n \n-sub git_get_paging_nav {\n-\tmy ($action, $hash, $head, $page, $nrevs) = @_;\n-\tmy $paging_nav;\n-\n-\n-\tif ($hash ne $head || $page) {\n-\t\t$paging_nav .= $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=$action\")}, \"HEAD\");\n-\t} else {\n-\t\t$paging_nav .= \"HEAD\";\n-\t}\n-\n-\tif ($page > 0) {\n-\t\t$paging_nav .= \" &sdot; \" .\n-\t\t\t$cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=$action;h=$hash;pg=\" . ($page-1)),\n-\t\t\t\t\t\t\t -accesskey => \"p\", -title => \"Alt-p\"}, \"prev\");\n-\t} else {\n-\t\t$paging_nav .= \" &sdot; prev\";\n-\t}\n+# format marker of refs pointing to given object\n+sub git_get_referencing {\n+\tmy ($refs, $id) = @_;\n \n-\tif ($nrevs >= (100 * ($page+1)-1)) {\n-\t\t$paging_nav .= \" &sdot; \" .\n-\t\t\t$cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=$action;h=$hash;pg=\" . ($page+1)),\n-\t\t\t\t\t\t\t -accesskey => \"n\", -title => \"Alt-n\"}, \"next\");\n+\tif (defined $refs->{$id}) {\n+\t\treturn ' <span class=\"tag\">' . esc_html($refs->{$id}) . '</span>';\n \t} else {\n-\t\t$paging_nav .= \" &sdot; next\";\n+\t\treturn \"\";\n \t}\n-\n-\treturn $paging_nav;\n }\n \n-sub git_get_type {\n-\tmy $hash = shift;\n-\n-\topen my $fd, \"-|\", $GIT, \"cat-file\", '-t', $hash or return;\n-\tmy $type = <$fd>;\n-\tclose $fd or return;\n-\tchomp $type;\n-\treturn $type;\n-}\n+## ----------------------------------------------------------------------\n+## git utility subroutines, invoking git commands\n \n+# get HEAD ref of given project as hash\n sub git_read_head {\n \tmy $project = shift;\n \tmy $oENV = $ENV{'GIT_DIR'};\n@@ -491,6 +484,57 @@ sub git_read_head {\n \treturn $retval;\n }\n \n+# get type of given object\n+sub git_get_type {\n+\tmy $hash = shift;\n+\n+\topen my $fd, \"-|\", $GIT, \"cat-file\", '-t', $hash or return;\n+\tmy $type = <$fd>;\n+\tclose $fd or return;\n+\tchomp $type;\n+\treturn $type;\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+# get hash of given path at given ref\n+sub git_get_hash_by_path {\n+\tmy $base = shift;\n+\tmy $path = shift || return undef;\n+\n+\tmy $tree = $base;\n+\n+\topen my $fd, \"-|\", $GIT, \"ls-tree\", $base, \"--\", $path\n+\t\tor die_error(undef, \"Open git-ls-tree failed.\");\n+\tmy $line = <$fd>;\n+\tclose $fd or return undef;\n+\n+\t#'100644 blob 0fa3f3a66fb6a137f6ec2c19351ed4d807070ffa\tpanic.c'\n+\t$line =~ m/^([0-9]+) (.+) ([0-9a-fA-F]{40})\\t(.+)$/;\n+\treturn $3;\n+}\n+\n+## ......................................................................\n+## git utility functions, directly accessing git repository\n+\n+# assumes that PATH is not symref\n sub git_read_hash {\n \tmy $path = shift;\n \n@@ -513,6 +557,100 @@ sub git_read_description {\n \treturn $descr;\n }\n \n+sub git_read_projects {\n+\tmy @list;\n+\n+\tif (-d $projects_list) {\n+\t\t# search in directory\n+\t\tmy $dir = $projects_list;\n+\t\topendir my ($dh), $dir or return undef;\n+\t\twhile (my $dir = readdir($dh)) {\n+\t\t\tif (-e \"$projectroot/$dir/HEAD\") {\n+\t\t\t\tmy $pr = {\n+\t\t\t\t\tpath => $dir,\n+\t\t\t\t};\n+\t\t\t\tpush @list, $pr\n+\t\t\t}\n+\t\t}\n+\t\tclosedir($dh);\n+\t} elsif (-f $projects_list) {\n+\t\t# read from file(url-encoded):\n+\t\t# 'git%2Fgit.git Linus+Torvalds'\n+\t\t# 'libs%2Fklibc%2Fklibc.git H.+Peter+Anvin'\n+\t\t# 'linux%2Fhotplug%2Fudev.git Greg+Kroah-Hartman'\n+\t\topen my ($fd), $projects_list or return undef;\n+\t\twhile (my $line = <$fd>) {\n+\t\t\tchomp $line;\n+\t\t\tmy ($path, $owner) = split ' ', $line;\n+\t\t\t$path = unescape($path);\n+\t\t\t$owner = unescape($owner);\n+\t\t\tif (!defined $path) {\n+\t\t\t\tnext;\n+\t\t\t}\n+\t\t\tif (-e \"$projectroot/$path/HEAD\") {\n+\t\t\t\tmy $pr = {\n+\t\t\t\t\tpath => $path,\n+\t\t\t\t\towner => decode(\"utf8\", $owner, Encode::FB_DEFAULT),\n+\t\t\t\t};\n+\t\t\t\tpush @list, $pr\n+\t\t\t}\n+\t\t}\n+\t\tclose $fd;\n+\t}\n+\t@list = sort {$a->{'path'} cmp $b->{'path'}} @list;\n+\treturn @list;\n+}\n+\n+sub read_info_ref {\n+\tmy $type = shift || \"\";\n+\tmy %refs;\n+\t# 5dc01c595e6c6ec9ccda4f6f69c131c0dd945f8c\trefs/tags/v2.6.11\n+\t# c39ae07f393806ccf406ef966e9a15afc43cc36a\trefs/tags/v2.6.11^{}\n+\topen my $fd, \"$projectroot/$project/info/refs\" or return;\n+\twhile (my $line = <$fd>) {\n+\t\tchomp $line;\n+\t\t# attention: for $type == \"\" it saves only last path part of ref name\n+\t\t# e.g. from 'refs/heads/jn/gitweb' it would leave only 'gitweb'\n+\t\tif ($line =~ m/^([0-9a-fA-F]{40})\\t.*$type\\/([^\\^]+)/) {\n+\t\t\tif (defined $refs{$1}) {\n+\t\t\t\t$refs{$1} .= \" / $2\";\n+\t\t\t} else {\n+\t\t\t\t$refs{$1} = $2;\n+\t\t\t}\n+\t\t}\n+\t}\n+\tclose $fd or return;\n+\treturn \\%refs;\n+}\n+\n+## ----------------------------------------------------------------------\n+## parse to hash functions\n+\n+sub date_str {\n+\tmy $epoch = shift;\n+\tmy $tz = shift || \"-0000\";\n+\n+\tmy %date;\n+\tmy @months = (\"Jan\", \"Feb\", \"Mar\", \"Apr\", \"May\", \"Jun\", \"Jul\", \"Aug\", \"Sep\", \"Oct\", \"Nov\", \"Dec\");\n+\tmy @days = (\"Sun\", \"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\", \"Sat\");\n+\tmy ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday) = gmtime($epoch);\n+\t$date{'hour'} = $hour;\n+\t$date{'minute'} = $min;\n+\t$date{'mday'} = $mday;\n+\t$date{'day'} = $days[$wday];\n+\t$date{'month'} = $months[$mon];\n+\t$date{'rfc2822'} = sprintf \"%s, %d %s %4d %02d:%02d:%02d +0000\", $days[$wday], $mday, $months[$mon], 1900+$year, $hour ,$min, $sec;\n+\t$date{'mday-time'} = sprintf \"%d %s %02d:%02d\", $mday, $months[$mon], $hour ,$min;\n+\n+\t$tz =~ m/^([+\\-][0-9][0-9])([0-9][0-9])$/;\n+\tmy $local = $epoch + ((int $1 + ($2/60)) * 3600);\n+\t($sec, $min, $hour, $mday, $mon, $year, $wday, $yday) = gmtime($local);\n+\t$date{'hour_local'} = $hour;\n+\t$date{'minute_local'} = $min;\n+\t$date{'tz_local'} = $tz;\n+\treturn %date;\n+}\n+\n sub git_read_tag {\n \tmy $tag_id = shift;\n \tmy %tag;\n@@ -548,37 +686,6 @@ sub git_read_tag {\n \treturn %tag\n }\n \n-sub age_string {\n-\tmy $age = shift;\n-\tmy $age_str;\n-\n-\tif ($age > 60*60*24*365*2) {\n-\t\t$age_str = (int $age/60/60/24/365);\n-\t\t$age_str .= \" years ago\";\n-\t} elsif ($age > 60*60*24*(365/12)*2) {\n-\t\t$age_str = int $age/60/60/24/(365/12);\n-\t\t$age_str .= \" months ago\";\n-\t} elsif ($age > 60*60*24*7*2) {\n-\t\t$age_str = int $age/60/60/24/7;\n-\t\t$age_str .= \" weeks ago\";\n-\t} elsif ($age > 60*60*24*2) {\n-\t\t$age_str = int $age/60/60/24;\n-\t\t$age_str .= \" days ago\";\n-\t} elsif ($age > 60*60*2) {\n-\t\t$age_str = int $age/60/60;\n-\t\t$age_str .= \" hours ago\";\n-\t} elsif ($age > 60*2) {\n-\t\t$age_str = int $age/60;\n-\t\t$age_str .= \" min ago\";\n-\t} elsif ($age > 2) {\n-\t\t$age_str = int $age;\n-\t\t$age_str .= \" sec ago\";\n-\t} else {\n-\t\t$age_str .= \" right now\";\n-\t}\n-\treturn $age_str;\n-}\n-\n sub git_read_commit {\n \tmy $commit_id = shift;\n \tmy $commit_text = shift;\n@@ -673,380 +780,8 @@ sub git_read_commit {\n \treturn %co;\n }\n \n-sub git_diff_print {\n-\tmy $from = shift;\n-\tmy $from_name = shift;\n-\tmy $to = shift;\n-\tmy $to_name = shift;\n-\tmy $format = shift || \"html\";\n-\n-\tmy $from_tmp = \"/dev/null\";\n-\tmy $to_tmp = \"/dev/null\";\n-\tmy $pid = $$;\n-\n-\t# create tmp from-file\n-\tif (defined $from) {\n-\t\t$from_tmp = \"$git_temp/gitweb_\" . $$ . \"_from\";\n-\t\topen my $fd2, \"> $from_tmp\";\n-\t\topen my $fd, \"-|\", $GIT, \"cat-file\", \"blob\", $from;\n-\t\tmy @file = <$fd>;\n-\t\tprint $fd2 @file;\n-\t\tclose $fd2;\n-\t\tclose $fd;\n-\t}\n-\n-\t# create tmp to-file\n-\tif (defined $to) {\n-\t\t$to_tmp = \"$git_temp/gitweb_\" . $$ . \"_to\";\n-\t\topen my $fd2, \"> $to_tmp\";\n-\t\topen my $fd, \"-|\", $GIT, \"cat-file\", \"blob\", $to;\n-\t\tmy @file = <$fd>;\n-\t\tprint $fd2 @file;\n-\t\tclose $fd2;\n-\t\tclose $fd;\n-\t}\n-\n-\topen my $fd, \"-|\", \"/usr/bin/diff -u -p -L \\'$from_name\\' -L \\'$to_name\\' $from_tmp $to_tmp\";\n-\tif ($format eq \"plain\") {\n-\t\tundef $/;\n-\t\tprint <$fd>;\n-\t\t$/ = \"\\n\";\n-\t} else {\n-\t\twhile (my $line = <$fd>) {\n-\t\t\tchomp $line;\n-\t\t\tmy $char = substr($line, 0, 1);\n-\t\t\tmy $diff_class = \"\";\n-\t\t\tif ($char eq '+') {\n-\t\t\t\t$diff_class = \" add\";\n-\t\t\t} elsif ($char eq \"-\") {\n-\t\t\t\t$diff_class = \" rem\";\n-\t\t\t} elsif ($char eq \"@\") {\n-\t\t\t\t$diff_class = \" chunk_header\";\n-\t\t\t} elsif ($char eq \"\\\\\") {\n-\t\t\t\t# skip errors\n-\t\t\t\tnext;\n-\t\t\t}\n-\t\t\twhile ((my $pos = index($line, \"\\t\")) != -1) {\n-\t\t\t\tif (my $count = (8 - (($pos-1) % 8))) {\n-\t\t\t\t\tmy $spaces = ' ' x $count;\n-\t\t\t\t\t$line =~ s/\\t/$spaces/;\n-\t\t\t\t}\n-\t\t\t}\n-\t\t\tprint \"<div class=\\\"diff$diff_class\\\">\" . esc_html($line) . \"</div>\\n\";\n-\t\t}\n-\t}\n-\tclose $fd;\n-\n-\tif (defined $from) {\n-\t\tunlink($from_tmp);\n-\t}\n-\tif (defined $to) {\n-\t\tunlink($to_tmp);\n-\t}\n-}\n-\n-sub mode_str {\n-\tmy $mode = oct shift;\n-\n-\tif (S_ISDIR($mode & S_IFMT)) {\n-\t\treturn 'drwxr-xr-x';\n-\t} elsif (S_ISLNK($mode)) {\n-\t\treturn 'lrwxrwxrwx';\n-\t} elsif (S_ISREG($mode)) {\n-\t\t# git cares only about the executable bit\n-\t\tif ($mode & S_IXUSR) {\n-\t\t\treturn '-rwxr-xr-x';\n-\t\t} else {\n-\t\t\treturn '-rw-r--r--';\n-\t\t};\n-\t} else {\n-\t\treturn '----------';\n-\t}\n-}\n-\n-sub chop_str {\n-\tmy $str = shift;\n-\tmy $len = shift;\n-\tmy $add_len = shift || 10;\n-\n-\t# allow only $len chars, but don't cut a word if it would fit in $add_len\n-\t# if it doesn't fit, cut it if it's still longer than the dots we would add\n-\t$str =~ m/^(.{0,$len}[^ \\/\\-_:\\.@]{0,$add_len})(.*)/;\n-\tmy $body = $1;\n-\tmy $tail = $2;\n-\tif (length($tail) > 4) {\n-\t\t$tail = \" ...\";\n-\t\t$body =~ s/&[^;]*$//; # remove chopped character entities\n-\t}\n-\treturn \"$body$tail\";\n-}\n-\n-sub file_type {\n-\tmy $mode = oct shift;\n-\n-\tif (S_ISDIR($mode & S_IFMT)) {\n-\t\treturn \"directory\";\n-\t} elsif (S_ISLNK($mode)) {\n-\t\treturn \"symlink\";\n-\t} elsif (S_ISREG($mode)) {\n-\t\treturn \"file\";\n-\t} else {\n-\t\treturn \"unknown\";\n-\t}\n-}\n-\n-sub format_log_line_html {\n-\tmy $line = shift;\n-\n-\t$line = esc_html($line);\n-\t$line =~ s/ /&nbsp;/g;\n-\tif ($line =~ m/([0-9a-fA-F]{40})/) {\n-\t\tmy $hash_text = $1;\n-\t\tif (git_get_type($hash_text) eq \"commit\") {\n-\t\t\tmy $link = $cgi->a({-class => \"text\", -href => \"$my_uri?\" . esc_param(\"p=$project;a=commit;h=$hash_text\")}, $hash_text);\n-\t\t\t$line =~ s/$hash_text/$link/;\n-\t\t}\n-\t}\n-\treturn $line;\n-}\n-\n-sub date_str {\n-\tmy $epoch = shift;\n-\tmy $tz = shift || \"-0000\";\n-\n-\tmy %date;\n-\tmy @months = (\"Jan\", \"Feb\", \"Mar\", \"Apr\", \"May\", \"Jun\", \"Jul\", \"Aug\", \"Sep\", \"Oct\", \"Nov\", \"Dec\");\n-\tmy @days = (\"Sun\", \"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\", \"Sat\");\n-\tmy ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday) = gmtime($epoch);\n-\t$date{'hour'} = $hour;\n-\t$date{'minute'} = $min;\n-\t$date{'mday'} = $mday;\n-\t$date{'day'} = $days[$wday];\n-\t$date{'month'} = $months[$mon];\n-\t$date{'rfc2822'} = sprintf \"%s, %d %s %4d %02d:%02d:%02d +0000\", $days[$wday], $mday, $months[$mon], 1900+$year, $hour ,$min, $sec;\n-\t$date{'mday-time'} = sprintf \"%d %s %02d:%02d\", $mday, $months[$mon], $hour ,$min;\n-\n-\t$tz =~ m/^([+\\-][0-9][0-9])([0-9][0-9])$/;\n-\tmy $local = $epoch + ((int $1 + ($2/60)) * 3600);\n-\t($sec, $min, $hour, $mday, $mon, $year, $wday, $yday) = gmtime($local);\n-\t$date{'hour_local'} = $hour;\n-\t$date{'minute_local'} = $min;\n-\t$date{'tz_local'} = $tz;\n-\treturn %date;\n-}\n-\n-# git-logo (cached in browser for one day)\n-sub git_logo {\n-\tbinmode STDOUT, ':raw';\n-\tprint $cgi->header(-type => 'image/png', -expires => '+1d');\n-\t# cat git-logo.png | hexdump -e '16/1 \" %02x\"  \"\\n\"' | sed 's/ /\\\\x/g'\n-\tprint\t\"\\x89\\x50\\x4e\\x47\\x0d\\x0a\\x1a\\x0a\\x00\\x00\\x00\\x0d\\x49\\x48\\x44\\x52\" .\n-\t\t\"\\x00\\x00\\x00\\x48\\x00\\x00\\x00\\x1b\\x04\\x03\\x00\\x00\\x00\\x2d\\xd9\\xd4\" .\n-\t\t\"\\x2d\\x00\\x00\\x00\\x18\\x50\\x4c\\x54\\x45\\xff\\xff\\xff\\x60\\x60\\x5d\\xb0\" .\n-\t\t\"\\xaf\\xaa\\x00\\x80\\x00\\xce\\xcd\\xc7\\xc0\\x00\\x00\\xe8\\xe8\\xe6\\xf7\\xf7\" .\n-\t\t\"\\xf6\\x95\\x0c\\xa7\\x47\\x00\\x00\\x00\\x73\\x49\\x44\\x41\\x54\\x28\\xcf\\x63\" .\n-\t\t\"\\x48\\x67\\x20\\x04\\x4a\\x5c\\x18\\x0a\\x08\\x2a\\x62\\x53\\x61\\x20\\x02\\x08\" .\n-\t\t\"\\x0d\\x69\\x45\\xac\\xa1\\xa1\\x01\\x30\\x0c\\x93\\x60\\x36\\x26\\x52\\x91\\xb1\" .\n-\t\t\"\\x01\\x11\\xd6\\xe1\\x55\\x64\\x6c\\x6c\\xcc\\x6c\\x6c\\x0c\\xa2\\x0c\\x70\\x2a\" .\n-\t\t\"\\x62\\x06\\x2a\\xc1\\x62\\x1d\\xb3\\x01\\x02\\x53\\xa4\\x08\\xe8\\x00\\x03\\x18\" .\n-\t\t\"\\x26\\x56\\x11\\xd4\\xe1\\x20\\x97\\x1b\\xe0\\xb4\\x0e\\x35\\x24\\x71\\x29\\x82\" .\n-\t\t\"\\x99\\x30\\xb8\\x93\\x0a\\x11\\xb9\\x45\\x88\\xc1\\x8d\\xa0\\xa2\\x44\\x21\\x06\" .\n-\t\t\"\\x27\\x41\\x82\\x40\\x85\\xc1\\x45\\x89\\x20\\x70\\x01\\x00\\xa4\\x3d\\x21\\xc5\" .\n-\t\t\"\\x12\\x1c\\x9a\\xfe\\x00\\x00\\x00\\x00\\x49\\x45\\x4e\\x44\\xae\\x42\\x60\\x82\";\n-}\n-\n-sub get_file_owner {\n-\tmy $path = shift;\n-\n-\tmy ($dev, $ino, $mode, $nlink, $st_uid, $st_gid, $rdev, $size) = stat($path);\n-\tmy ($name, $passwd, $uid, $gid, $quota, $comment, $gcos, $dir, $shell) = getpwuid($st_uid);\n-\tif (!defined $gcos) {\n-\t\treturn undef;\n-\t}\n-\tmy $owner = $gcos;\n-\t$owner =~ s/[,;].*$//;\n-\treturn decode(\"utf8\", $owner, Encode::FB_DEFAULT);\n-}\n-\n-sub git_read_projects {\n-\tmy @list;\n-\n-\tif (-d $projects_list) {\n-\t\t# search in directory\n-\t\tmy $dir = $projects_list;\n-\t\topendir my ($dh), $dir or return undef;\n-\t\twhile (my $dir = readdir($dh)) {\n-\t\t\tif (-e \"$projectroot/$dir/HEAD\") {\n-\t\t\t\tmy $pr = {\n-\t\t\t\t\tpath => $dir,\n-\t\t\t\t};\n-\t\t\t\tpush @list, $pr\n-\t\t\t}\n-\t\t}\n-\t\tclosedir($dh);\n-\t} elsif (-f $projects_list) {\n-\t\t# read from file(url-encoded):\n-\t\t# 'git%2Fgit.git Linus+Torvalds'\n-\t\t# 'libs%2Fklibc%2Fklibc.git H.+Peter+Anvin'\n-\t\t# 'linux%2Fhotplug%2Fudev.git Greg+Kroah-Hartman'\n-\t\topen my ($fd), $projects_list or return undef;\n-\t\twhile (my $line = <$fd>) {\n-\t\t\tchomp $line;\n-\t\t\tmy ($path, $owner) = split ' ', $line;\n-\t\t\t$path = unescape($path);\n-\t\t\t$owner = unescape($owner);\n-\t\t\tif (!defined $path) {\n-\t\t\t\tnext;\n-\t\t\t}\n-\t\t\tif (-e \"$projectroot/$path/HEAD\") {\n-\t\t\t\tmy $pr = {\n-\t\t\t\t\tpath => $path,\n-\t\t\t\t\towner => decode(\"utf8\", $owner, Encode::FB_DEFAULT),\n-\t\t\t\t};\n-\t\t\t\tpush @list, $pr\n-\t\t\t}\n-\t\t}\n-\t\tclose $fd;\n-\t}\n-\t@list = sort {$a->{'path'} cmp $b->{'path'}} @list;\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-\tif (!@list) {\n-\t\tdie_error(undef, \"No project found.\");\n-\t}\n-\tforeach my $pr (@list) {\n-\t\tmy $head = git_read_head($pr->{'path'});\n-\t\tif (!defined $head) {\n-\t\t\tnext;\n-\t\t}\n-\t\t$ENV{'GIT_DIR'} = \"$projectroot/$pr->{'path'}\";\n-\t\tmy %co = git_read_commit($head);\n-\t\tif (!%co) {\n-\t\t\tnext;\n-\t\t}\n-\t\t$pr->{'commit'} = \\%co;\n-\t\tif (!defined $pr->{'descr'}) {\n-\t\t\tmy $descr = git_read_description($pr->{'path'}) || \"\";\n-\t\t\t$pr->{'descr'} = chop_str($descr, 25, 5);\n-\t\t}\n-\t\tif (!defined $pr->{'owner'}) {\n-\t\t\t$pr->{'owner'} = get_file_owner(\"$projectroot/$pr->{'path'}\") || \"\";\n-\t\t}\n-\t\tpush @projects, $pr;\n-\t}\n-\tgit_header_html();\n-\tif (-f $home_text) {\n-\t\tprint \"<div class=\\\"index_include\\\">\\n\";\n-\t\topen (my $fd, $home_text);\n-\t\tprint <$fd>;\n-\t\tclose $fd;\n-\t\tprint \"</div>\\n\";\n-\t}\n-\tprint \"<table class=\\\"project_list\\\">\\n\" .\n-\t      \"<tr>\\n\";\n-\tif (!defined($order) || (defined($order) && ($order eq \"project\"))) {\n-\t\t@projects = sort {$a->{'path'} cmp $b->{'path'}} @projects;\n-\t\tprint \"<th>Project</th>\\n\";\n-\t} else {\n-\t\tprint \"<th>\" . $cgi->a({-class => \"header\", -href => \"$my_uri?\" . esc_param(\"o=project\")}, \"Project\") . \"</th>\\n\";\n-\t}\n-\tif (defined($order) && ($order eq \"descr\")) {\n-\t\t@projects = sort {$a->{'descr'} cmp $b->{'descr'}} @projects;\n-\t\tprint \"<th>Description</th>\\n\";\n-\t} else {\n-\t\tprint \"<th>\" . $cgi->a({-class => \"header\", -href => \"$my_uri?\" . esc_param(\"o=descr\")}, \"Description\") . \"</th>\\n\";\n-\t}\n-\tif (defined($order) && ($order eq \"owner\")) {\n-\t\t@projects = sort {$a->{'owner'} cmp $b->{'owner'}} @projects;\n-\t\tprint \"<th>Owner</th>\\n\";\n-\t} else {\n-\t\tprint \"<th>\" . $cgi->a({-class => \"header\", -href => \"$my_uri?\" . esc_param(\"o=owner\")}, \"Owner\") . \"</th>\\n\";\n-\t}\n-\tif (defined($order) && ($order eq \"age\")) {\n-\t\t@projects = sort {$a->{'commit'}{'age'} <=> $b->{'commit'}{'age'}} @projects;\n-\t\tprint \"<th>Last Change</th>\\n\";\n-\t} else {\n-\t\tprint \"<th>\" . $cgi->a({-class => \"header\", -href => \"$my_uri?\" . esc_param(\"o=age\")}, \"Last Change\") . \"</th>\\n\";\n-\t}\n-\tprint \"<th></th>\\n\" .\n-\t      \"</tr>\\n\";\n-\tmy $alternate = 0;\n-\tforeach my $pr (@projects) {\n-\t\tif ($alternate) {\n-\t\t\tprint \"<tr class=\\\"dark\\\">\\n\";\n-\t\t} else {\n-\t\t\tprint \"<tr class=\\\"light\\\">\\n\";\n-\t\t}\n-\t\t$alternate ^= 1;\n-\t\tprint \"<td>\" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$pr->{'path'};a=summary\"), -class => \"list\"}, esc_html($pr->{'path'})) . \"</td>\\n\" .\n-\t\t      \"<td>\" . esc_html($pr->{'descr'}) . \"</td>\\n\" .\n-\t\t      \"<td><i>\" . chop_str($pr->{'owner'}, 15) . \"</i></td>\\n\";\n-\t\tprint \"<td class=\\\"\". age_class($pr->{'commit'}{'age'}) . \"\\\">\" . $pr->{'commit'}{'age_string'} . \"</td>\\n\" .\n-\t\t      \"<td class=\\\"link\\\">\" .\n-\t\t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$pr->{'path'};a=summary\")}, \"summary\") .\n-\t\t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$pr->{'path'};a=shortlog\")}, \"shortlog\") .\n-\t\t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$pr->{'path'};a=log\")}, \"log\") .\n-\t\t      \"</td>\\n\" .\n-\t\t      \"</tr>\\n\";\n-\t}\n-\tprint \"</table>\\n\";\n-\tgit_footer_html();\n-}\n-\n-sub read_info_ref {\n-\tmy $type = shift || \"\";\n-\tmy %refs;\n-\t# 5dc01c595e6c6ec9ccda4f6f69c131c0dd945f8c\trefs/tags/v2.6.11\n-\t# c39ae07f393806ccf406ef966e9a15afc43cc36a\trefs/tags/v2.6.11^{}\n-\topen my $fd, \"$projectroot/$project/info/refs\" or return;\n-\twhile (my $line = <$fd>) {\n-\t\tchomp $line;\n-\t\t# attention: for $type == \"\" it saves only last path part of ref name\n-\t\t# e.g. from 'refs/heads/jn/gitweb' it would leave only 'gitweb'\n-\t\tif ($line =~ m/^([0-9a-fA-F]{40})\\t.*$type\\/([^\\^]+)/) {\n-\t\t\tif (defined $refs{$1}) {\n-\t\t\t\t$refs{$1} .= \" / $2\";\n-\t\t\t} else {\n-\t\t\t\t$refs{$1} = $2;\n-\t\t\t}\n-\t\t}\n-\t}\n-\tclose $fd or return;\n-\treturn \\%refs;\n-}\n-\n-sub git_get_referencing {\n-\tmy ($refs, $id) = @_;\n-\n-\tif (defined $refs->{$id}) {\n-\t\treturn ' <span class=\"tag\">' . esc_html($refs->{$id}) . '</span>';\n-\t} else {\n-\t\treturn \"\";\n-\t}\n-}\n+## ......................................................................\n+## parse to array of hashes functions\n \n sub git_read_refs {\n \tmy $ref_dir = shift;\n@@ -1115,6 +850,299 @@ sub git_read_refs {\n \treturn \\@reflist;\n }\n \n+## ----------------------------------------------------------------------\n+## filesystem-related functions\n+\n+sub get_file_owner {\n+\tmy $path = shift;\n+\n+\tmy ($dev, $ino, $mode, $nlink, $st_uid, $st_gid, $rdev, $size) = stat($path);\n+\tmy ($name, $passwd, $uid, $gid, $quota, $comment, $gcos, $dir, $shell) = getpwuid($st_uid);\n+\tif (!defined $gcos) {\n+\t\treturn undef;\n+\t}\n+\tmy $owner = $gcos;\n+\t$owner =~ s/[,;].*$//;\n+\treturn decode(\"utf8\", $owner, Encode::FB_DEFAULT);\n+}\n+\n+## ......................................................................\n+## mimetype related functions\n+\n+sub mimetype_guess_file {\n+\tmy $filename = shift;\n+\tmy $mimemap = shift;\n+\t-r $mimemap or return undef;\n+\n+\tmy %mimemap;\n+\topen(MIME, $mimemap) or return undef;\n+\twhile (<MIME>) {\n+\t\tmy ($mime, $exts) = split(/\\t+/);\n+\t\tmy @exts = split(/\\s+/, $exts);\n+\t\tforeach my $ext (@exts) {\n+\t\t\t$mimemap{$ext} = $mime;\n+\t\t}\n+\t}\n+\tclose(MIME);\n+\n+\t$filename =~ /\\.(.*?)$/;\n+\treturn $mimemap{$1};\n+}\n+\n+sub mimetype_guess {\n+\tmy $filename = shift;\n+\tmy $mime;\n+\t$filename =~ /\\./ or return undef;\n+\n+\tif ($mimetypes_file) {\n+\t\tmy $file = $mimetypes_file;\n+\t\t#$file =~ m#^/# or $file = \"$projectroot/$path/$file\";\n+\t\t$mime = mimetype_guess_file($filename, $file);\n+\t}\n+\t$mime ||= mimetype_guess_file($filename, '/etc/mime.types');\n+\treturn $mime;\n+}\n+\n+sub git_blob_plain_mimetype {\n+\tmy $fd = shift;\n+\tmy $filename = shift;\n+\n+\tif ($filename) {\n+\t\tmy $mime = mimetype_guess($filename);\n+\t\t$mime and return $mime;\n+\t}\n+\n+\t# just in case\n+\treturn $default_blob_plain_mimetype unless $fd;\n+\n+\tif (-T $fd) {\n+\t\treturn 'text/plain' .\n+\t\t       ($default_text_plain_charset ? '; charset='.$default_text_plain_charset : '');\n+\t} elsif (! $filename) {\n+\t\treturn 'application/octet-stream';\n+\t} elsif ($filename =~ m/\\.png$/i) {\n+\t\treturn 'image/png';\n+\t} elsif ($filename =~ m/\\.gif$/i) {\n+\t\treturn 'image/gif';\n+\t} elsif ($filename =~ m/\\.jpe?g$/i) {\n+\t\treturn 'image/jpeg';\n+\t} else {\n+\t\treturn 'application/octet-stream';\n+\t}\n+}\n+\n+## ======================================================================\n+## functions printing HTML: header, footer, error page\n+\n+sub git_header_html {\n+\tmy $status = shift || \"200 OK\";\n+\tmy $expires = shift;\n+\n+\tmy $title = \"$site_name git\";\n+\tif (defined $project) {\n+\t\t$title .= \" - $project\";\n+\t\tif (defined $action) {\n+\t\t\t$title .= \"/$action\";\n+\t\t\tif (defined $file_name) {\n+\t\t\t\t$title .= \" - $file_name\";\n+\t\t\t\tif ($action eq \"tree\" && $file_name !~ m|/$|) {\n+\t\t\t\t\t$title .= \"/\";\n+\t\t\t\t}\n+\t\t\t}\n+\t\t}\n+\t}\n+\tmy $content_type;\n+\t# require explicit support from the UA if we are to send the page as\n+\t# 'application/xhtml+xml', otherwise send it as plain old 'text/html'.\n+\t# we have to do this because MSIE sometimes globs '*/*', pretending to\n+\t# support xhtml+xml but choking when it gets what it asked for.\n+\tif ($cgi->http('HTTP_ACCEPT') =~ m/(,|;|\\s|^)application\\/xhtml\\+xml(,|;|\\s|$)/ && $cgi->Accept('application/xhtml+xml') != 0) {\n+\t\t$content_type = 'application/xhtml+xml';\n+\t} else {\n+\t\t$content_type = 'text/html';\n+\t}\n+\tprint $cgi->header(-type=>$content_type, -charset => 'utf-8', -status=> $status, -expires => $expires);\n+\tprint <<EOF;\n+<?xml version=\"1.0\" encoding=\"utf-8\"?>\n+<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n+<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en-US\" lang=\"en-US\">\n+<!-- git web interface v$version, (C) 2005-2006, Kay Sievers <kay.sievers\\@vrfy.org>, Christian Gierke -->\n+<!-- git core binaries version $git_version -->\n+<head>\n+<meta http-equiv=\"content-type\" content=\"$content_type; charset=utf-8\"/>\n+<meta name=\"robots\" content=\"index, nofollow\"/>\n+<title>$title</title>\n+<link rel=\"stylesheet\" type=\"text/css\" href=\"$stylesheet\"/>\n+$rss_link\n+</head>\n+<body>\n+EOF\n+\tprint \"<div class=\\\"page_header\\\">\\n\" .\n+\t      \"<a href=\\\"http://www.kernel.org/pub/software/scm/git/docs/\\\" title=\\\"git documentation\\\">\" .\n+\t      \"<img src=\\\"$my_uri?\" . esc_param(\"a=git-logo.png\") . \"\\\" width=\\\"72\\\" height=\\\"27\\\" alt=\\\"git\\\" style=\\\"float:right; border-width:0px;\\\"/>\" .\n+\t      \"</a>\\n\";\n+\tprint $cgi->a({-href => esc_param($home_link)}, \"projects\") . \" / \";\n+\tif (defined $project) {\n+\t\tprint $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=summary\")}, esc_html($project));\n+\t\tif (defined $action) {\n+\t\t\tprint \" / $action\";\n+\t\t}\n+\t\tprint \"\\n\";\n+\t\tif (!defined $searchtext) {\n+\t\t\t$searchtext = \"\";\n+\t\t}\n+\t\tmy $search_hash;\n+\t\tif (defined $hash_base) {\n+\t\t\t$search_hash = $hash_base;\n+\t\t} elsif (defined $hash) {\n+\t\t\t$search_hash = $hash;\n+\t\t} else {\n+\t\t\t$search_hash = \"HEAD\";\n+\t\t}\n+\t\t$cgi->param(\"a\", \"search\");\n+\t\t$cgi->param(\"h\", $search_hash);\n+\t\tprint $cgi->startform(-method => \"get\", -action => $my_uri) .\n+\t\t      \"<div class=\\\"search\\\">\\n\" .\n+\t\t      $cgi->hidden(-name => \"p\") . \"\\n\" .\n+\t\t      $cgi->hidden(-name => \"a\") . \"\\n\" .\n+\t\t      $cgi->hidden(-name => \"h\") . \"\\n\" .\n+\t\t      $cgi->textfield(-name => \"s\", -value => $searchtext) . \"\\n\" .\n+\t\t      \"</div>\" .\n+\t\t      $cgi->end_form() . \"\\n\";\n+\t}\n+\tprint \"</div>\\n\";\n+}\n+\n+sub git_footer_html {\n+\tprint \"<div class=\\\"page_footer\\\">\\n\";\n+\tif (defined $project) {\n+\t\tmy $descr = git_read_description($project);\n+\t\tif (defined $descr) {\n+\t\t\tprint \"<div class=\\\"page_footer_text\\\">\" . esc_html($descr) . \"</div>\\n\";\n+\t\t}\n+\t\tprint $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=rss\"), -class => \"rss_logo\"}, \"RSS\") . \"\\n\";\n+\t} else {\n+\t\tprint $cgi->a({-href => \"$my_uri?\" . esc_param(\"a=opml\"), -class => \"rss_logo\"}, \"OPML\") . \"\\n\";\n+\t}\n+\tprint \"</div>\\n\" .\n+\t      \"</body>\\n\" .\n+\t      \"</html>\";\n+}\n+\n+sub die_error {\n+\tmy $status = shift || \"403 Forbidden\";\n+\tmy $error = shift || \"Malformed query, file missing or permission denied\";\n+\n+\tgit_header_html($status);\n+\tprint \"<div class=\\\"page_body\\\">\\n\" .\n+\t      \"<br/><br/>\\n\" .\n+\t      \"$status - $error\\n\" .\n+\t      \"<br/>\\n\" .\n+\t      \"</div>\\n\";\n+\tgit_footer_html();\n+\texit;\n+}\n+\n+## ----------------------------------------------------------------------\n+## functions printing or outputting HTML: navigation\n+\n+sub git_page_nav {\n+\tmy ($current, $suppress, $head, $treehead, $treebase, $extra) = @_;\n+\t$extra = '' if !defined $extra; # pager or formats\n+\n+\tmy @navs = qw(summary shortlog log commit commitdiff tree);\n+\tif ($suppress) {\n+\t\t@navs = grep { $_ ne $suppress } @navs;\n+\t}\n+\n+\tmy %arg = map { $_, ''} @navs;\n+\tif (defined $head) {\n+\t\tfor (qw(commit commitdiff)) {\n+\t\t\t$arg{$_} = \";h=$head\";\n+\t\t}\n+\t\tif ($current =~ m/^(tree | log | shortlog | commit | commitdiff | search)$/x) {\n+\t\t\tfor (qw(shortlog log)) {\n+\t\t\t\t$arg{$_} = \";h=$head\";\n+\t\t\t}\n+\t\t}\n+\t}\n+\t$arg{tree} .= \";h=$treehead\" if defined $treehead;\n+\t$arg{tree} .= \";hb=$treebase\" if defined $treebase;\n+\n+\tprint \"<div class=\\\"page_nav\\\">\\n\" .\n+\t\t(join \" | \",\n+\t\t map { $_ eq $current\n+\t\t\t\t\t ? $_\n+\t\t\t\t\t : $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=$_$arg{$_}\")}, \"$_\")\n+\t\t\t\t }\n+\t\t @navs);\n+\tprint \"<br/>\\n$extra<br/>\\n\" .\n+\t      \"</div>\\n\";\n+}\n+\n+sub git_get_paging_nav {\n+\tmy ($action, $hash, $head, $page, $nrevs) = @_;\n+\tmy $paging_nav;\n+\n+\n+\tif ($hash ne $head || $page) {\n+\t\t$paging_nav .= $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=$action\")}, \"HEAD\");\n+\t} else {\n+\t\t$paging_nav .= \"HEAD\";\n+\t}\n+\n+\tif ($page > 0) {\n+\t\t$paging_nav .= \" &sdot; \" .\n+\t\t\t$cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=$action;h=$hash;pg=\" . ($page-1)),\n+\t\t\t\t\t\t\t -accesskey => \"p\", -title => \"Alt-p\"}, \"prev\");\n+\t} else {\n+\t\t$paging_nav .= \" &sdot; prev\";\n+\t}\n+\n+\tif ($nrevs >= (100 * ($page+1)-1)) {\n+\t\t$paging_nav .= \" &sdot; \" .\n+\t\t\t$cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=$action;h=$hash;pg=\" . ($page+1)),\n+\t\t\t\t\t\t\t -accesskey => \"n\", -title => \"Alt-n\"}, \"next\");\n+\t} else {\n+\t\t$paging_nav .= \" &sdot; next\";\n+\t}\n+\n+\treturn $paging_nav;\n+}\n+\n+## ......................................................................\n+## functions printing or outputting HTML: div\n+\n+sub git_header_div {\n+\tmy ($action, $title, $hash, $hash_base) = @_;\n+\tmy $rest = '';\n+\n+\t$rest .= \";h=$hash\" if $hash;\n+\t$rest .= \";hb=$hash_base\" if $hash_base;\n+\n+\tprint \"<div class=\\\"header\\\">\\n\" .\n+\t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=$action$rest\"),\n+\t               -class => \"title\"}, $title ? $title : $action) . \"\\n\" .\n+\t      \"</div>\\n\";\n+}\n+\n+sub git_print_page_path {\n+\tmy $name = shift;\n+\tmy $type = shift;\n+\n+\tif (!defined $name) {\n+\t\tprint \"<div class=\\\"page_path\\\"><b>/</b></div>\\n\";\n+\t} elsif ($type =~ \"blob\") {\n+\t\tprint \"<div class=\\\"page_path\\\"><b>\" .\n+\t\t\t$cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=blob_plain;f=$file_name\")}, esc_html($name)) . \"</b><br/></div>\\n\";\n+\t} else {\n+\t\tprint \"<div class=\\\"page_path\\\"><b>\" . esc_html($name) . \"</b><br/></div>\\n\";\n+\t}\n+}\n+\n+## ......................................................................\n+## functions printing large fragments of HTML\n+\n sub git_shortlog_body {\n \t# uses global variable $project\n \tmy ($revlist, $from, $to, $refs, $extra) = @_;\n@@ -1265,6 +1293,191 @@ sub git_heads_body {\n \tprint \"</table>\\n\";\n }\n \n+## ----------------------------------------------------------------------\n+## functions printing large fragments, format as one of arguments\n+\n+sub git_diff_print {\n+\tmy $from = shift;\n+\tmy $from_name = shift;\n+\tmy $to = shift;\n+\tmy $to_name = shift;\n+\tmy $format = shift || \"html\";\n+\n+\tmy $from_tmp = \"/dev/null\";\n+\tmy $to_tmp = \"/dev/null\";\n+\tmy $pid = $$;\n+\n+\t# create tmp from-file\n+\tif (defined $from) {\n+\t\t$from_tmp = \"$git_temp/gitweb_\" . $$ . \"_from\";\n+\t\topen my $fd2, \"> $from_tmp\";\n+\t\topen my $fd, \"-|\", $GIT, \"cat-file\", \"blob\", $from;\n+\t\tmy @file = <$fd>;\n+\t\tprint $fd2 @file;\n+\t\tclose $fd2;\n+\t\tclose $fd;\n+\t}\n+\n+\t# create tmp to-file\n+\tif (defined $to) {\n+\t\t$to_tmp = \"$git_temp/gitweb_\" . $$ . \"_to\";\n+\t\topen my $fd2, \"> $to_tmp\";\n+\t\topen my $fd, \"-|\", $GIT, \"cat-file\", \"blob\", $to;\n+\t\tmy @file = <$fd>;\n+\t\tprint $fd2 @file;\n+\t\tclose $fd2;\n+\t\tclose $fd;\n+\t}\n+\n+\topen my $fd, \"-|\", \"/usr/bin/diff -u -p -L \\'$from_name\\' -L \\'$to_name\\' $from_tmp $to_tmp\";\n+\tif ($format eq \"plain\") {\n+\t\tundef $/;\n+\t\tprint <$fd>;\n+\t\t$/ = \"\\n\";\n+\t} else {\n+\t\twhile (my $line = <$fd>) {\n+\t\t\tchomp $line;\n+\t\t\tmy $char = substr($line, 0, 1);\n+\t\t\tmy $diff_class = \"\";\n+\t\t\tif ($char eq '+') {\n+\t\t\t\t$diff_class = \" add\";\n+\t\t\t} elsif ($char eq \"-\") {\n+\t\t\t\t$diff_class = \" rem\";\n+\t\t\t} elsif ($char eq \"@\") {\n+\t\t\t\t$diff_class = \" chunk_header\";\n+\t\t\t} elsif ($char eq \"\\\\\") {\n+\t\t\t\t# skip errors\n+\t\t\t\tnext;\n+\t\t\t}\n+\t\t\twhile ((my $pos = index($line, \"\\t\")) != -1) {\n+\t\t\t\tif (my $count = (8 - (($pos-1) % 8))) {\n+\t\t\t\t\tmy $spaces = ' ' x $count;\n+\t\t\t\t\t$line =~ s/\\t/$spaces/;\n+\t\t\t\t}\n+\t\t\t}\n+\t\t\tprint \"<div class=\\\"diff$diff_class\\\">\" . esc_html($line) . \"</div>\\n\";\n+\t\t}\n+\t}\n+\tclose $fd;\n+\n+\tif (defined $from) {\n+\t\tunlink($from_tmp);\n+\t}\n+\tif (defined $to) {\n+\t\tunlink($to_tmp);\n+\t}\n+}\n+\n+\n+## ======================================================================\n+## ======================================================================\n+## actions\n+\n+# git-logo (cached in browser for one day)\n+sub git_logo {\n+\tbinmode STDOUT, ':raw';\n+\tprint $cgi->header(-type => 'image/png', -expires => '+1d');\n+\t# cat git-logo.png | hexdump -e '16/1 \" %02x\"  \"\\n\"' | sed 's/ /\\\\x/g'\n+\tprint\t\"\\x89\\x50\\x4e\\x47\\x0d\\x0a\\x1a\\x0a\\x00\\x00\\x00\\x0d\\x49\\x48\\x44\\x52\" .\n+\t\t\"\\x00\\x00\\x00\\x48\\x00\\x00\\x00\\x1b\\x04\\x03\\x00\\x00\\x00\\x2d\\xd9\\xd4\" .\n+\t\t\"\\x2d\\x00\\x00\\x00\\x18\\x50\\x4c\\x54\\x45\\xff\\xff\\xff\\x60\\x60\\x5d\\xb0\" .\n+\t\t\"\\xaf\\xaa\\x00\\x80\\x00\\xce\\xcd\\xc7\\xc0\\x00\\x00\\xe8\\xe8\\xe6\\xf7\\xf7\" .\n+\t\t\"\\xf6\\x95\\x0c\\xa7\\x47\\x00\\x00\\x00\\x73\\x49\\x44\\x41\\x54\\x28\\xcf\\x63\" .\n+\t\t\"\\x48\\x67\\x20\\x04\\x4a\\x5c\\x18\\x0a\\x08\\x2a\\x62\\x53\\x61\\x20\\x02\\x08\" .\n+\t\t\"\\x0d\\x69\\x45\\xac\\xa1\\xa1\\x01\\x30\\x0c\\x93\\x60\\x36\\x26\\x52\\x91\\xb1\" .\n+\t\t\"\\x01\\x11\\xd6\\xe1\\x55\\x64\\x6c\\x6c\\xcc\\x6c\\x6c\\x0c\\xa2\\x0c\\x70\\x2a\" .\n+\t\t\"\\x62\\x06\\x2a\\xc1\\x62\\x1d\\xb3\\x01\\x02\\x53\\xa4\\x08\\xe8\\x00\\x03\\x18\" .\n+\t\t\"\\x26\\x56\\x11\\xd4\\xe1\\x20\\x97\\x1b\\xe0\\xb4\\x0e\\x35\\x24\\x71\\x29\\x82\" .\n+\t\t\"\\x99\\x30\\xb8\\x93\\x0a\\x11\\xb9\\x45\\x88\\xc1\\x8d\\xa0\\xa2\\x44\\x21\\x06\" .\n+\t\t\"\\x27\\x41\\x82\\x40\\x85\\xc1\\x45\\x89\\x20\\x70\\x01\\x00\\xa4\\x3d\\x21\\xc5\" .\n+\t\t\"\\x12\\x1c\\x9a\\xfe\\x00\\x00\\x00\\x00\\x49\\x45\\x4e\\x44\\xae\\x42\\x60\\x82\";\n+}\n+\n+sub git_project_list {\n+\tmy @list = git_read_projects();\n+\tmy @projects;\n+\tif (!@list) {\n+\t\tdie_error(undef, \"No project found.\");\n+\t}\n+\tforeach my $pr (@list) {\n+\t\tmy $head = git_read_head($pr->{'path'});\n+\t\tif (!defined $head) {\n+\t\t\tnext;\n+\t\t}\n+\t\t$ENV{'GIT_DIR'} = \"$projectroot/$pr->{'path'}\";\n+\t\tmy %co = git_read_commit($head);\n+\t\tif (!%co) {\n+\t\t\tnext;\n+\t\t}\n+\t\t$pr->{'commit'} = \\%co;\n+\t\tif (!defined $pr->{'descr'}) {\n+\t\t\tmy $descr = git_read_description($pr->{'path'}) || \"\";\n+\t\t\t$pr->{'descr'} = chop_str($descr, 25, 5);\n+\t\t}\n+\t\tif (!defined $pr->{'owner'}) {\n+\t\t\t$pr->{'owner'} = get_file_owner(\"$projectroot/$pr->{'path'}\") || \"\";\n+\t\t}\n+\t\tpush @projects, $pr;\n+\t}\n+\tgit_header_html();\n+\tif (-f $home_text) {\n+\t\tprint \"<div class=\\\"index_include\\\">\\n\";\n+\t\topen (my $fd, $home_text);\n+\t\tprint <$fd>;\n+\t\tclose $fd;\n+\t\tprint \"</div>\\n\";\n+\t}\n+\tprint \"<table class=\\\"project_list\\\">\\n\" .\n+\t      \"<tr>\\n\";\n+\tif (!defined($order) || (defined($order) && ($order eq \"project\"))) {\n+\t\t@projects = sort {$a->{'path'} cmp $b->{'path'}} @projects;\n+\t\tprint \"<th>Project</th>\\n\";\n+\t} else {\n+\t\tprint \"<th>\" . $cgi->a({-class => \"header\", -href => \"$my_uri?\" . esc_param(\"o=project\")}, \"Project\") . \"</th>\\n\";\n+\t}\n+\tif (defined($order) && ($order eq \"descr\")) {\n+\t\t@projects = sort {$a->{'descr'} cmp $b->{'descr'}} @projects;\n+\t\tprint \"<th>Description</th>\\n\";\n+\t} else {\n+\t\tprint \"<th>\" . $cgi->a({-class => \"header\", -href => \"$my_uri?\" . esc_param(\"o=descr\")}, \"Description\") . \"</th>\\n\";\n+\t}\n+\tif (defined($order) && ($order eq \"owner\")) {\n+\t\t@projects = sort {$a->{'owner'} cmp $b->{'owner'}} @projects;\n+\t\tprint \"<th>Owner</th>\\n\";\n+\t} else {\n+\t\tprint \"<th>\" . $cgi->a({-class => \"header\", -href => \"$my_uri?\" . esc_param(\"o=owner\")}, \"Owner\") . \"</th>\\n\";\n+\t}\n+\tif (defined($order) && ($order eq \"age\")) {\n+\t\t@projects = sort {$a->{'commit'}{'age'} <=> $b->{'commit'}{'age'}} @projects;\n+\t\tprint \"<th>Last Change</th>\\n\";\n+\t} else {\n+\t\tprint \"<th>\" . $cgi->a({-class => \"header\", -href => \"$my_uri?\" . esc_param(\"o=age\")}, \"Last Change\") . \"</th>\\n\";\n+\t}\n+\tprint \"<th></th>\\n\" .\n+\t      \"</tr>\\n\";\n+\tmy $alternate = 0;\n+\tforeach my $pr (@projects) {\n+\t\tif ($alternate) {\n+\t\t\tprint \"<tr class=\\\"dark\\\">\\n\";\n+\t\t} else {\n+\t\t\tprint \"<tr class=\\\"light\\\">\\n\";\n+\t\t}\n+\t\t$alternate ^= 1;\n+\t\tprint \"<td>\" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$pr->{'path'};a=summary\"), -class => \"list\"}, esc_html($pr->{'path'})) . \"</td>\\n\" .\n+\t\t      \"<td>\" . esc_html($pr->{'descr'}) . \"</td>\\n\" .\n+\t\t      \"<td><i>\" . chop_str($pr->{'owner'}, 15) . \"</i></td>\\n\";\n+\t\tprint \"<td class=\\\"\". age_class($pr->{'commit'}{'age'}) . \"\\\">\" . $pr->{'commit'}{'age_string'} . \"</td>\\n\" .\n+\t\t      \"<td class=\\\"link\\\">\" .\n+\t\t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$pr->{'path'};a=summary\")}, \"summary\") .\n+\t\t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$pr->{'path'};a=shortlog\")}, \"shortlog\") .\n+\t\t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$pr->{'path'};a=log\")}, \"log\") .\n+\t\t      \"</td>\\n\" .\n+\t\t      \"</tr>\\n\";\n+\t}\n+\tprint \"</table>\\n\";\n+\tgit_footer_html();\n+}\n+\n sub git_summary {\n \tmy $descr = git_read_description($project) || \"none\";\n \tmy $head = git_read_head($project);\n@@ -1326,20 +1539,6 @@ sub git_summary {\n \tgit_footer_html();\n }\n \n-sub git_print_page_path {\n-\tmy $name = shift;\n-\tmy $type = shift;\n-\n-\tif (!defined $name) {\n-\t\tprint \"<div class=\\\"page_path\\\"><b>/</b></div>\\n\";\n-\t} elsif ($type =~ \"blob\") {\n-\t\tprint \"<div class=\\\"page_path\\\"><b>\" .\n-\t\t\t$cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=blob_plain;f=$file_name\")}, esc_html($name)) . \"</b><br/></div>\\n\";\n-\t} else {\n-\t\tprint \"<div class=\\\"page_path\\\"><b>\" . esc_html($name) . \"</b><br/></div>\\n\";\n-\t}\n-}\n-\n sub git_tag {\n \tmy $head = git_read_head($project);\n \tgit_header_html();\n@@ -1546,84 +1745,6 @@ sub git_heads {\n \tgit_footer_html();\n }\n \n-sub git_get_hash_by_path {\n-\tmy $base = shift;\n-\tmy $path = shift || return undef;\n-\n-\tmy $tree = $base;\n-\n-\topen my $fd, \"-|\", $GIT, \"ls-tree\", $base, \"--\", $path\n-\t\tor die_error(undef, \"Open git-ls-tree failed.\");\n-\tmy $line = <$fd>;\n-\tclose $fd or return undef;\n-\n-\t#'100644 blob 0fa3f3a66fb6a137f6ec2c19351ed4d807070ffa\tpanic.c'\n-\t$line =~ m/^([0-9]+) (.+) ([0-9a-fA-F]{40})\\t(.+)$/;\n-\treturn $3;\n-}\n-\n-sub mimetype_guess_file {\n-\tmy $filename = shift;\n-\tmy $mimemap = shift;\n-\t-r $mimemap or return undef;\n-\n-\tmy %mimemap;\n-\topen(MIME, $mimemap) or return undef;\n-\twhile (<MIME>) {\n-\t\tmy ($mime, $exts) = split(/\\t+/);\n-\t\tmy @exts = split(/\\s+/, $exts);\n-\t\tforeach my $ext (@exts) {\n-\t\t\t$mimemap{$ext} = $mime;\n-\t\t}\n-\t}\n-\tclose(MIME);\n-\n-\t$filename =~ /\\.(.*?)$/;\n-\treturn $mimemap{$1};\n-}\n-\n-sub mimetype_guess {\n-\tmy $filename = shift;\n-\tmy $mime;\n-\t$filename =~ /\\./ or return undef;\n-\n-\tif ($mimetypes_file) {\n-\t\tmy $file = $mimetypes_file;\n-\t\t#$file =~ m#^/# or $file = \"$projectroot/$path/$file\";\n-\t\t$mime = mimetype_guess_file($filename, $file);\n-\t}\n-\t$mime ||= mimetype_guess_file($filename, '/etc/mime.types');\n-\treturn $mime;\n-}\n-\n-sub git_blob_plain_mimetype {\n-\tmy $fd = shift;\n-\tmy $filename = shift;\n-\n-\tif ($filename) {\n-\t\tmy $mime = mimetype_guess($filename);\n-\t\t$mime and return $mime;\n-\t}\n-\n-\t# just in case\n-\treturn $default_blob_plain_mimetype unless $fd;\n-\n-\tif (-T $fd) {\n-\t\treturn 'text/plain' .\n-\t\t       ($default_text_plain_charset ? '; charset='.$default_text_plain_charset : '');\n-\t} elsif (! $filename) {\n-\t\treturn 'application/octet-stream';\n-\t} elsif ($filename =~ m/\\.png$/i) {\n-\t\treturn 'image/png';\n-\t} elsif ($filename =~ m/\\.gif$/i) {\n-\t\treturn 'image/gif';\n-\t} elsif ($filename =~ m/\\.jpe?g$/i) {\n-\t\treturn 'image/jpeg';\n-\t} else {\n-\t\treturn 'application/octet-stream';\n-\t}\n-}\n-\n sub git_blob_plain {\n \tif (!defined $hash) {\n \t\tif (defined $file_name) {\n@@ -1793,98 +1914,6 @@ #\t\t\t      \" | \" . $cgi->a({-href => \"$my\n \tgit_footer_html();\n }\n \n-sub git_rss {\n-\t# http://www.notestips.com/80256B3A007F2692/1/NAMO5P9UPQ\n-\topen my $fd, \"-|\", $GIT, \"rev-list\", \"--max-count=150\", git_read_head($project) \n-\t\tor die_error(undef, \"Open git-rev-list failed.\");\n-\tmy @revlist = map { chomp; $_ } <$fd>;\n-\tclose $fd or die_error(undef, \"Reading rev-list failed.\");\n-\tprint $cgi->header(-type => 'text/xml', -charset => 'utf-8');\n-\tprint \"<?xml version=\\\"1.0\\\" encoding=\\\"utf-8\\\"?>\\n\".\n-\t      \"<rss version=\\\"2.0\\\" xmlns:content=\\\"http://purl.org/rss/1.0/modules/content/\\\">\\n\";\n-\tprint \"<channel>\\n\";\n-\tprint \"<title>$project</title>\\n\".\n-\t      \"<link>\" . esc_html(\"$my_url?p=$project;a=summary\") . \"</link>\\n\".\n-\t      \"<description>$project log</description>\\n\".\n-\t      \"<language>en</language>\\n\";\n-\n-\tfor (my $i = 0; $i <= $#revlist; $i++) {\n-\t\tmy $commit = $revlist[$i];\n-\t\tmy %co = git_read_commit($commit);\n-\t\t# we read 150, we always show 30 and the ones more recent than 48 hours\n-\t\tif (($i >= 20) && ((time - $co{'committer_epoch'}) > 48*60*60)) {\n-\t\t\tlast;\n-\t\t}\n-\t\tmy %cd = date_str($co{'committer_epoch'});\n-\t\topen $fd, \"-|\", $GIT, \"diff-tree\", '-r', $co{'parent'}, $co{'id'} or next;\n-\t\tmy @difftree = map { chomp; $_ } <$fd>;\n-\t\tclose $fd or next;\n-\t\tprint \"<item>\\n\" .\n-\t\t      \"<title>\" .\n-\t\t      sprintf(\"%d %s %02d:%02d\", $cd{'mday'}, $cd{'month'}, $cd{'hour'}, $cd{'minute'}) . \" - \" . esc_html($co{'title'}) .\n-\t\t      \"</title>\\n\" .\n-\t\t      \"<author>\" . esc_html($co{'author'}) . \"</author>\\n\" .\n-\t\t      \"<pubDate>$cd{'rfc2822'}</pubDate>\\n\" .\n-\t\t      \"<guid isPermaLink=\\\"true\\\">\" . esc_html(\"$my_url?p=$project;a=commit;h=$commit\") . \"</guid>\\n\" .\n-\t\t      \"<link>\" . esc_html(\"$my_url?p=$project;a=commit;h=$commit\") . \"</link>\\n\" .\n-\t\t      \"<description>\" . esc_html($co{'title'}) . \"</description>\\n\" .\n-\t\t      \"<content:encoded>\" .\n-\t\t      \"<![CDATA[\\n\";\n-\t\tmy $comment = $co{'comment'};\n-\t\tforeach my $line (@$comment) {\n-\t\t\t$line = decode(\"utf8\", $line, Encode::FB_DEFAULT);\n-\t\t\tprint \"$line<br/>\\n\";\n-\t\t}\n-\t\tprint \"<br/>\\n\";\n-\t\tforeach my $line (@difftree) {\n-\t\t\tif (!($line =~ m/^:([0-7]{6}) ([0-7]{6}) ([0-9a-fA-F]{40}) ([0-9a-fA-F]{40}) (.)([0-9]{0,3})\\t(.*)$/)) {\n-\t\t\t\tnext;\n-\t\t\t}\n-\t\t\tmy $file = validate_input(unquote($7));\n-\t\t\t$file = decode(\"utf8\", $file, Encode::FB_DEFAULT);\n-\t\t\tprint \"$file<br/>\\n\";\n-\t\t}\n-\t\tprint \"]]>\\n\" .\n-\t\t      \"</content:encoded>\\n\" .\n-\t\t      \"</item>\\n\";\n-\t}\n-\tprint \"</channel></rss>\";\n-}\n-\n-sub git_opml {\n-\tmy @list = git_read_projects();\n-\n-\tprint $cgi->header(-type => 'text/xml', -charset => 'utf-8');\n-\tprint \"<?xml version=\\\"1.0\\\" encoding=\\\"utf-8\\\"?>\\n\".\n-\t      \"<opml version=\\\"1.0\\\">\\n\".\n-\t      \"<head>\".\n-\t      \"  <title>$site_name Git OPML Export</title>\\n\".\n-\t      \"</head>\\n\".\n-\t      \"<body>\\n\".\n-\t      \"<outline text=\\\"git RSS feeds\\\">\\n\";\n-\n-\tforeach my $pr (@list) {\n-\t\tmy %proj = %$pr;\n-\t\tmy $head = git_read_head($proj{'path'});\n-\t\tif (!defined $head) {\n-\t\t\tnext;\n-\t\t}\n-\t\t$ENV{'GIT_DIR'} = \"$projectroot/$proj{'path'}\";\n-\t\tmy %co = git_read_commit($head);\n-\t\tif (!%co) {\n-\t\t\tnext;\n-\t\t}\n-\n-\t\tmy $path = esc_html(chop_str($proj{'path'}, 25, 5));\n-\t\tmy $rss  = \"$my_url?p=$proj{'path'};a=rss\";\n-\t\tmy $html = \"$my_url?p=$proj{'path'};a=summary\";\n-\t\tprint \"<outline type=\\\"rss\\\" text=\\\"$path\\\" title=\\\"$path\\\" xmlUrl=\\\"$rss\\\" htmlUrl=\\\"$html\\\"/>\\n\";\n-\t}\n-\tprint \"</outline>\\n\".\n-\t      \"</body>\\n\".\n-\t      \"</opml>\\n\";\n-}\n-\n sub git_log {\n \tmy $head = git_read_head($project);\n \tif (!defined $hash) {\n@@ -2556,3 +2585,98 @@ sub git_shortlog {\n \n \tgit_footer_html();\n }\n+\n+## ......................................................................\n+## feeds (RSS, OPML)\n+\n+sub git_rss {\n+\t# http://www.notestips.com/80256B3A007F2692/1/NAMO5P9UPQ\n+\topen my $fd, \"-|\", $GIT, \"rev-list\", \"--max-count=150\", git_read_head($project)\n+\t\tor die_error(undef, \"Open git-rev-list failed.\");\n+\tmy @revlist = map { chomp; $_ } <$fd>;\n+\tclose $fd or die_error(undef, \"Reading rev-list failed.\");\n+\tprint $cgi->header(-type => 'text/xml', -charset => 'utf-8');\n+\tprint \"<?xml version=\\\"1.0\\\" encoding=\\\"utf-8\\\"?>\\n\".\n+\t      \"<rss version=\\\"2.0\\\" xmlns:content=\\\"http://purl.org/rss/1.0/modules/content/\\\">\\n\";\n+\tprint \"<channel>\\n\";\n+\tprint \"<title>$project</title>\\n\".\n+\t      \"<link>\" . esc_html(\"$my_url?p=$project;a=summary\") . \"</link>\\n\".\n+\t      \"<description>$project log</description>\\n\".\n+\t      \"<language>en</language>\\n\";\n+\n+\tfor (my $i = 0; $i <= $#revlist; $i++) {\n+\t\tmy $commit = $revlist[$i];\n+\t\tmy %co = git_read_commit($commit);\n+\t\t# we read 150, we always show 30 and the ones more recent than 48 hours\n+\t\tif (($i >= 20) && ((time - $co{'committer_epoch'}) > 48*60*60)) {\n+\t\t\tlast;\n+\t\t}\n+\t\tmy %cd = date_str($co{'committer_epoch'});\n+\t\topen $fd, \"-|\", $GIT, \"diff-tree\", '-r', $co{'parent'}, $co{'id'} or next;\n+\t\tmy @difftree = map { chomp; $_ } <$fd>;\n+\t\tclose $fd or next;\n+\t\tprint \"<item>\\n\" .\n+\t\t      \"<title>\" .\n+\t\t      sprintf(\"%d %s %02d:%02d\", $cd{'mday'}, $cd{'month'}, $cd{'hour'}, $cd{'minute'}) . \" - \" . esc_html($co{'title'}) .\n+\t\t      \"</title>\\n\" .\n+\t\t      \"<author>\" . esc_html($co{'author'}) . \"</author>\\n\" .\n+\t\t      \"<pubDate>$cd{'rfc2822'}</pubDate>\\n\" .\n+\t\t      \"<guid isPermaLink=\\\"true\\\">\" . esc_html(\"$my_url?p=$project;a=commit;h=$commit\") . \"</guid>\\n\" .\n+\t\t      \"<link>\" . esc_html(\"$my_url?p=$project;a=commit;h=$commit\") . \"</link>\\n\" .\n+\t\t      \"<description>\" . esc_html($co{'title'}) . \"</description>\\n\" .\n+\t\t      \"<content:encoded>\" .\n+\t\t      \"<![CDATA[\\n\";\n+\t\tmy $comment = $co{'comment'};\n+\t\tforeach my $line (@$comment) {\n+\t\t\t$line = decode(\"utf8\", $line, Encode::FB_DEFAULT);\n+\t\t\tprint \"$line<br/>\\n\";\n+\t\t}\n+\t\tprint \"<br/>\\n\";\n+\t\tforeach my $line (@difftree) {\n+\t\t\tif (!($line =~ m/^:([0-7]{6}) ([0-7]{6}) ([0-9a-fA-F]{40}) ([0-9a-fA-F]{40}) (.)([0-9]{0,3})\\t(.*)$/)) {\n+\t\t\t\tnext;\n+\t\t\t}\n+\t\t\tmy $file = validate_input(unquote($7));\n+\t\t\t$file = decode(\"utf8\", $file, Encode::FB_DEFAULT);\n+\t\t\tprint \"$file<br/>\\n\";\n+\t\t}\n+\t\tprint \"]]>\\n\" .\n+\t\t      \"</content:encoded>\\n\" .\n+\t\t      \"</item>\\n\";\n+\t}\n+\tprint \"</channel></rss>\";\n+}\n+\n+sub git_opml {\n+\tmy @list = git_read_projects();\n+\n+\tprint $cgi->header(-type => 'text/xml', -charset => 'utf-8');\n+\tprint \"<?xml version=\\\"1.0\\\" encoding=\\\"utf-8\\\"?>\\n\".\n+\t      \"<opml version=\\\"1.0\\\">\\n\".\n+\t      \"<head>\".\n+\t      \"  <title>$site_name Git OPML Export</title>\\n\".\n+\t      \"</head>\\n\".\n+\t      \"<body>\\n\".\n+\t      \"<outline text=\\\"git RSS feeds\\\">\\n\";\n+\n+\tforeach my $pr (@list) {\n+\t\tmy %proj = %$pr;\n+\t\tmy $head = git_read_head($proj{'path'});\n+\t\tif (!defined $head) {\n+\t\t\tnext;\n+\t\t}\n+\t\t$ENV{'GIT_DIR'} = \"$projectroot/$proj{'path'}\";\n+\t\tmy %co = git_read_commit($head);\n+\t\tif (!%co) {\n+\t\t\tnext;\n+\t\t}\n+\n+\t\tmy $path = esc_html(chop_str($proj{'path'}, 25, 5));\n+\t\tmy $rss  = \"$my_url?p=$proj{'path'};a=rss\";\n+\t\tmy $html = \"$my_url?p=$proj{'path'};a=summary\";\n+\t\tprint \"<outline type=\\\"rss\\\" text=\\\"$path\\\" title=\\\"$path\\\" xmlUrl=\\\"$rss\\\" htmlUrl=\\\"$html\\\"/>\\n\";\n+\t}\n+\tprint \"</outline>\\n\".\n+\t      \"</body>\\n\".\n+\t      \"</opml>\\n\";\n+}\n-- \n1.4.1.1\n"},{"id":"24451","messageId":"7v3bch7gf8.fsf@assigned-by-dhcp.cox.net","threadId":"5038","inReplyTo":"200607311833.39524.jnareb@gmail.com","subject":"Re: [PATCH 19] gitweb: No need to quote path for list version of open \"-|\"","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-07-31T18:55:23Z","receivedAt":"2006-07-31T18:55:23Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"I suspect the patch title is wrong -- it is not \"no need to\" but\n\"quoting path breaks so do not do it\" ;-).\n\nI guess this fixes the problem I saw last night?\n"},{"id":"24452","messageId":"200607312058.00706.jnareb@gmail.com","threadId":"5038","inReplyTo":"200607302236.06686.jnareb@gmail.com","subject":"Re: [PATCH 16b] gitweb: Remove characters entities entirely when shortening string -- correction","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-07-31T18:58:00Z","receivedAt":"2006-07-31T18:58:00Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Signed-off-by: Jakub Narebski <jnareb@gmail.com>\n---\nApply it on top of [PATCH 16] to correct it;\nthis patch was generated after [PATCH 19].\n\n gitweb/gitweb.cgi |    2 +-\n 1 files changed, 1 insertions(+), 1 deletions(-)\n\ndiff --git a/gitweb/gitweb.cgi b/gitweb/gitweb.cgi\nindex f7fe28a..cb6af39 100755\n--- a/gitweb/gitweb.cgi\n+++ b/gitweb/gitweb.cgi\n@@ -776,7 +776,7 @@ sub chop_str {\n \tmy $tail = $2;\n \tif (length($tail) > 4) {\n \t\t$tail = \" ...\";\n-\t\t$body =~ s/&[^;]$//; # remove chopped character entities\n+\t\t$body =~ s/&[^;]*$//; # remove chopped character entities\n \t}\n \treturn \"$body$tail\";\n }\n-- \n1.4.1.1\n"},{"id":"24453","messageId":"ealk0e$to2$2@sea.gmane.org","threadId":"5038","inReplyTo":"7v3bch7gf8.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH 19] gitweb: No need to quote path for list version of open \"-|\"","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-07-31T19:00:47Z","receivedAt":"2006-07-31T19:00:47Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"<opublikowany i wysłany>\n\nJunio C Hamano wrote:\n\n> I suspect the patch title is wrong -- it is not \"no need to\" but\n> \"quoting path breaks so do not do it\" ;-).\n> \n> I guess this fixes the problem I saw last night?\n\nIf I remember correctly it worked without this patch, for git 1.4.1.1 \n(i.e. with --full-history option, although not working as advertised: see my\ncomment earlier in thread).\n\nHow to do sane fallback to version without \"--full-history\", if git binaries\nused do not support \"--full-history\"?\n\n-- \nJakub Narebski\nWarsaw, Poland\nShadeHawk on #git\n"},{"id":"24455","messageId":"200607312122.16767.jnareb@gmail.com","threadId":"5038","inReplyTo":"200607312048.44075.jnareb@gmail.com","subject":"[PATCH 20 (amend)] gitweb: Reordering code and dividing it into categories","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-07-31T19:22:15Z","receivedAt":"2006-07-31T19:22:15Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Reorder gitweb code around, divide it into sections (categories) and\nadd some comments.\n\nSigned-off-by: Jakub Narebski <jnareb@gmail.com>\n---\n gitweb/gitweb.cgi | 1616 ++++++++++++++++++++++++++++-------------------------\n 1 files changed, 840 insertions(+), 776 deletions(-)\n\ndiff --git a/gitweb/gitweb.cgi b/gitweb/gitweb.cgi\nindex cb6af39..c1ee79e 100755\n--- a/gitweb/gitweb.cgi\n+++ b/gitweb/gitweb.cgi\n@@ -160,21 +160,7 @@ if (defined $searchtext) {\n \t$searchtext = quotemeta $searchtext;\n }\n \n-sub validate_input {\n-\tmy $input = shift;\n-\n-\tif ($input =~ m/^[0-9a-fA-F]{40}$/) {\n-\t\treturn $input;\n-\t}\n-\tif ($input =~ m/(^|\\/)(|\\.|\\.\\.)($|\\/)/) {\n-\t\treturn undef;\n-\t}\n-\tif ($input =~ m/[^a-zA-Z0-9_\\x80-\\xff\\ \\t\\.\\/\\-\\+\\#\\~\\%]/) {\n-\t\treturn undef;\n-\t}\n-\treturn $input;\n-}\n-\n+# dispatch\n if (!defined $action || $action eq \"summary\") {\n \tgit_summary();\n \texit;\n@@ -235,6 +221,24 @@ if (!defined $action || $action eq \"summ\n \texit;\n }\n \n+## ======================================================================\n+## validation, quoting/unquoting and escaping\n+\n+sub validate_input {\n+\tmy $input = shift;\n+\n+\tif ($input =~ m/^[0-9a-fA-F]{40}$/) {\n+\t\treturn $input;\n+\t}\n+\tif ($input =~ m/(^|\\/)(|\\.|\\.\\.)($|\\/)/) {\n+\t\treturn undef;\n+\t}\n+\tif ($input =~ m/[^a-zA-Z0-9_\\x80-\\xff\\ \\t\\.\\/\\-\\+\\#\\~\\%]/) {\n+\t\treturn undef;\n+\t}\n+\treturn $input;\n+}\n+\n # quote unsafe chars, but keep the slash, even when it's not\n # correct, but quoted slashes look too horrible in bookmarks\n sub esc_param {\n@@ -264,6 +268,29 @@ sub unquote {\n \treturn $str;\n }\n \n+## ----------------------------------------------------------------------\n+## HTML aware string manipulation\n+\n+sub chop_str {\n+\tmy $str = shift;\n+\tmy $len = shift;\n+\tmy $add_len = shift || 10;\n+\n+\t# allow only $len chars, but don't cut a word if it would fit in $add_len\n+\t# if it doesn't fit, cut it if it's still longer than the dots we would add\n+\t$str =~ m/^(.{0,$len}[^ \\/\\-_:\\.@]{0,$add_len})(.*)/;\n+\tmy $body = $1;\n+\tmy $tail = $2;\n+\tif (length($tail) > 4) {\n+\t\t$tail = \" ...\";\n+\t\t$body =~ s/&[^;]*$//; # remove chopped character entities\n+\t}\n+\treturn \"$body$tail\";\n+}\n+\n+## ----------------------------------------------------------------------\n+## functions returning short strings\n+\n # CSS class for given age value (in seconds)\n sub age_class {\n \tmy $age = shift;\n@@ -277,202 +304,108 @@ sub age_class {\n \t}\n }\n \n-sub git_header_html {\n-\tmy $status = shift || \"200 OK\";\n-\tmy $expires = shift;\n+# convert age in seconds to \"nn units ago\" string\n+sub age_string {\n+\tmy $age = shift;\n+\tmy $age_str;\n \n-\tmy $title = \"$site_name git\";\n-\tif (defined $project) {\n-\t\t$title .= \" - $project\";\n-\t\tif (defined $action) {\n-\t\t\t$title .= \"/$action\";\n-\t\t\tif (defined $file_name) {\n-\t\t\t\t$title .= \" - $file_name\";\n-\t\t\t\tif ($action eq \"tree\" && $file_name !~ m|/$|) {\n-\t\t\t\t\t$title .= \"/\";\n-\t\t\t\t}\n-\t\t\t}\n-\t\t}\n-\t}\n-\tmy $content_type;\n-\t# require explicit support from the UA if we are to send the page as\n-\t# 'application/xhtml+xml', otherwise send it as plain old 'text/html'.\n-\t# we have to do this because MSIE sometimes globs '*/*', pretending to\n-\t# support xhtml+xml but choking when it gets what it asked for.\n-\tif ($cgi->http('HTTP_ACCEPT') =~ m/(,|;|\\s|^)application\\/xhtml\\+xml(,|;|\\s|$)/ && $cgi->Accept('application/xhtml+xml') != 0) {\n-\t\t$content_type = 'application/xhtml+xml';\n+\tif ($age > 60*60*24*365*2) {\n+\t\t$age_str = (int $age/60/60/24/365);\n+\t\t$age_str .= \" years ago\";\n+\t} elsif ($age > 60*60*24*(365/12)*2) {\n+\t\t$age_str = int $age/60/60/24/(365/12);\n+\t\t$age_str .= \" months ago\";\n+\t} elsif ($age > 60*60*24*7*2) {\n+\t\t$age_str = int $age/60/60/24/7;\n+\t\t$age_str .= \" weeks ago\";\n+\t} elsif ($age > 60*60*24*2) {\n+\t\t$age_str = int $age/60/60/24;\n+\t\t$age_str .= \" days ago\";\n+\t} elsif ($age > 60*60*2) {\n+\t\t$age_str = int $age/60/60;\n+\t\t$age_str .= \" hours ago\";\n+\t} elsif ($age > 60*2) {\n+\t\t$age_str = int $age/60;\n+\t\t$age_str .= \" min ago\";\n+\t} elsif ($age > 2) {\n+\t\t$age_str = int $age;\n+\t\t$age_str .= \" sec ago\";\n \t} else {\n-\t\t$content_type = 'text/html';\n-\t}\n-\tprint $cgi->header(-type=>$content_type, -charset => 'utf-8', -status=> $status, -expires => $expires);\n-\tprint <<EOF;\n-<?xml version=\"1.0\" encoding=\"utf-8\"?>\n-<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n-<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en-US\" lang=\"en-US\">\n-<!-- git web interface v$version, (C) 2005-2006, Kay Sievers <kay.sievers\\@vrfy.org>, Christian Gierke -->\n-<!-- git core binaries version $git_version -->\n-<head>\n-<meta http-equiv=\"content-type\" content=\"$content_type; charset=utf-8\"/>\n-<meta name=\"robots\" content=\"index, nofollow\"/>\n-<title>$title</title>\n-<link rel=\"stylesheet\" type=\"text/css\" href=\"$stylesheet\"/>\n-$rss_link\n-</head>\n-<body>\n-EOF\n-\tprint \"<div class=\\\"page_header\\\">\\n\" .\n-\t      \"<a href=\\\"http://www.kernel.org/pub/software/scm/git/docs/\\\" title=\\\"git documentation\\\">\" .\n-\t      \"<img src=\\\"$my_uri?\" . esc_param(\"a=git-logo.png\") . \"\\\" width=\\\"72\\\" height=\\\"27\\\" alt=\\\"git\\\" style=\\\"float:right; border-width:0px;\\\"/>\" .\n-\t      \"</a>\\n\";\n-\tprint $cgi->a({-href => esc_param($home_link)}, \"projects\") . \" / \";\n-\tif (defined $project) {\n-\t\tprint $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=summary\")}, esc_html($project));\n-\t\tif (defined $action) {\n-\t\t\tprint \" / $action\";\n-\t\t}\n-\t\tprint \"\\n\";\n-\t\tif (!defined $searchtext) {\n-\t\t\t$searchtext = \"\";\n-\t\t}\n-\t\tmy $search_hash;\n-\t\tif (defined $hash_base) {\n-\t\t\t$search_hash = $hash_base;\n-\t\t} elsif (defined $hash) {\n-\t\t\t$search_hash = $hash;\n-\t\t} else {\n-\t\t\t$search_hash = \"HEAD\";\n-\t\t}\n-\t\t$cgi->param(\"a\", \"search\");\n-\t\t$cgi->param(\"h\", $search_hash);\n-\t\tprint $cgi->startform(-method => \"get\", -action => $my_uri) .\n-\t\t      \"<div class=\\\"search\\\">\\n\" .\n-\t\t      $cgi->hidden(-name => \"p\") . \"\\n\" .\n-\t\t      $cgi->hidden(-name => \"a\") . \"\\n\" .\n-\t\t      $cgi->hidden(-name => \"h\") . \"\\n\" .\n-\t\t      $cgi->textfield(-name => \"s\", -value => $searchtext) . \"\\n\" .\n-\t\t      \"</div>\" .\n-\t\t      $cgi->end_form() . \"\\n\";\n+\t\t$age_str .= \" right now\";\n \t}\n-\tprint \"</div>\\n\";\n+\treturn $age_str;\n }\n \n-sub git_footer_html {\n-\tprint \"<div class=\\\"page_footer\\\">\\n\";\n-\tif (defined $project) {\n-\t\tmy $descr = git_read_description($project);\n-\t\tif (defined $descr) {\n-\t\t\tprint \"<div class=\\\"page_footer_text\\\">\" . esc_html($descr) . \"</div>\\n\";\n-\t\t}\n-\t\tprint $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=rss\"), -class => \"rss_logo\"}, \"RSS\") . \"\\n\";\n+# convert file mode in octal to symbolic file mode string\n+sub mode_str {\n+\tmy $mode = oct shift;\n+\n+\tif (S_ISDIR($mode & S_IFMT)) {\n+\t\treturn 'drwxr-xr-x';\n+\t} elsif (S_ISLNK($mode)) {\n+\t\treturn 'lrwxrwxrwx';\n+\t} elsif (S_ISREG($mode)) {\n+\t\t# git cares only about the executable bit\n+\t\tif ($mode & S_IXUSR) {\n+\t\t\treturn '-rwxr-xr-x';\n+\t\t} else {\n+\t\t\treturn '-rw-r--r--';\n+\t\t};\n \t} else {\n-\t\tprint $cgi->a({-href => \"$my_uri?\" . esc_param(\"a=opml\"), -class => \"rss_logo\"}, \"OPML\") . \"\\n\";\n+\t\treturn '----------';\n \t}\n-\tprint \"</div>\\n\" .\n-\t      \"</body>\\n\" .\n-\t      \"</html>\";\n }\n \n-sub die_error {\n-\tmy $status = shift || \"403 Forbidden\";\n-\tmy $error = shift || \"Malformed query, file missing or permission denied\";\n+# convert file mode in octal to file type string\n+sub file_type {\n+\tmy $mode = oct shift;\n \n-\tgit_header_html($status);\n-\tprint \"<div class=\\\"page_body\\\">\\n\" .\n-\t      \"<br/><br/>\\n\" .\n-\t      \"$status - $error\\n\" .\n-\t      \"<br/>\\n\" .\n-\t      \"</div>\\n\";\n-\tgit_footer_html();\n-\texit;\n+\tif (S_ISDIR($mode & S_IFMT)) {\n+\t\treturn \"directory\";\n+\t} elsif (S_ISLNK($mode)) {\n+\t\treturn \"symlink\";\n+\t} elsif (S_ISREG($mode)) {\n+\t\treturn \"file\";\n+\t} else {\n+\t\treturn \"unknown\";\n+\t}\n }\n \n-sub git_page_nav {\n-\tmy ($current, $suppress, $head, $treehead, $treebase, $extra) = @_;\n-\t$extra = '' if !defined $extra; # pager or formats\n+## ----------------------------------------------------------------------\n+## functions returning short HTML fragments, or transforming HTML fragments\n+## which don't beling to other sections\n \n-\tmy @navs = qw(summary shortlog log commit commitdiff tree);\n-\tif ($suppress) {\n-\t\t@navs = grep { $_ ne $suppress } @navs;\n-\t}\n+# format line of commit message or tag comment\n+sub format_log_line_html {\n+\tmy $line = shift;\n \n-\tmy %arg = map { $_, ''} @navs;\n-\tif (defined $head) {\n-\t\tfor (qw(commit commitdiff)) {\n-\t\t\t$arg{$_} = \";h=$head\";\n-\t\t}\n-\t\tif ($current =~ m/^(tree | log | shortlog | commit | commitdiff | search)$/x) {\n-\t\t\tfor (qw(shortlog log)) {\n-\t\t\t\t$arg{$_} = \";h=$head\";\n-\t\t\t}\n+\t$line = esc_html($line);\n+\t$line =~ s/ /&nbsp;/g;\n+\tif ($line =~ m/([0-9a-fA-F]{40})/) {\n+\t\tmy $hash_text = $1;\n+\t\tif (git_get_type($hash_text) eq \"commit\") {\n+\t\t\tmy $link = $cgi->a({-class => \"text\", -href => \"$my_uri?\" . esc_param(\"p=$project;a=commit;h=$hash_text\")}, $hash_text);\n+\t\t\t$line =~ s/$hash_text/$link/;\n \t\t}\n \t}\n-\t$arg{tree} .= \";h=$treehead\" if defined $treehead;\n-\t$arg{tree} .= \";hb=$treebase\" if defined $treebase;\n-\n-\tprint \"<div class=\\\"page_nav\\\">\\n\" .\n-\t\t(join \" | \",\n-\t\t map { $_ eq $current\n-\t\t\t\t\t ? $_\n-\t\t\t\t\t : $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=$_$arg{$_}\")}, \"$_\")\n-\t\t\t\t }\n-\t\t @navs);\n-\tprint \"<br/>\\n$extra<br/>\\n\" .\n-\t      \"</div>\\n\";\n-}\n-\n-sub git_header_div {\n-\tmy ($action, $title, $hash, $hash_base) = @_;\n-\tmy $rest = '';\n-\n-\t$rest .= \";h=$hash\" if $hash;\n-\t$rest .= \";hb=$hash_base\" if $hash_base;\n-\n-\tprint \"<div class=\\\"header\\\">\\n\" .\n-\t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=$action$rest\"),\n-\t               -class => \"title\"}, $title ? $title : $action) . \"\\n\" .\n-\t      \"</div>\\n\";\n+\treturn $line;\n }\n \n-sub git_get_paging_nav {\n-\tmy ($action, $hash, $head, $page, $nrevs) = @_;\n-\tmy $paging_nav;\n-\n-\n-\tif ($hash ne $head || $page) {\n-\t\t$paging_nav .= $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=$action\")}, \"HEAD\");\n-\t} else {\n-\t\t$paging_nav .= \"HEAD\";\n-\t}\n-\n-\tif ($page > 0) {\n-\t\t$paging_nav .= \" &sdot; \" .\n-\t\t\t$cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=$action;h=$hash;pg=\" . ($page-1)),\n-\t\t\t\t\t\t\t -accesskey => \"p\", -title => \"Alt-p\"}, \"prev\");\n-\t} else {\n-\t\t$paging_nav .= \" &sdot; prev\";\n-\t}\n+# format marker of refs pointing to given object\n+sub git_get_referencing {\n+\tmy ($refs, $id) = @_;\n \n-\tif ($nrevs >= (100 * ($page+1)-1)) {\n-\t\t$paging_nav .= \" &sdot; \" .\n-\t\t\t$cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=$action;h=$hash;pg=\" . ($page+1)),\n-\t\t\t\t\t\t\t -accesskey => \"n\", -title => \"Alt-n\"}, \"next\");\n+\tif (defined $refs->{$id}) {\n+\t\treturn ' <span class=\"tag\">' . esc_html($refs->{$id}) . '</span>';\n \t} else {\n-\t\t$paging_nav .= \" &sdot; next\";\n+\t\treturn \"\";\n \t}\n-\n-\treturn $paging_nav;\n }\n \n-sub git_get_type {\n-\tmy $hash = shift;\n-\n-\topen my $fd, \"-|\", $GIT, \"cat-file\", '-t', $hash or return;\n-\tmy $type = <$fd>;\n-\tclose $fd or return;\n-\tchomp $type;\n-\treturn $type;\n-}\n+## ----------------------------------------------------------------------\n+## git utility subroutines, invoking git commands\n \n+# get HEAD ref of given project as hash\n sub git_read_head {\n \tmy $project = shift;\n \tmy $oENV = $ENV{'GIT_DIR'};\n@@ -491,6 +424,57 @@ sub git_read_head {\n \treturn $retval;\n }\n \n+# get type of given object\n+sub git_get_type {\n+\tmy $hash = shift;\n+\n+\topen my $fd, \"-|\", $GIT, \"cat-file\", '-t', $hash or return;\n+\tmy $type = <$fd>;\n+\tclose $fd or return;\n+\tchomp $type;\n+\treturn $type;\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+# get hash of given path at given ref\n+sub git_get_hash_by_path {\n+\tmy $base = shift;\n+\tmy $path = shift || return undef;\n+\n+\tmy $tree = $base;\n+\n+\topen my $fd, \"-|\", $GIT, \"ls-tree\", $base, \"--\", $path\n+\t\tor die_error(undef, \"Open git-ls-tree failed.\");\n+\tmy $line = <$fd>;\n+\tclose $fd or return undef;\n+\n+\t#'100644 blob 0fa3f3a66fb6a137f6ec2c19351ed4d807070ffa\tpanic.c'\n+\t$line =~ m/^([0-9]+) (.+) ([0-9a-fA-F]{40})\\t(.+)$/;\n+\treturn $3;\n+}\n+\n+## ......................................................................\n+## git utility functions, directly accessing git repository\n+\n+# assumes that PATH is not symref\n sub git_read_hash {\n \tmy $path = shift;\n \n@@ -513,6 +497,100 @@ sub git_read_description {\n \treturn $descr;\n }\n \n+sub git_read_projects {\n+\tmy @list;\n+\n+\tif (-d $projects_list) {\n+\t\t# search in directory\n+\t\tmy $dir = $projects_list;\n+\t\topendir my ($dh), $dir or return undef;\n+\t\twhile (my $dir = readdir($dh)) {\n+\t\t\tif (-e \"$projectroot/$dir/HEAD\") {\n+\t\t\t\tmy $pr = {\n+\t\t\t\t\tpath => $dir,\n+\t\t\t\t};\n+\t\t\t\tpush @list, $pr\n+\t\t\t}\n+\t\t}\n+\t\tclosedir($dh);\n+\t} elsif (-f $projects_list) {\n+\t\t# read from file(url-encoded):\n+\t\t# 'git%2Fgit.git Linus+Torvalds'\n+\t\t# 'libs%2Fklibc%2Fklibc.git H.+Peter+Anvin'\n+\t\t# 'linux%2Fhotplug%2Fudev.git Greg+Kroah-Hartman'\n+\t\topen my ($fd), $projects_list or return undef;\n+\t\twhile (my $line = <$fd>) {\n+\t\t\tchomp $line;\n+\t\t\tmy ($path, $owner) = split ' ', $line;\n+\t\t\t$path = unescape($path);\n+\t\t\t$owner = unescape($owner);\n+\t\t\tif (!defined $path) {\n+\t\t\t\tnext;\n+\t\t\t}\n+\t\t\tif (-e \"$projectroot/$path/HEAD\") {\n+\t\t\t\tmy $pr = {\n+\t\t\t\t\tpath => $path,\n+\t\t\t\t\towner => decode(\"utf8\", $owner, Encode::FB_DEFAULT),\n+\t\t\t\t};\n+\t\t\t\tpush @list, $pr\n+\t\t\t}\n+\t\t}\n+\t\tclose $fd;\n+\t}\n+\t@list = sort {$a->{'path'} cmp $b->{'path'}} @list;\n+\treturn @list;\n+}\n+\n+sub read_info_ref {\n+\tmy $type = shift || \"\";\n+\tmy %refs;\n+\t# 5dc01c595e6c6ec9ccda4f6f69c131c0dd945f8c\trefs/tags/v2.6.11\n+\t# c39ae07f393806ccf406ef966e9a15afc43cc36a\trefs/tags/v2.6.11^{}\n+\topen my $fd, \"$projectroot/$project/info/refs\" or return;\n+\twhile (my $line = <$fd>) {\n+\t\tchomp $line;\n+\t\t# attention: for $type == \"\" it saves only last path part of ref name\n+\t\t# e.g. from 'refs/heads/jn/gitweb' it would leave only 'gitweb'\n+\t\tif ($line =~ m/^([0-9a-fA-F]{40})\\t.*$type\\/([^\\^]+)/) {\n+\t\t\tif (defined $refs{$1}) {\n+\t\t\t\t$refs{$1} .= \" / $2\";\n+\t\t\t} else {\n+\t\t\t\t$refs{$1} = $2;\n+\t\t\t}\n+\t\t}\n+\t}\n+\tclose $fd or return;\n+\treturn \\%refs;\n+}\n+\n+## ----------------------------------------------------------------------\n+## parse to hash functions\n+\n+sub date_str {\n+\tmy $epoch = shift;\n+\tmy $tz = shift || \"-0000\";\n+\n+\tmy %date;\n+\tmy @months = (\"Jan\", \"Feb\", \"Mar\", \"Apr\", \"May\", \"Jun\", \"Jul\", \"Aug\", \"Sep\", \"Oct\", \"Nov\", \"Dec\");\n+\tmy @days = (\"Sun\", \"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\", \"Sat\");\n+\tmy ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday) = gmtime($epoch);\n+\t$date{'hour'} = $hour;\n+\t$date{'minute'} = $min;\n+\t$date{'mday'} = $mday;\n+\t$date{'day'} = $days[$wday];\n+\t$date{'month'} = $months[$mon];\n+\t$date{'rfc2822'} = sprintf \"%s, %d %s %4d %02d:%02d:%02d +0000\", $days[$wday], $mday, $months[$mon], 1900+$year, $hour ,$min, $sec;\n+\t$date{'mday-time'} = sprintf \"%d %s %02d:%02d\", $mday, $months[$mon], $hour ,$min;\n+\n+\t$tz =~ m/^([+\\-][0-9][0-9])([0-9][0-9])$/;\n+\tmy $local = $epoch + ((int $1 + ($2/60)) * 3600);\n+\t($sec, $min, $hour, $mday, $mon, $year, $wday, $yday) = gmtime($local);\n+\t$date{'hour_local'} = $hour;\n+\t$date{'minute_local'} = $min;\n+\t$date{'tz_local'} = $tz;\n+\treturn %date;\n+}\n+\n sub git_read_tag {\n \tmy $tag_id = shift;\n \tmy %tag;\n@@ -548,37 +626,6 @@ sub git_read_tag {\n \treturn %tag\n }\n \n-sub age_string {\n-\tmy $age = shift;\n-\tmy $age_str;\n-\n-\tif ($age > 60*60*24*365*2) {\n-\t\t$age_str = (int $age/60/60/24/365);\n-\t\t$age_str .= \" years ago\";\n-\t} elsif ($age > 60*60*24*(365/12)*2) {\n-\t\t$age_str = int $age/60/60/24/(365/12);\n-\t\t$age_str .= \" months ago\";\n-\t} elsif ($age > 60*60*24*7*2) {\n-\t\t$age_str = int $age/60/60/24/7;\n-\t\t$age_str .= \" weeks ago\";\n-\t} elsif ($age > 60*60*24*2) {\n-\t\t$age_str = int $age/60/60/24;\n-\t\t$age_str .= \" days ago\";\n-\t} elsif ($age > 60*60*2) {\n-\t\t$age_str = int $age/60/60;\n-\t\t$age_str .= \" hours ago\";\n-\t} elsif ($age > 60*2) {\n-\t\t$age_str = int $age/60;\n-\t\t$age_str .= \" min ago\";\n-\t} elsif ($age > 2) {\n-\t\t$age_str = int $age;\n-\t\t$age_str .= \" sec ago\";\n-\t} else {\n-\t\t$age_str .= \" right now\";\n-\t}\n-\treturn $age_str;\n-}\n-\n sub git_read_commit {\n \tmy $commit_id = shift;\n \tmy $commit_text = shift;\n@@ -673,380 +720,8 @@ sub git_read_commit {\n \treturn %co;\n }\n \n-sub git_diff_print {\n-\tmy $from = shift;\n-\tmy $from_name = shift;\n-\tmy $to = shift;\n-\tmy $to_name = shift;\n-\tmy $format = shift || \"html\";\n-\n-\tmy $from_tmp = \"/dev/null\";\n-\tmy $to_tmp = \"/dev/null\";\n-\tmy $pid = $$;\n-\n-\t# create tmp from-file\n-\tif (defined $from) {\n-\t\t$from_tmp = \"$git_temp/gitweb_\" . $$ . \"_from\";\n-\t\topen my $fd2, \"> $from_tmp\";\n-\t\topen my $fd, \"-|\", $GIT, \"cat-file\", \"blob\", $from;\n-\t\tmy @file = <$fd>;\n-\t\tprint $fd2 @file;\n-\t\tclose $fd2;\n-\t\tclose $fd;\n-\t}\n-\n-\t# create tmp to-file\n-\tif (defined $to) {\n-\t\t$to_tmp = \"$git_temp/gitweb_\" . $$ . \"_to\";\n-\t\topen my $fd2, \"> $to_tmp\";\n-\t\topen my $fd, \"-|\", $GIT, \"cat-file\", \"blob\", $to;\n-\t\tmy @file = <$fd>;\n-\t\tprint $fd2 @file;\n-\t\tclose $fd2;\n-\t\tclose $fd;\n-\t}\n-\n-\topen my $fd, \"-|\", \"/usr/bin/diff -u -p -L \\'$from_name\\' -L \\'$to_name\\' $from_tmp $to_tmp\";\n-\tif ($format eq \"plain\") {\n-\t\tundef $/;\n-\t\tprint <$fd>;\n-\t\t$/ = \"\\n\";\n-\t} else {\n-\t\twhile (my $line = <$fd>) {\n-\t\t\tchomp $line;\n-\t\t\tmy $char = substr($line, 0, 1);\n-\t\t\tmy $diff_class = \"\";\n-\t\t\tif ($char eq '+') {\n-\t\t\t\t$diff_class = \" add\";\n-\t\t\t} elsif ($char eq \"-\") {\n-\t\t\t\t$diff_class = \" rem\";\n-\t\t\t} elsif ($char eq \"@\") {\n-\t\t\t\t$diff_class = \" chunk_header\";\n-\t\t\t} elsif ($char eq \"\\\\\") {\n-\t\t\t\t# skip errors\n-\t\t\t\tnext;\n-\t\t\t}\n-\t\t\twhile ((my $pos = index($line, \"\\t\")) != -1) {\n-\t\t\t\tif (my $count = (8 - (($pos-1) % 8))) {\n-\t\t\t\t\tmy $spaces = ' ' x $count;\n-\t\t\t\t\t$line =~ s/\\t/$spaces/;\n-\t\t\t\t}\n-\t\t\t}\n-\t\t\tprint \"<div class=\\\"diff$diff_class\\\">\" . esc_html($line) . \"</div>\\n\";\n-\t\t}\n-\t}\n-\tclose $fd;\n-\n-\tif (defined $from) {\n-\t\tunlink($from_tmp);\n-\t}\n-\tif (defined $to) {\n-\t\tunlink($to_tmp);\n-\t}\n-}\n-\n-sub mode_str {\n-\tmy $mode = oct shift;\n-\n-\tif (S_ISDIR($mode & S_IFMT)) {\n-\t\treturn 'drwxr-xr-x';\n-\t} elsif (S_ISLNK($mode)) {\n-\t\treturn 'lrwxrwxrwx';\n-\t} elsif (S_ISREG($mode)) {\n-\t\t# git cares only about the executable bit\n-\t\tif ($mode & S_IXUSR) {\n-\t\t\treturn '-rwxr-xr-x';\n-\t\t} else {\n-\t\t\treturn '-rw-r--r--';\n-\t\t};\n-\t} else {\n-\t\treturn '----------';\n-\t}\n-}\n-\n-sub chop_str {\n-\tmy $str = shift;\n-\tmy $len = shift;\n-\tmy $add_len = shift || 10;\n-\n-\t# allow only $len chars, but don't cut a word if it would fit in $add_len\n-\t# if it doesn't fit, cut it if it's still longer than the dots we would add\n-\t$str =~ m/^(.{0,$len}[^ \\/\\-_:\\.@]{0,$add_len})(.*)/;\n-\tmy $body = $1;\n-\tmy $tail = $2;\n-\tif (length($tail) > 4) {\n-\t\t$tail = \" ...\";\n-\t\t$body =~ s/&[^;]*$//; # remove chopped character entities\n-\t}\n-\treturn \"$body$tail\";\n-}\n-\n-sub file_type {\n-\tmy $mode = oct shift;\n-\n-\tif (S_ISDIR($mode & S_IFMT)) {\n-\t\treturn \"directory\";\n-\t} elsif (S_ISLNK($mode)) {\n-\t\treturn \"symlink\";\n-\t} elsif (S_ISREG($mode)) {\n-\t\treturn \"file\";\n-\t} else {\n-\t\treturn \"unknown\";\n-\t}\n-}\n-\n-sub format_log_line_html {\n-\tmy $line = shift;\n-\n-\t$line = esc_html($line);\n-\t$line =~ s/ /&nbsp;/g;\n-\tif ($line =~ m/([0-9a-fA-F]{40})/) {\n-\t\tmy $hash_text = $1;\n-\t\tif (git_get_type($hash_text) eq \"commit\") {\n-\t\t\tmy $link = $cgi->a({-class => \"text\", -href => \"$my_uri?\" . esc_param(\"p=$project;a=commit;h=$hash_text\")}, $hash_text);\n-\t\t\t$line =~ s/$hash_text/$link/;\n-\t\t}\n-\t}\n-\treturn $line;\n-}\n-\n-sub date_str {\n-\tmy $epoch = shift;\n-\tmy $tz = shift || \"-0000\";\n-\n-\tmy %date;\n-\tmy @months = (\"Jan\", \"Feb\", \"Mar\", \"Apr\", \"May\", \"Jun\", \"Jul\", \"Aug\", \"Sep\", \"Oct\", \"Nov\", \"Dec\");\n-\tmy @days = (\"Sun\", \"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\", \"Sat\");\n-\tmy ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday) = gmtime($epoch);\n-\t$date{'hour'} = $hour;\n-\t$date{'minute'} = $min;\n-\t$date{'mday'} = $mday;\n-\t$date{'day'} = $days[$wday];\n-\t$date{'month'} = $months[$mon];\n-\t$date{'rfc2822'} = sprintf \"%s, %d %s %4d %02d:%02d:%02d +0000\", $days[$wday], $mday, $months[$mon], 1900+$year, $hour ,$min, $sec;\n-\t$date{'mday-time'} = sprintf \"%d %s %02d:%02d\", $mday, $months[$mon], $hour ,$min;\n-\n-\t$tz =~ m/^([+\\-][0-9][0-9])([0-9][0-9])$/;\n-\tmy $local = $epoch + ((int $1 + ($2/60)) * 3600);\n-\t($sec, $min, $hour, $mday, $mon, $year, $wday, $yday) = gmtime($local);\n-\t$date{'hour_local'} = $hour;\n-\t$date{'minute_local'} = $min;\n-\t$date{'tz_local'} = $tz;\n-\treturn %date;\n-}\n-\n-# git-logo (cached in browser for one day)\n-sub git_logo {\n-\tbinmode STDOUT, ':raw';\n-\tprint $cgi->header(-type => 'image/png', -expires => '+1d');\n-\t# cat git-logo.png | hexdump -e '16/1 \" %02x\"  \"\\n\"' | sed 's/ /\\\\x/g'\n-\tprint\t\"\\x89\\x50\\x4e\\x47\\x0d\\x0a\\x1a\\x0a\\x00\\x00\\x00\\x0d\\x49\\x48\\x44\\x52\" .\n-\t\t\"\\x00\\x00\\x00\\x48\\x00\\x00\\x00\\x1b\\x04\\x03\\x00\\x00\\x00\\x2d\\xd9\\xd4\" .\n-\t\t\"\\x2d\\x00\\x00\\x00\\x18\\x50\\x4c\\x54\\x45\\xff\\xff\\xff\\x60\\x60\\x5d\\xb0\" .\n-\t\t\"\\xaf\\xaa\\x00\\x80\\x00\\xce\\xcd\\xc7\\xc0\\x00\\x00\\xe8\\xe8\\xe6\\xf7\\xf7\" .\n-\t\t\"\\xf6\\x95\\x0c\\xa7\\x47\\x00\\x00\\x00\\x73\\x49\\x44\\x41\\x54\\x28\\xcf\\x63\" .\n-\t\t\"\\x48\\x67\\x20\\x04\\x4a\\x5c\\x18\\x0a\\x08\\x2a\\x62\\x53\\x61\\x20\\x02\\x08\" .\n-\t\t\"\\x0d\\x69\\x45\\xac\\xa1\\xa1\\x01\\x30\\x0c\\x93\\x60\\x36\\x26\\x52\\x91\\xb1\" .\n-\t\t\"\\x01\\x11\\xd6\\xe1\\x55\\x64\\x6c\\x6c\\xcc\\x6c\\x6c\\x0c\\xa2\\x0c\\x70\\x2a\" .\n-\t\t\"\\x62\\x06\\x2a\\xc1\\x62\\x1d\\xb3\\x01\\x02\\x53\\xa4\\x08\\xe8\\x00\\x03\\x18\" .\n-\t\t\"\\x26\\x56\\x11\\xd4\\xe1\\x20\\x97\\x1b\\xe0\\xb4\\x0e\\x35\\x24\\x71\\x29\\x82\" .\n-\t\t\"\\x99\\x30\\xb8\\x93\\x0a\\x11\\xb9\\x45\\x88\\xc1\\x8d\\xa0\\xa2\\x44\\x21\\x06\" .\n-\t\t\"\\x27\\x41\\x82\\x40\\x85\\xc1\\x45\\x89\\x20\\x70\\x01\\x00\\xa4\\x3d\\x21\\xc5\" .\n-\t\t\"\\x12\\x1c\\x9a\\xfe\\x00\\x00\\x00\\x00\\x49\\x45\\x4e\\x44\\xae\\x42\\x60\\x82\";\n-}\n-\n-sub get_file_owner {\n-\tmy $path = shift;\n-\n-\tmy ($dev, $ino, $mode, $nlink, $st_uid, $st_gid, $rdev, $size) = stat($path);\n-\tmy ($name, $passwd, $uid, $gid, $quota, $comment, $gcos, $dir, $shell) = getpwuid($st_uid);\n-\tif (!defined $gcos) {\n-\t\treturn undef;\n-\t}\n-\tmy $owner = $gcos;\n-\t$owner =~ s/[,;].*$//;\n-\treturn decode(\"utf8\", $owner, Encode::FB_DEFAULT);\n-}\n-\n-sub git_read_projects {\n-\tmy @list;\n-\n-\tif (-d $projects_list) {\n-\t\t# search in directory\n-\t\tmy $dir = $projects_list;\n-\t\topendir my ($dh), $dir or return undef;\n-\t\twhile (my $dir = readdir($dh)) {\n-\t\t\tif (-e \"$projectroot/$dir/HEAD\") {\n-\t\t\t\tmy $pr = {\n-\t\t\t\t\tpath => $dir,\n-\t\t\t\t};\n-\t\t\t\tpush @list, $pr\n-\t\t\t}\n-\t\t}\n-\t\tclosedir($dh);\n-\t} elsif (-f $projects_list) {\n-\t\t# read from file(url-encoded):\n-\t\t# 'git%2Fgit.git Linus+Torvalds'\n-\t\t# 'libs%2Fklibc%2Fklibc.git H.+Peter+Anvin'\n-\t\t# 'linux%2Fhotplug%2Fudev.git Greg+Kroah-Hartman'\n-\t\topen my ($fd), $projects_list or return undef;\n-\t\twhile (my $line = <$fd>) {\n-\t\t\tchomp $line;\n-\t\t\tmy ($path, $owner) = split ' ', $line;\n-\t\t\t$path = unescape($path);\n-\t\t\t$owner = unescape($owner);\n-\t\t\tif (!defined $path) {\n-\t\t\t\tnext;\n-\t\t\t}\n-\t\t\tif (-e \"$projectroot/$path/HEAD\") {\n-\t\t\t\tmy $pr = {\n-\t\t\t\t\tpath => $path,\n-\t\t\t\t\towner => decode(\"utf8\", $owner, Encode::FB_DEFAULT),\n-\t\t\t\t};\n-\t\t\t\tpush @list, $pr\n-\t\t\t}\n-\t\t}\n-\t\tclose $fd;\n-\t}\n-\t@list = sort {$a->{'path'} cmp $b->{'path'}} @list;\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-\tif (!@list) {\n-\t\tdie_error(undef, \"No project found.\");\n-\t}\n-\tforeach my $pr (@list) {\n-\t\tmy $head = git_read_head($pr->{'path'});\n-\t\tif (!defined $head) {\n-\t\t\tnext;\n-\t\t}\n-\t\t$ENV{'GIT_DIR'} = \"$projectroot/$pr->{'path'}\";\n-\t\tmy %co = git_read_commit($head);\n-\t\tif (!%co) {\n-\t\t\tnext;\n-\t\t}\n-\t\t$pr->{'commit'} = \\%co;\n-\t\tif (!defined $pr->{'descr'}) {\n-\t\t\tmy $descr = git_read_description($pr->{'path'}) || \"\";\n-\t\t\t$pr->{'descr'} = chop_str($descr, 25, 5);\n-\t\t}\n-\t\tif (!defined $pr->{'owner'}) {\n-\t\t\t$pr->{'owner'} = get_file_owner(\"$projectroot/$pr->{'path'}\") || \"\";\n-\t\t}\n-\t\tpush @projects, $pr;\n-\t}\n-\tgit_header_html();\n-\tif (-f $home_text) {\n-\t\tprint \"<div class=\\\"index_include\\\">\\n\";\n-\t\topen (my $fd, $home_text);\n-\t\tprint <$fd>;\n-\t\tclose $fd;\n-\t\tprint \"</div>\\n\";\n-\t}\n-\tprint \"<table class=\\\"project_list\\\">\\n\" .\n-\t      \"<tr>\\n\";\n-\tif (!defined($order) || (defined($order) && ($order eq \"project\"))) {\n-\t\t@projects = sort {$a->{'path'} cmp $b->{'path'}} @projects;\n-\t\tprint \"<th>Project</th>\\n\";\n-\t} else {\n-\t\tprint \"<th>\" . $cgi->a({-class => \"header\", -href => \"$my_uri?\" . esc_param(\"o=project\")}, \"Project\") . \"</th>\\n\";\n-\t}\n-\tif (defined($order) && ($order eq \"descr\")) {\n-\t\t@projects = sort {$a->{'descr'} cmp $b->{'descr'}} @projects;\n-\t\tprint \"<th>Description</th>\\n\";\n-\t} else {\n-\t\tprint \"<th>\" . $cgi->a({-class => \"header\", -href => \"$my_uri?\" . esc_param(\"o=descr\")}, \"Description\") . \"</th>\\n\";\n-\t}\n-\tif (defined($order) && ($order eq \"owner\")) {\n-\t\t@projects = sort {$a->{'owner'} cmp $b->{'owner'}} @projects;\n-\t\tprint \"<th>Owner</th>\\n\";\n-\t} else {\n-\t\tprint \"<th>\" . $cgi->a({-class => \"header\", -href => \"$my_uri?\" . esc_param(\"o=owner\")}, \"Owner\") . \"</th>\\n\";\n-\t}\n-\tif (defined($order) && ($order eq \"age\")) {\n-\t\t@projects = sort {$a->{'commit'}{'age'} <=> $b->{'commit'}{'age'}} @projects;\n-\t\tprint \"<th>Last Change</th>\\n\";\n-\t} else {\n-\t\tprint \"<th>\" . $cgi->a({-class => \"header\", -href => \"$my_uri?\" . esc_param(\"o=age\")}, \"Last Change\") . \"</th>\\n\";\n-\t}\n-\tprint \"<th></th>\\n\" .\n-\t      \"</tr>\\n\";\n-\tmy $alternate = 0;\n-\tforeach my $pr (@projects) {\n-\t\tif ($alternate) {\n-\t\t\tprint \"<tr class=\\\"dark\\\">\\n\";\n-\t\t} else {\n-\t\t\tprint \"<tr class=\\\"light\\\">\\n\";\n-\t\t}\n-\t\t$alternate ^= 1;\n-\t\tprint \"<td>\" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$pr->{'path'};a=summary\"), -class => \"list\"}, esc_html($pr->{'path'})) . \"</td>\\n\" .\n-\t\t      \"<td>\" . esc_html($pr->{'descr'}) . \"</td>\\n\" .\n-\t\t      \"<td><i>\" . chop_str($pr->{'owner'}, 15) . \"</i></td>\\n\";\n-\t\tprint \"<td class=\\\"\". age_class($pr->{'commit'}{'age'}) . \"\\\">\" . $pr->{'commit'}{'age_string'} . \"</td>\\n\" .\n-\t\t      \"<td class=\\\"link\\\">\" .\n-\t\t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$pr->{'path'};a=summary\")}, \"summary\") .\n-\t\t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$pr->{'path'};a=shortlog\")}, \"shortlog\") .\n-\t\t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$pr->{'path'};a=log\")}, \"log\") .\n-\t\t      \"</td>\\n\" .\n-\t\t      \"</tr>\\n\";\n-\t}\n-\tprint \"</table>\\n\";\n-\tgit_footer_html();\n-}\n-\n-sub read_info_ref {\n-\tmy $type = shift || \"\";\n-\tmy %refs;\n-\t# 5dc01c595e6c6ec9ccda4f6f69c131c0dd945f8c\trefs/tags/v2.6.11\n-\t# c39ae07f393806ccf406ef966e9a15afc43cc36a\trefs/tags/v2.6.11^{}\n-\topen my $fd, \"$projectroot/$project/info/refs\" or return;\n-\twhile (my $line = <$fd>) {\n-\t\tchomp $line;\n-\t\t# attention: for $type == \"\" it saves only last path part of ref name\n-\t\t# e.g. from 'refs/heads/jn/gitweb' it would leave only 'gitweb'\n-\t\tif ($line =~ m/^([0-9a-fA-F]{40})\\t.*$type\\/([^\\^]+)/) {\n-\t\t\tif (defined $refs{$1}) {\n-\t\t\t\t$refs{$1} .= \" / $2\";\n-\t\t\t} else {\n-\t\t\t\t$refs{$1} = $2;\n-\t\t\t}\n-\t\t}\n-\t}\n-\tclose $fd or return;\n-\treturn \\%refs;\n-}\n-\n-sub git_get_referencing {\n-\tmy ($refs, $id) = @_;\n-\n-\tif (defined $refs->{$id}) {\n-\t\treturn ' <span class=\"tag\">' . esc_html($refs->{$id}) . '</span>';\n-\t} else {\n-\t\treturn \"\";\n-\t}\n-}\n+## ......................................................................\n+## parse to array of hashes functions\n \n sub git_read_refs {\n \tmy $ref_dir = shift;\n@@ -1115,6 +790,299 @@ sub git_read_refs {\n \treturn \\@reflist;\n }\n \n+## ----------------------------------------------------------------------\n+## filesystem-related functions\n+\n+sub get_file_owner {\n+\tmy $path = shift;\n+\n+\tmy ($dev, $ino, $mode, $nlink, $st_uid, $st_gid, $rdev, $size) = stat($path);\n+\tmy ($name, $passwd, $uid, $gid, $quota, $comment, $gcos, $dir, $shell) = getpwuid($st_uid);\n+\tif (!defined $gcos) {\n+\t\treturn undef;\n+\t}\n+\tmy $owner = $gcos;\n+\t$owner =~ s/[,;].*$//;\n+\treturn decode(\"utf8\", $owner, Encode::FB_DEFAULT);\n+}\n+\n+## ......................................................................\n+## mimetype related functions\n+\n+sub mimetype_guess_file {\n+\tmy $filename = shift;\n+\tmy $mimemap = shift;\n+\t-r $mimemap or return undef;\n+\n+\tmy %mimemap;\n+\topen(MIME, $mimemap) or return undef;\n+\twhile (<MIME>) {\n+\t\tmy ($mime, $exts) = split(/\\t+/);\n+\t\tmy @exts = split(/\\s+/, $exts);\n+\t\tforeach my $ext (@exts) {\n+\t\t\t$mimemap{$ext} = $mime;\n+\t\t}\n+\t}\n+\tclose(MIME);\n+\n+\t$filename =~ /\\.(.*?)$/;\n+\treturn $mimemap{$1};\n+}\n+\n+sub mimetype_guess {\n+\tmy $filename = shift;\n+\tmy $mime;\n+\t$filename =~ /\\./ or return undef;\n+\n+\tif ($mimetypes_file) {\n+\t\tmy $file = $mimetypes_file;\n+\t\t#$file =~ m#^/# or $file = \"$projectroot/$path/$file\";\n+\t\t$mime = mimetype_guess_file($filename, $file);\n+\t}\n+\t$mime ||= mimetype_guess_file($filename, '/etc/mime.types');\n+\treturn $mime;\n+}\n+\n+sub git_blob_plain_mimetype {\n+\tmy $fd = shift;\n+\tmy $filename = shift;\n+\n+\tif ($filename) {\n+\t\tmy $mime = mimetype_guess($filename);\n+\t\t$mime and return $mime;\n+\t}\n+\n+\t# just in case\n+\treturn $default_blob_plain_mimetype unless $fd;\n+\n+\tif (-T $fd) {\n+\t\treturn 'text/plain' .\n+\t\t       ($default_text_plain_charset ? '; charset='.$default_text_plain_charset : '');\n+\t} elsif (! $filename) {\n+\t\treturn 'application/octet-stream';\n+\t} elsif ($filename =~ m/\\.png$/i) {\n+\t\treturn 'image/png';\n+\t} elsif ($filename =~ m/\\.gif$/i) {\n+\t\treturn 'image/gif';\n+\t} elsif ($filename =~ m/\\.jpe?g$/i) {\n+\t\treturn 'image/jpeg';\n+\t} else {\n+\t\treturn 'application/octet-stream';\n+\t}\n+}\n+\n+## ======================================================================\n+## functions printing HTML: header, footer, error page\n+\n+sub git_header_html {\n+\tmy $status = shift || \"200 OK\";\n+\tmy $expires = shift;\n+\n+\tmy $title = \"$site_name git\";\n+\tif (defined $project) {\n+\t\t$title .= \" - $project\";\n+\t\tif (defined $action) {\n+\t\t\t$title .= \"/$action\";\n+\t\t\tif (defined $file_name) {\n+\t\t\t\t$title .= \" - $file_name\";\n+\t\t\t\tif ($action eq \"tree\" && $file_name !~ m|/$|) {\n+\t\t\t\t\t$title .= \"/\";\n+\t\t\t\t}\n+\t\t\t}\n+\t\t}\n+\t}\n+\tmy $content_type;\n+\t# require explicit support from the UA if we are to send the page as\n+\t# 'application/xhtml+xml', otherwise send it as plain old 'text/html'.\n+\t# we have to do this because MSIE sometimes globs '*/*', pretending to\n+\t# support xhtml+xml but choking when it gets what it asked for.\n+\tif ($cgi->http('HTTP_ACCEPT') =~ m/(,|;|\\s|^)application\\/xhtml\\+xml(,|;|\\s|$)/ && $cgi->Accept('application/xhtml+xml') != 0) {\n+\t\t$content_type = 'application/xhtml+xml';\n+\t} else {\n+\t\t$content_type = 'text/html';\n+\t}\n+\tprint $cgi->header(-type=>$content_type, -charset => 'utf-8', -status=> $status, -expires => $expires);\n+\tprint <<EOF;\n+<?xml version=\"1.0\" encoding=\"utf-8\"?>\n+<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n+<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en-US\" lang=\"en-US\">\n+<!-- git web interface v$version, (C) 2005-2006, Kay Sievers <kay.sievers\\@vrfy.org>, Christian Gierke -->\n+<!-- git core binaries version $git_version -->\n+<head>\n+<meta http-equiv=\"content-type\" content=\"$content_type; charset=utf-8\"/>\n+<meta name=\"robots\" content=\"index, nofollow\"/>\n+<title>$title</title>\n+<link rel=\"stylesheet\" type=\"text/css\" href=\"$stylesheet\"/>\n+$rss_link\n+</head>\n+<body>\n+EOF\n+\tprint \"<div class=\\\"page_header\\\">\\n\" .\n+\t      \"<a href=\\\"http://www.kernel.org/pub/software/scm/git/docs/\\\" title=\\\"git documentation\\\">\" .\n+\t      \"<img src=\\\"$my_uri?\" . esc_param(\"a=git-logo.png\") . \"\\\" width=\\\"72\\\" height=\\\"27\\\" alt=\\\"git\\\" style=\\\"float:right; border-width:0px;\\\"/>\" .\n+\t      \"</a>\\n\";\n+\tprint $cgi->a({-href => esc_param($home_link)}, \"projects\") . \" / \";\n+\tif (defined $project) {\n+\t\tprint $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=summary\")}, esc_html($project));\n+\t\tif (defined $action) {\n+\t\t\tprint \" / $action\";\n+\t\t}\n+\t\tprint \"\\n\";\n+\t\tif (!defined $searchtext) {\n+\t\t\t$searchtext = \"\";\n+\t\t}\n+\t\tmy $search_hash;\n+\t\tif (defined $hash_base) {\n+\t\t\t$search_hash = $hash_base;\n+\t\t} elsif (defined $hash) {\n+\t\t\t$search_hash = $hash;\n+\t\t} else {\n+\t\t\t$search_hash = \"HEAD\";\n+\t\t}\n+\t\t$cgi->param(\"a\", \"search\");\n+\t\t$cgi->param(\"h\", $search_hash);\n+\t\tprint $cgi->startform(-method => \"get\", -action => $my_uri) .\n+\t\t      \"<div class=\\\"search\\\">\\n\" .\n+\t\t      $cgi->hidden(-name => \"p\") . \"\\n\" .\n+\t\t      $cgi->hidden(-name => \"a\") . \"\\n\" .\n+\t\t      $cgi->hidden(-name => \"h\") . \"\\n\" .\n+\t\t      $cgi->textfield(-name => \"s\", -value => $searchtext) . \"\\n\" .\n+\t\t      \"</div>\" .\n+\t\t      $cgi->end_form() . \"\\n\";\n+\t}\n+\tprint \"</div>\\n\";\n+}\n+\n+sub git_footer_html {\n+\tprint \"<div class=\\\"page_footer\\\">\\n\";\n+\tif (defined $project) {\n+\t\tmy $descr = git_read_description($project);\n+\t\tif (defined $descr) {\n+\t\t\tprint \"<div class=\\\"page_footer_text\\\">\" . esc_html($descr) . \"</div>\\n\";\n+\t\t}\n+\t\tprint $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=rss\"), -class => \"rss_logo\"}, \"RSS\") . \"\\n\";\n+\t} else {\n+\t\tprint $cgi->a({-href => \"$my_uri?\" . esc_param(\"a=opml\"), -class => \"rss_logo\"}, \"OPML\") . \"\\n\";\n+\t}\n+\tprint \"</div>\\n\" .\n+\t      \"</body>\\n\" .\n+\t      \"</html>\";\n+}\n+\n+sub die_error {\n+\tmy $status = shift || \"403 Forbidden\";\n+\tmy $error = shift || \"Malformed query, file missing or permission denied\";\n+\n+\tgit_header_html($status);\n+\tprint \"<div class=\\\"page_body\\\">\\n\" .\n+\t      \"<br/><br/>\\n\" .\n+\t      \"$status - $error\\n\" .\n+\t      \"<br/>\\n\" .\n+\t      \"</div>\\n\";\n+\tgit_footer_html();\n+\texit;\n+}\n+\n+## ----------------------------------------------------------------------\n+## functions printing or outputting HTML: navigation\n+\n+sub git_page_nav {\n+\tmy ($current, $suppress, $head, $treehead, $treebase, $extra) = @_;\n+\t$extra = '' if !defined $extra; # pager or formats\n+\n+\tmy @navs = qw(summary shortlog log commit commitdiff tree);\n+\tif ($suppress) {\n+\t\t@navs = grep { $_ ne $suppress } @navs;\n+\t}\n+\n+\tmy %arg = map { $_, ''} @navs;\n+\tif (defined $head) {\n+\t\tfor (qw(commit commitdiff)) {\n+\t\t\t$arg{$_} = \";h=$head\";\n+\t\t}\n+\t\tif ($current =~ m/^(tree | log | shortlog | commit | commitdiff | search)$/x) {\n+\t\t\tfor (qw(shortlog log)) {\n+\t\t\t\t$arg{$_} = \";h=$head\";\n+\t\t\t}\n+\t\t}\n+\t}\n+\t$arg{tree} .= \";h=$treehead\" if defined $treehead;\n+\t$arg{tree} .= \";hb=$treebase\" if defined $treebase;\n+\n+\tprint \"<div class=\\\"page_nav\\\">\\n\" .\n+\t\t(join \" | \",\n+\t\t map { $_ eq $current\n+\t\t\t\t\t ? $_\n+\t\t\t\t\t : $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=$_$arg{$_}\")}, \"$_\")\n+\t\t\t\t }\n+\t\t @navs);\n+\tprint \"<br/>\\n$extra<br/>\\n\" .\n+\t      \"</div>\\n\";\n+}\n+\n+sub git_get_paging_nav {\n+\tmy ($action, $hash, $head, $page, $nrevs) = @_;\n+\tmy $paging_nav;\n+\n+\n+\tif ($hash ne $head || $page) {\n+\t\t$paging_nav .= $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=$action\")}, \"HEAD\");\n+\t} else {\n+\t\t$paging_nav .= \"HEAD\";\n+\t}\n+\n+\tif ($page > 0) {\n+\t\t$paging_nav .= \" &sdot; \" .\n+\t\t\t$cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=$action;h=$hash;pg=\" . ($page-1)),\n+\t\t\t\t\t\t\t -accesskey => \"p\", -title => \"Alt-p\"}, \"prev\");\n+\t} else {\n+\t\t$paging_nav .= \" &sdot; prev\";\n+\t}\n+\n+\tif ($nrevs >= (100 * ($page+1)-1)) {\n+\t\t$paging_nav .= \" &sdot; \" .\n+\t\t\t$cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=$action;h=$hash;pg=\" . ($page+1)),\n+\t\t\t\t\t\t\t -accesskey => \"n\", -title => \"Alt-n\"}, \"next\");\n+\t} else {\n+\t\t$paging_nav .= \" &sdot; next\";\n+\t}\n+\n+\treturn $paging_nav;\n+}\n+\n+## ......................................................................\n+## functions printing or outputting HTML: div\n+\n+sub git_header_div {\n+\tmy ($action, $title, $hash, $hash_base) = @_;\n+\tmy $rest = '';\n+\n+\t$rest .= \";h=$hash\" if $hash;\n+\t$rest .= \";hb=$hash_base\" if $hash_base;\n+\n+\tprint \"<div class=\\\"header\\\">\\n\" .\n+\t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=$action$rest\"),\n+\t               -class => \"title\"}, $title ? $title : $action) . \"\\n\" .\n+\t      \"</div>\\n\";\n+}\n+\n+sub git_print_page_path {\n+\tmy $name = shift;\n+\tmy $type = shift;\n+\n+\tif (!defined $name) {\n+\t\tprint \"<div class=\\\"page_path\\\"><b>/</b></div>\\n\";\n+\t} elsif ($type =~ \"blob\") {\n+\t\tprint \"<div class=\\\"page_path\\\"><b>\" .\n+\t\t\t$cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=blob_plain;f=$file_name\")}, esc_html($name)) . \"</b><br/></div>\\n\";\n+\t} else {\n+\t\tprint \"<div class=\\\"page_path\\\"><b>\" . esc_html($name) . \"</b><br/></div>\\n\";\n+\t}\n+}\n+\n+## ......................................................................\n+## functions printing large fragments of HTML\n+\n sub git_shortlog_body {\n \t# uses global variable $project\n \tmy ($revlist, $from, $to, $refs, $extra) = @_;\n@@ -1265,6 +1233,191 @@ sub git_heads_body {\n \tprint \"</table>\\n\";\n }\n \n+## ----------------------------------------------------------------------\n+## functions printing large fragments, format as one of arguments\n+\n+sub git_diff_print {\n+\tmy $from = shift;\n+\tmy $from_name = shift;\n+\tmy $to = shift;\n+\tmy $to_name = shift;\n+\tmy $format = shift || \"html\";\n+\n+\tmy $from_tmp = \"/dev/null\";\n+\tmy $to_tmp = \"/dev/null\";\n+\tmy $pid = $$;\n+\n+\t# create tmp from-file\n+\tif (defined $from) {\n+\t\t$from_tmp = \"$git_temp/gitweb_\" . $$ . \"_from\";\n+\t\topen my $fd2, \"> $from_tmp\";\n+\t\topen my $fd, \"-|\", $GIT, \"cat-file\", \"blob\", $from;\n+\t\tmy @file = <$fd>;\n+\t\tprint $fd2 @file;\n+\t\tclose $fd2;\n+\t\tclose $fd;\n+\t}\n+\n+\t# create tmp to-file\n+\tif (defined $to) {\n+\t\t$to_tmp = \"$git_temp/gitweb_\" . $$ . \"_to\";\n+\t\topen my $fd2, \"> $to_tmp\";\n+\t\topen my $fd, \"-|\", $GIT, \"cat-file\", \"blob\", $to;\n+\t\tmy @file = <$fd>;\n+\t\tprint $fd2 @file;\n+\t\tclose $fd2;\n+\t\tclose $fd;\n+\t}\n+\n+\topen my $fd, \"-|\", \"/usr/bin/diff -u -p -L \\'$from_name\\' -L \\'$to_name\\' $from_tmp $to_tmp\";\n+\tif ($format eq \"plain\") {\n+\t\tundef $/;\n+\t\tprint <$fd>;\n+\t\t$/ = \"\\n\";\n+\t} else {\n+\t\twhile (my $line = <$fd>) {\n+\t\t\tchomp $line;\n+\t\t\tmy $char = substr($line, 0, 1);\n+\t\t\tmy $diff_class = \"\";\n+\t\t\tif ($char eq '+') {\n+\t\t\t\t$diff_class = \" add\";\n+\t\t\t} elsif ($char eq \"-\") {\n+\t\t\t\t$diff_class = \" rem\";\n+\t\t\t} elsif ($char eq \"@\") {\n+\t\t\t\t$diff_class = \" chunk_header\";\n+\t\t\t} elsif ($char eq \"\\\\\") {\n+\t\t\t\t# skip errors\n+\t\t\t\tnext;\n+\t\t\t}\n+\t\t\twhile ((my $pos = index($line, \"\\t\")) != -1) {\n+\t\t\t\tif (my $count = (8 - (($pos-1) % 8))) {\n+\t\t\t\t\tmy $spaces = ' ' x $count;\n+\t\t\t\t\t$line =~ s/\\t/$spaces/;\n+\t\t\t\t}\n+\t\t\t}\n+\t\t\tprint \"<div class=\\\"diff$diff_class\\\">\" . esc_html($line) . \"</div>\\n\";\n+\t\t}\n+\t}\n+\tclose $fd;\n+\n+\tif (defined $from) {\n+\t\tunlink($from_tmp);\n+\t}\n+\tif (defined $to) {\n+\t\tunlink($to_tmp);\n+\t}\n+}\n+\n+\n+## ======================================================================\n+## ======================================================================\n+## actions\n+\n+# git-logo (cached in browser for one day)\n+sub git_logo {\n+\tbinmode STDOUT, ':raw';\n+\tprint $cgi->header(-type => 'image/png', -expires => '+1d');\n+\t# cat git-logo.png | hexdump -e '16/1 \" %02x\"  \"\\n\"' | sed 's/ /\\\\x/g'\n+\tprint\t\"\\x89\\x50\\x4e\\x47\\x0d\\x0a\\x1a\\x0a\\x00\\x00\\x00\\x0d\\x49\\x48\\x44\\x52\" .\n+\t\t\"\\x00\\x00\\x00\\x48\\x00\\x00\\x00\\x1b\\x04\\x03\\x00\\x00\\x00\\x2d\\xd9\\xd4\" .\n+\t\t\"\\x2d\\x00\\x00\\x00\\x18\\x50\\x4c\\x54\\x45\\xff\\xff\\xff\\x60\\x60\\x5d\\xb0\" .\n+\t\t\"\\xaf\\xaa\\x00\\x80\\x00\\xce\\xcd\\xc7\\xc0\\x00\\x00\\xe8\\xe8\\xe6\\xf7\\xf7\" .\n+\t\t\"\\xf6\\x95\\x0c\\xa7\\x47\\x00\\x00\\x00\\x73\\x49\\x44\\x41\\x54\\x28\\xcf\\x63\" .\n+\t\t\"\\x48\\x67\\x20\\x04\\x4a\\x5c\\x18\\x0a\\x08\\x2a\\x62\\x53\\x61\\x20\\x02\\x08\" .\n+\t\t\"\\x0d\\x69\\x45\\xac\\xa1\\xa1\\x01\\x30\\x0c\\x93\\x60\\x36\\x26\\x52\\x91\\xb1\" .\n+\t\t\"\\x01\\x11\\xd6\\xe1\\x55\\x64\\x6c\\x6c\\xcc\\x6c\\x6c\\x0c\\xa2\\x0c\\x70\\x2a\" .\n+\t\t\"\\x62\\x06\\x2a\\xc1\\x62\\x1d\\xb3\\x01\\x02\\x53\\xa4\\x08\\xe8\\x00\\x03\\x18\" .\n+\t\t\"\\x26\\x56\\x11\\xd4\\xe1\\x20\\x97\\x1b\\xe0\\xb4\\x0e\\x35\\x24\\x71\\x29\\x82\" .\n+\t\t\"\\x99\\x30\\xb8\\x93\\x0a\\x11\\xb9\\x45\\x88\\xc1\\x8d\\xa0\\xa2\\x44\\x21\\x06\" .\n+\t\t\"\\x27\\x41\\x82\\x40\\x85\\xc1\\x45\\x89\\x20\\x70\\x01\\x00\\xa4\\x3d\\x21\\xc5\" .\n+\t\t\"\\x12\\x1c\\x9a\\xfe\\x00\\x00\\x00\\x00\\x49\\x45\\x4e\\x44\\xae\\x42\\x60\\x82\";\n+}\n+\n+sub git_project_list {\n+\tmy @list = git_read_projects();\n+\tmy @projects;\n+\tif (!@list) {\n+\t\tdie_error(undef, \"No project found.\");\n+\t}\n+\tforeach my $pr (@list) {\n+\t\tmy $head = git_read_head($pr->{'path'});\n+\t\tif (!defined $head) {\n+\t\t\tnext;\n+\t\t}\n+\t\t$ENV{'GIT_DIR'} = \"$projectroot/$pr->{'path'}\";\n+\t\tmy %co = git_read_commit($head);\n+\t\tif (!%co) {\n+\t\t\tnext;\n+\t\t}\n+\t\t$pr->{'commit'} = \\%co;\n+\t\tif (!defined $pr->{'descr'}) {\n+\t\t\tmy $descr = git_read_description($pr->{'path'}) || \"\";\n+\t\t\t$pr->{'descr'} = chop_str($descr, 25, 5);\n+\t\t}\n+\t\tif (!defined $pr->{'owner'}) {\n+\t\t\t$pr->{'owner'} = get_file_owner(\"$projectroot/$pr->{'path'}\") || \"\";\n+\t\t}\n+\t\tpush @projects, $pr;\n+\t}\n+\tgit_header_html();\n+\tif (-f $home_text) {\n+\t\tprint \"<div class=\\\"index_include\\\">\\n\";\n+\t\topen (my $fd, $home_text);\n+\t\tprint <$fd>;\n+\t\tclose $fd;\n+\t\tprint \"</div>\\n\";\n+\t}\n+\tprint \"<table class=\\\"project_list\\\">\\n\" .\n+\t      \"<tr>\\n\";\n+\tif (!defined($order) || (defined($order) && ($order eq \"project\"))) {\n+\t\t@projects = sort {$a->{'path'} cmp $b->{'path'}} @projects;\n+\t\tprint \"<th>Project</th>\\n\";\n+\t} else {\n+\t\tprint \"<th>\" . $cgi->a({-class => \"header\", -href => \"$my_uri?\" . esc_param(\"o=project\")}, \"Project\") . \"</th>\\n\";\n+\t}\n+\tif (defined($order) && ($order eq \"descr\")) {\n+\t\t@projects = sort {$a->{'descr'} cmp $b->{'descr'}} @projects;\n+\t\tprint \"<th>Description</th>\\n\";\n+\t} else {\n+\t\tprint \"<th>\" . $cgi->a({-class => \"header\", -href => \"$my_uri?\" . esc_param(\"o=descr\")}, \"Description\") . \"</th>\\n\";\n+\t}\n+\tif (defined($order) && ($order eq \"owner\")) {\n+\t\t@projects = sort {$a->{'owner'} cmp $b->{'owner'}} @projects;\n+\t\tprint \"<th>Owner</th>\\n\";\n+\t} else {\n+\t\tprint \"<th>\" . $cgi->a({-class => \"header\", -href => \"$my_uri?\" . esc_param(\"o=owner\")}, \"Owner\") . \"</th>\\n\";\n+\t}\n+\tif (defined($order) && ($order eq \"age\")) {\n+\t\t@projects = sort {$a->{'commit'}{'age'} <=> $b->{'commit'}{'age'}} @projects;\n+\t\tprint \"<th>Last Change</th>\\n\";\n+\t} else {\n+\t\tprint \"<th>\" . $cgi->a({-class => \"header\", -href => \"$my_uri?\" . esc_param(\"o=age\")}, \"Last Change\") . \"</th>\\n\";\n+\t}\n+\tprint \"<th></th>\\n\" .\n+\t      \"</tr>\\n\";\n+\tmy $alternate = 0;\n+\tforeach my $pr (@projects) {\n+\t\tif ($alternate) {\n+\t\t\tprint \"<tr class=\\\"dark\\\">\\n\";\n+\t\t} else {\n+\t\t\tprint \"<tr class=\\\"light\\\">\\n\";\n+\t\t}\n+\t\t$alternate ^= 1;\n+\t\tprint \"<td>\" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$pr->{'path'};a=summary\"), -class => \"list\"}, esc_html($pr->{'path'})) . \"</td>\\n\" .\n+\t\t      \"<td>\" . esc_html($pr->{'descr'}) . \"</td>\\n\" .\n+\t\t      \"<td><i>\" . chop_str($pr->{'owner'}, 15) . \"</i></td>\\n\";\n+\t\tprint \"<td class=\\\"\". age_class($pr->{'commit'}{'age'}) . \"\\\">\" . $pr->{'commit'}{'age_string'} . \"</td>\\n\" .\n+\t\t      \"<td class=\\\"link\\\">\" .\n+\t\t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$pr->{'path'};a=summary\")}, \"summary\") .\n+\t\t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$pr->{'path'};a=shortlog\")}, \"shortlog\") .\n+\t\t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$pr->{'path'};a=log\")}, \"log\") .\n+\t\t      \"</td>\\n\" .\n+\t\t      \"</tr>\\n\";\n+\t}\n+\tprint \"</table>\\n\";\n+\tgit_footer_html();\n+}\n+\n sub git_summary {\n \tmy $descr = git_read_description($project) || \"none\";\n \tmy $head = git_read_head($project);\n@@ -1326,20 +1479,6 @@ sub git_summary {\n \tgit_footer_html();\n }\n \n-sub git_print_page_path {\n-\tmy $name = shift;\n-\tmy $type = shift;\n-\n-\tif (!defined $name) {\n-\t\tprint \"<div class=\\\"page_path\\\"><b>/</b></div>\\n\";\n-\t} elsif ($type =~ \"blob\") {\n-\t\tprint \"<div class=\\\"page_path\\\"><b>\" .\n-\t\t\t$cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=blob_plain;f=$file_name\")}, esc_html($name)) . \"</b><br/></div>\\n\";\n-\t} else {\n-\t\tprint \"<div class=\\\"page_path\\\"><b>\" . esc_html($name) . \"</b><br/></div>\\n\";\n-\t}\n-}\n-\n sub git_tag {\n \tmy $head = git_read_head($project);\n \tgit_header_html();\n@@ -1546,84 +1685,6 @@ sub git_heads {\n \tgit_footer_html();\n }\n \n-sub git_get_hash_by_path {\n-\tmy $base = shift;\n-\tmy $path = shift || return undef;\n-\n-\tmy $tree = $base;\n-\n-\topen my $fd, \"-|\", $GIT, \"ls-tree\", $base, \"--\", $path\n-\t\tor die_error(undef, \"Open git-ls-tree failed.\");\n-\tmy $line = <$fd>;\n-\tclose $fd or return undef;\n-\n-\t#'100644 blob 0fa3f3a66fb6a137f6ec2c19351ed4d807070ffa\tpanic.c'\n-\t$line =~ m/^([0-9]+) (.+) ([0-9a-fA-F]{40})\\t(.+)$/;\n-\treturn $3;\n-}\n-\n-sub mimetype_guess_file {\n-\tmy $filename = shift;\n-\tmy $mimemap = shift;\n-\t-r $mimemap or return undef;\n-\n-\tmy %mimemap;\n-\topen(MIME, $mimemap) or return undef;\n-\twhile (<MIME>) {\n-\t\tmy ($mime, $exts) = split(/\\t+/);\n-\t\tmy @exts = split(/\\s+/, $exts);\n-\t\tforeach my $ext (@exts) {\n-\t\t\t$mimemap{$ext} = $mime;\n-\t\t}\n-\t}\n-\tclose(MIME);\n-\n-\t$filename =~ /\\.(.*?)$/;\n-\treturn $mimemap{$1};\n-}\n-\n-sub mimetype_guess {\n-\tmy $filename = shift;\n-\tmy $mime;\n-\t$filename =~ /\\./ or return undef;\n-\n-\tif ($mimetypes_file) {\n-\t\tmy $file = $mimetypes_file;\n-\t\t#$file =~ m#^/# or $file = \"$projectroot/$path/$file\";\n-\t\t$mime = mimetype_guess_file($filename, $file);\n-\t}\n-\t$mime ||= mimetype_guess_file($filename, '/etc/mime.types');\n-\treturn $mime;\n-}\n-\n-sub git_blob_plain_mimetype {\n-\tmy $fd = shift;\n-\tmy $filename = shift;\n-\n-\tif ($filename) {\n-\t\tmy $mime = mimetype_guess($filename);\n-\t\t$mime and return $mime;\n-\t}\n-\n-\t# just in case\n-\treturn $default_blob_plain_mimetype unless $fd;\n-\n-\tif (-T $fd) {\n-\t\treturn 'text/plain' .\n-\t\t       ($default_text_plain_charset ? '; charset='.$default_text_plain_charset : '');\n-\t} elsif (! $filename) {\n-\t\treturn 'application/octet-stream';\n-\t} elsif ($filename =~ m/\\.png$/i) {\n-\t\treturn 'image/png';\n-\t} elsif ($filename =~ m/\\.gif$/i) {\n-\t\treturn 'image/gif';\n-\t} elsif ($filename =~ m/\\.jpe?g$/i) {\n-\t\treturn 'image/jpeg';\n-\t} else {\n-\t\treturn 'application/octet-stream';\n-\t}\n-}\n-\n sub git_blob_plain {\n \tif (!defined $hash) {\n \t\tif (defined $file_name) {\n@@ -1793,98 +1854,6 @@ #\t\t\t      \" | \" . $cgi->a({-href => \"$my\n \tgit_footer_html();\n }\n \n-sub git_rss {\n-\t# http://www.notestips.com/80256B3A007F2692/1/NAMO5P9UPQ\n-\topen my $fd, \"-|\", $GIT, \"rev-list\", \"--max-count=150\", git_read_head($project) \n-\t\tor die_error(undef, \"Open git-rev-list failed.\");\n-\tmy @revlist = map { chomp; $_ } <$fd>;\n-\tclose $fd or die_error(undef, \"Reading rev-list failed.\");\n-\tprint $cgi->header(-type => 'text/xml', -charset => 'utf-8');\n-\tprint \"<?xml version=\\\"1.0\\\" encoding=\\\"utf-8\\\"?>\\n\".\n-\t      \"<rss version=\\\"2.0\\\" xmlns:content=\\\"http://purl.org/rss/1.0/modules/content/\\\">\\n\";\n-\tprint \"<channel>\\n\";\n-\tprint \"<title>$project</title>\\n\".\n-\t      \"<link>\" . esc_html(\"$my_url?p=$project;a=summary\") . \"</link>\\n\".\n-\t      \"<description>$project log</description>\\n\".\n-\t      \"<language>en</language>\\n\";\n-\n-\tfor (my $i = 0; $i <= $#revlist; $i++) {\n-\t\tmy $commit = $revlist[$i];\n-\t\tmy %co = git_read_commit($commit);\n-\t\t# we read 150, we always show 30 and the ones more recent than 48 hours\n-\t\tif (($i >= 20) && ((time - $co{'committer_epoch'}) > 48*60*60)) {\n-\t\t\tlast;\n-\t\t}\n-\t\tmy %cd = date_str($co{'committer_epoch'});\n-\t\topen $fd, \"-|\", $GIT, \"diff-tree\", '-r', $co{'parent'}, $co{'id'} or next;\n-\t\tmy @difftree = map { chomp; $_ } <$fd>;\n-\t\tclose $fd or next;\n-\t\tprint \"<item>\\n\" .\n-\t\t      \"<title>\" .\n-\t\t      sprintf(\"%d %s %02d:%02d\", $cd{'mday'}, $cd{'month'}, $cd{'hour'}, $cd{'minute'}) . \" - \" . esc_html($co{'title'}) .\n-\t\t      \"</title>\\n\" .\n-\t\t      \"<author>\" . esc_html($co{'author'}) . \"</author>\\n\" .\n-\t\t      \"<pubDate>$cd{'rfc2822'}</pubDate>\\n\" .\n-\t\t      \"<guid isPermaLink=\\\"true\\\">\" . esc_html(\"$my_url?p=$project;a=commit;h=$commit\") . \"</guid>\\n\" .\n-\t\t      \"<link>\" . esc_html(\"$my_url?p=$project;a=commit;h=$commit\") . \"</link>\\n\" .\n-\t\t      \"<description>\" . esc_html($co{'title'}) . \"</description>\\n\" .\n-\t\t      \"<content:encoded>\" .\n-\t\t      \"<![CDATA[\\n\";\n-\t\tmy $comment = $co{'comment'};\n-\t\tforeach my $line (@$comment) {\n-\t\t\t$line = decode(\"utf8\", $line, Encode::FB_DEFAULT);\n-\t\t\tprint \"$line<br/>\\n\";\n-\t\t}\n-\t\tprint \"<br/>\\n\";\n-\t\tforeach my $line (@difftree) {\n-\t\t\tif (!($line =~ m/^:([0-7]{6}) ([0-7]{6}) ([0-9a-fA-F]{40}) ([0-9a-fA-F]{40}) (.)([0-9]{0,3})\\t(.*)$/)) {\n-\t\t\t\tnext;\n-\t\t\t}\n-\t\t\tmy $file = validate_input(unquote($7));\n-\t\t\t$file = decode(\"utf8\", $file, Encode::FB_DEFAULT);\n-\t\t\tprint \"$file<br/>\\n\";\n-\t\t}\n-\t\tprint \"]]>\\n\" .\n-\t\t      \"</content:encoded>\\n\" .\n-\t\t      \"</item>\\n\";\n-\t}\n-\tprint \"</channel></rss>\";\n-}\n-\n-sub git_opml {\n-\tmy @list = git_read_projects();\n-\n-\tprint $cgi->header(-type => 'text/xml', -charset => 'utf-8');\n-\tprint \"<?xml version=\\\"1.0\\\" encoding=\\\"utf-8\\\"?>\\n\".\n-\t      \"<opml version=\\\"1.0\\\">\\n\".\n-\t      \"<head>\".\n-\t      \"  <title>$site_name Git OPML Export</title>\\n\".\n-\t      \"</head>\\n\".\n-\t      \"<body>\\n\".\n-\t      \"<outline text=\\\"git RSS feeds\\\">\\n\";\n-\n-\tforeach my $pr (@list) {\n-\t\tmy %proj = %$pr;\n-\t\tmy $head = git_read_head($proj{'path'});\n-\t\tif (!defined $head) {\n-\t\t\tnext;\n-\t\t}\n-\t\t$ENV{'GIT_DIR'} = \"$projectroot/$proj{'path'}\";\n-\t\tmy %co = git_read_commit($head);\n-\t\tif (!%co) {\n-\t\t\tnext;\n-\t\t}\n-\n-\t\tmy $path = esc_html(chop_str($proj{'path'}, 25, 5));\n-\t\tmy $rss  = \"$my_url?p=$proj{'path'};a=rss\";\n-\t\tmy $html = \"$my_url?p=$proj{'path'};a=summary\";\n-\t\tprint \"<outline type=\\\"rss\\\" text=\\\"$path\\\" title=\\\"$path\\\" xmlUrl=\\\"$rss\\\" htmlUrl=\\\"$html\\\"/>\\n\";\n-\t}\n-\tprint \"</outline>\\n\".\n-\t      \"</body>\\n\".\n-\t      \"</opml>\\n\";\n-}\n-\n sub git_log {\n \tmy $head = git_read_head($project);\n \tif (!defined $hash) {\n@@ -2556,3 +2525,98 @@ sub git_shortlog {\n \n \tgit_footer_html();\n }\n+\n+## ......................................................................\n+## feeds (RSS, OPML)\n+\n+sub git_rss {\n+\t# http://www.notestips.com/80256B3A007F2692/1/NAMO5P9UPQ\n+\topen my $fd, \"-|\", $GIT, \"rev-list\", \"--max-count=150\", git_read_head($project)\n+\t\tor die_error(undef, \"Open git-rev-list failed.\");\n+\tmy @revlist = map { chomp; $_ } <$fd>;\n+\tclose $fd or die_error(undef, \"Reading rev-list failed.\");\n+\tprint $cgi->header(-type => 'text/xml', -charset => 'utf-8');\n+\tprint \"<?xml version=\\\"1.0\\\" encoding=\\\"utf-8\\\"?>\\n\".\n+\t      \"<rss version=\\\"2.0\\\" xmlns:content=\\\"http://purl.org/rss/1.0/modules/content/\\\">\\n\";\n+\tprint \"<channel>\\n\";\n+\tprint \"<title>$project</title>\\n\".\n+\t      \"<link>\" . esc_html(\"$my_url?p=$project;a=summary\") . \"</link>\\n\".\n+\t      \"<description>$project log</description>\\n\".\n+\t      \"<language>en</language>\\n\";\n+\n+\tfor (my $i = 0; $i <= $#revlist; $i++) {\n+\t\tmy $commit = $revlist[$i];\n+\t\tmy %co = git_read_commit($commit);\n+\t\t# we read 150, we always show 30 and the ones more recent than 48 hours\n+\t\tif (($i >= 20) && ((time - $co{'committer_epoch'}) > 48*60*60)) {\n+\t\t\tlast;\n+\t\t}\n+\t\tmy %cd = date_str($co{'committer_epoch'});\n+\t\topen $fd, \"-|\", $GIT, \"diff-tree\", '-r', $co{'parent'}, $co{'id'} or next;\n+\t\tmy @difftree = map { chomp; $_ } <$fd>;\n+\t\tclose $fd or next;\n+\t\tprint \"<item>\\n\" .\n+\t\t      \"<title>\" .\n+\t\t      sprintf(\"%d %s %02d:%02d\", $cd{'mday'}, $cd{'month'}, $cd{'hour'}, $cd{'minute'}) . \" - \" . esc_html($co{'title'}) .\n+\t\t      \"</title>\\n\" .\n+\t\t      \"<author>\" . esc_html($co{'author'}) . \"</author>\\n\" .\n+\t\t      \"<pubDate>$cd{'rfc2822'}</pubDate>\\n\" .\n+\t\t      \"<guid isPermaLink=\\\"true\\\">\" . esc_html(\"$my_url?p=$project;a=commit;h=$commit\") . \"</guid>\\n\" .\n+\t\t      \"<link>\" . esc_html(\"$my_url?p=$project;a=commit;h=$commit\") . \"</link>\\n\" .\n+\t\t      \"<description>\" . esc_html($co{'title'}) . \"</description>\\n\" .\n+\t\t      \"<content:encoded>\" .\n+\t\t      \"<![CDATA[\\n\";\n+\t\tmy $comment = $co{'comment'};\n+\t\tforeach my $line (@$comment) {\n+\t\t\t$line = decode(\"utf8\", $line, Encode::FB_DEFAULT);\n+\t\t\tprint \"$line<br/>\\n\";\n+\t\t}\n+\t\tprint \"<br/>\\n\";\n+\t\tforeach my $line (@difftree) {\n+\t\t\tif (!($line =~ m/^:([0-7]{6}) ([0-7]{6}) ([0-9a-fA-F]{40}) ([0-9a-fA-F]{40}) (.)([0-9]{0,3})\\t(.*)$/)) {\n+\t\t\t\tnext;\n+\t\t\t}\n+\t\t\tmy $file = validate_input(unquote($7));\n+\t\t\t$file = decode(\"utf8\", $file, Encode::FB_DEFAULT);\n+\t\t\tprint \"$file<br/>\\n\";\n+\t\t}\n+\t\tprint \"]]>\\n\" .\n+\t\t      \"</content:encoded>\\n\" .\n+\t\t      \"</item>\\n\";\n+\t}\n+\tprint \"</channel></rss>\";\n+}\n+\n+sub git_opml {\n+\tmy @list = git_read_projects();\n+\n+\tprint $cgi->header(-type => 'text/xml', -charset => 'utf-8');\n+\tprint \"<?xml version=\\\"1.0\\\" encoding=\\\"utf-8\\\"?>\\n\".\n+\t      \"<opml version=\\\"1.0\\\">\\n\".\n+\t      \"<head>\".\n+\t      \"  <title>$site_name Git OPML Export</title>\\n\".\n+\t      \"</head>\\n\".\n+\t      \"<body>\\n\".\n+\t      \"<outline text=\\\"git RSS feeds\\\">\\n\";\n+\n+\tforeach my $pr (@list) {\n+\t\tmy %proj = %$pr;\n+\t\tmy $head = git_read_head($proj{'path'});\n+\t\tif (!defined $head) {\n+\t\t\tnext;\n+\t\t}\n+\t\t$ENV{'GIT_DIR'} = \"$projectroot/$proj{'path'}\";\n+\t\tmy %co = git_read_commit($head);\n+\t\tif (!%co) {\n+\t\t\tnext;\n+\t\t}\n+\n+\t\tmy $path = esc_html(chop_str($proj{'path'}, 25, 5));\n+\t\tmy $rss  = \"$my_url?p=$proj{'path'};a=rss\";\n+\t\tmy $html = \"$my_url?p=$proj{'path'};a=summary\";\n+\t\tprint \"<outline type=\\\"rss\\\" text=\\\"$path\\\" title=\\\"$path\\\" xmlUrl=\\\"$rss\\\" htmlUrl=\\\"$html\\\"/>\\n\";\n+\t}\n+\tprint \"</outline>\\n\".\n+\t      \"</body>\\n\".\n+\t      \"</opml>\\n\";\n+}\n-- \n1.4.1.1\n"},{"id":"24462","messageId":"E1G7faj-0006W8-17@moooo.ath.cx","threadId":"5038","inReplyTo":"200607292239.11034.jnareb@gmail.com","subject":"[PATCH] gitweb: use a hash to lookup the sub for an action","fromName":"Matthias Lederhofer","fromEmail":"matled@gmx.net","sentAt":"2006-07-31T21:46:25Z","receivedAt":"2006-07-31T21:46:25Z","isPatch":true,"sender":{"key":"matled@gmx.net","avatar":null},"body":"Signed-off-by: Matthias Lederhofer <matled@gmx.net>\n---\n gitweb/gitweb.cgi |   81 ++++++++++++++++-------------------------------------\n 1 files changed, 25 insertions(+), 56 deletions(-)\n\ndiff --git a/gitweb/gitweb.cgi b/gitweb/gitweb.cgi\nindex c1ee79e..75390c8 100755\n--- a/gitweb/gitweb.cgi\n+++ b/gitweb/gitweb.cgi\n@@ -161,65 +161,34 @@ if (defined $searchtext) {\n }\n \n # dispatch\n-if (!defined $action || $action eq \"summary\") {\n-\tgit_summary();\n-\texit;\n-} elsif ($action eq \"heads\") {\n-\tgit_heads();\n-\texit;\n-} elsif ($action eq \"tags\") {\n-\tgit_tags();\n-\texit;\n-} elsif ($action eq \"blob\") {\n-\tgit_blob();\n-\texit;\n-} elsif ($action eq \"blob_plain\") {\n-\tgit_blob_plain();\n-\texit;\n-} elsif ($action eq \"tree\") {\n-\tgit_tree();\n-\texit;\n-} elsif ($action eq \"rss\") {\n-\tgit_rss();\n-\texit;\n-} elsif ($action eq \"commit\") {\n-\tgit_commit();\n-\texit;\n-} elsif ($action eq \"log\") {\n-\tgit_log();\n-\texit;\n-} elsif ($action eq \"blobdiff\") {\n-\tgit_blobdiff();\n-\texit;\n-} elsif ($action eq \"blobdiff_plain\") {\n-\tgit_blobdiff_plain();\n-\texit;\n-} elsif ($action eq \"commitdiff\") {\n-\tgit_commitdiff();\n-\texit;\n-} elsif ($action eq \"commitdiff_plain\") {\n-\tgit_commitdiff_plain();\n-\texit;\n-} elsif ($action eq \"history\") {\n-\tgit_history();\n-\texit;\n-} elsif ($action eq \"search\") {\n-\tgit_search();\n-\texit;\n-} elsif ($action eq \"shortlog\") {\n-\tgit_shortlog();\n-\texit;\n-} elsif ($action eq \"tag\") {\n-\tgit_tag();\n-\texit;\n-} elsif ($action eq \"blame\") {\n-\tgit_blame2();\n-\texit;\n-} else {\n+my %actions = (\n+\t\"blame\" => \\&git_blame2,\n+\t\"blobdiff\" => \\&git_blobdiff,\n+\t\"blobdiff_plain\" => \\&git_blobdiff_plain,\n+\t\"blob\" => \\&git_blob,\n+\t\"blob_plain\" => \\&git_blob_plain,\n+\t\"commitdiff\" => \\&git_commitdiff,\n+\t\"commitdiff_plain\" => \\&git_commitdiff_plain,\n+\t\"commit\" => \\&git_commit,\n+\t\"heads\" => \\&git_heads,\n+\t\"history\" => \\&git_history,\n+\t\"log\" => \\&git_log,\n+\t\"rss\" => \\&git_rss,\n+\t\"search\" => \\&git_search,\n+\t\"shortlog\" => \\&git_shortlog,\n+\t\"summary\" => \\&git_summary,\n+\t\"tag\" => \\&git_tag,\n+\t\"tags\" => \\&git_tags,\n+\t\"tree\" => \\&git_tree,\n+);\n+\n+$action = 'summary' if (!defined($action));\n+if (!defined($actions{$action})) {\n \tundef $action;\n \tdie_error(undef, \"Unknown action.\");\n-\texit;\n }\n+$actions{$action}->();\n+exit;\n \n ## ======================================================================\n ## validation, quoting/unquoting and escaping\n-- \n1.4.2.rc2.ge0bed\n"},{"id":"24467","messageId":"7v3bch5rha.fsf@assigned-by-dhcp.cox.net","threadId":"5038","inReplyTo":"E1G7faj-0006W8-17@moooo.ath.cx","subject":"Re: [PATCH] gitweb: use a hash to lookup the sub for an action","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-07-31T22:39:29Z","receivedAt":"2006-07-31T22:39:29Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Matthias Lederhofer <matled@gmx.net> writes:\n\n> Signed-off-by: Matthias Lederhofer <matled@gmx.net>\n\nYeah, finally.  I like this.\n"},{"id":"24468","messageId":"eam1nq$d6r$1@sea.gmane.org","threadId":"5038","inReplyTo":"E1G7faj-0006W8-17@moooo.ath.cx","subject":"Re: [PATCH 21] gitweb: use a hash to lookup the sub for an action","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-07-31T22:55:09Z","receivedAt":"2006-07-31T22:55:09Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Matthias Lederhofer wrote:\n\n> Signed-off-by: Matthias Lederhofer <matled@gmx.net>\n\nAcked-by: Jakub Narebski <jnareb@gmail.com>\n\n-- \nJakub Narebski\nWarsaw, Poland\nShadeHawk on #git\n"},{"id":"24473","messageId":"200608010259.13721.jnareb@gmail.com","threadId":"5038","inReplyTo":"200607292239.11034.jnareb@gmail.com","subject":"[PATCH 22]","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-08-01T00:59:12Z","receivedAt":"2006-08-01T00:59:12Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":">From d69d3357f134bb5548f18fafff7664499adc1fcd Mon Sep 17 00:00:00 2001\nFrom: Jakub Narebski <jnareb@gmail.com>\nDate: Tue, 1 Aug 2006 02:56:51 +0200\nSubject: [PATCH] gitweb: Refactoring git_project_list\n\nSlightly reworking git_project_list, including moving setting $order,\nas it is used only in this action. Mostly reindent.\n\nSigned-off-by: Jakub Narebski <jnareb@gmail.com>\n---\nAfter Matthias Lederhofer <matled@gmx.net> patch,\n\"[PATCH] gitweb: use a hash to lookup the sub for an action\"\n\n gitweb/gitweb.cgi |   57 +++++++++++++++++++++++++++++++++--------------------\n 1 files changed, 35 insertions(+), 22 deletions(-)\n\ndiff --git a/gitweb/gitweb.cgi b/gitweb/gitweb.cgi\nindex 75390c8..27c36ef 100755\n--- a/gitweb/gitweb.cgi\n+++ b/gitweb/gitweb.cgi\n@@ -80,14 +80,6 @@ if (defined $action) {\n \t}\n }\n \n-our $order = $cgi->param('o');\n-if (defined $order) {\n-\tif ($order =~ m/[^0-9a-zA-Z_]/) {\n-\t\tundef $order;\n-\t\tdie_error(undef, \"Invalid order parameter.\");\n-\t}\n-}\n-\n our $project = ($cgi->param('p') || $ENV{'PATH_INFO'});\n if (defined $project) {\n \t$project =~ s|^/||; $project =~ s|/$||;\n@@ -1303,10 +1295,15 @@ sub git_logo {\n }\n \n sub git_project_list {\n+\tmy $order = $cgi->param('o');\n+\tif (defined $order && $order !~ m/project|descr|owner|age/) {\n+\t\tdie_error(undef, \"Invalid order parameter '$order'.\");\n+\t}\n+\n \tmy @list = git_read_projects();\n \tmy @projects;\n \tif (!@list) {\n-\t\tdie_error(undef, \"No project found.\");\n+\t\tdie_error(undef, \"No projects found.\");\n \t}\n \tforeach my $pr (@list) {\n \t\tmy $head = git_read_head($pr->{'path'});\n@@ -1328,6 +1325,7 @@ sub git_project_list {\n \t\t}\n \t\tpush @projects, $pr;\n \t}\n+\n \tgit_header_html();\n \tif (-f $home_text) {\n \t\tprint \"<div class=\\\"index_include\\\">\\n\";\n@@ -1338,29 +1336,42 @@ sub git_project_list {\n \t}\n \tprint \"<table class=\\\"project_list\\\">\\n\" .\n \t      \"<tr>\\n\";\n-\tif (!defined($order) || (defined($order) && ($order eq \"project\"))) {\n+\t$order ||= \"project\";\n+\tif ($order eq \"project\") {\n \t\t@projects = sort {$a->{'path'} cmp $b->{'path'}} @projects;\n \t\tprint \"<th>Project</th>\\n\";\n \t} else {\n-\t\tprint \"<th>\" . $cgi->a({-class => \"header\", -href => \"$my_uri?\" . esc_param(\"o=project\")}, \"Project\") . \"</th>\\n\";\n+\t\tprint \"<th>\" .\n+\t\t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"o=project\"),\n+\t\t               -class => \"header\"}, \"Project\") .\n+\t\t      \"</th>\\n\";\n \t}\n-\tif (defined($order) && ($order eq \"descr\")) {\n+\tif ($order eq \"descr\") {\n \t\t@projects = sort {$a->{'descr'} cmp $b->{'descr'}} @projects;\n \t\tprint \"<th>Description</th>\\n\";\n \t} else {\n-\t\tprint \"<th>\" . $cgi->a({-class => \"header\", -href => \"$my_uri?\" . esc_param(\"o=descr\")}, \"Description\") . \"</th>\\n\";\n+\t\tprint \"<th>\" .\n+\t\t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"o=descr\"),\n+\t\t               -class => \"header\"}, \"Description\") .\n+\t\t      \"</th>\\n\";\n \t}\n-\tif (defined($order) && ($order eq \"owner\")) {\n+\tif ($order eq \"owner\") {\n \t\t@projects = sort {$a->{'owner'} cmp $b->{'owner'}} @projects;\n \t\tprint \"<th>Owner</th>\\n\";\n \t} else {\n-\t\tprint \"<th>\" . $cgi->a({-class => \"header\", -href => \"$my_uri?\" . esc_param(\"o=owner\")}, \"Owner\") . \"</th>\\n\";\n+\t\tprint \"<th>\" .\n+\t\t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"o=owner\"),\n+\t\t               -class => \"header\"}, \"Owner\") .\n+\t\t      \"</th>\\n\";\n \t}\n-\tif (defined($order) && ($order eq \"age\")) {\n+\tif ($order eq \"age\") {\n \t\t@projects = sort {$a->{'commit'}{'age'} <=> $b->{'commit'}{'age'}} @projects;\n \t\tprint \"<th>Last Change</th>\\n\";\n \t} else {\n-\t\tprint \"<th>\" . $cgi->a({-class => \"header\", -href => \"$my_uri?\" . esc_param(\"o=age\")}, \"Last Change\") . \"</th>\\n\";\n+\t\tprint \"<th>\" .\n+\t\t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"o=age\"),\n+\t\t               -class => \"header\"}, \"Last Change\") .\n+\t\t      \"</th>\\n\";\n \t}\n \tprint \"<th></th>\\n\" .\n \t      \"</tr>\\n\";\n@@ -1372,14 +1383,16 @@ sub git_project_list {\n \t\t\tprint \"<tr class=\\\"light\\\">\\n\";\n \t\t}\n \t\t$alternate ^= 1;\n-\t\tprint \"<td>\" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$pr->{'path'};a=summary\"), -class => \"list\"}, esc_html($pr->{'path'})) . \"</td>\\n\" .\n+\t\tprint \"<td>\" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$pr->{'path'};a=summary\"),\n+\t\t                        -class => \"list\"}, esc_html($pr->{'path'})) . \"</td>\\n\" .\n \t\t      \"<td>\" . esc_html($pr->{'descr'}) . \"</td>\\n\" .\n \t\t      \"<td><i>\" . chop_str($pr->{'owner'}, 15) . \"</i></td>\\n\";\n-\t\tprint \"<td class=\\\"\". age_class($pr->{'commit'}{'age'}) . \"\\\">\" . $pr->{'commit'}{'age_string'} . \"</td>\\n\" .\n+\t\tprint \"<td class=\\\"\". age_class($pr->{'commit'}{'age'}) . \"\\\">\" .\n+\t\t      $pr->{'commit'}{'age_string'} . \"</td>\\n\" .\n \t\t      \"<td class=\\\"link\\\">\" .\n-\t\t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$pr->{'path'};a=summary\")}, \"summary\") .\n-\t\t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$pr->{'path'};a=shortlog\")}, \"shortlog\") .\n-\t\t      \" | \" . $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$pr->{'path'};a=log\")}, \"log\") .\n+\t\t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$pr->{'path'};a=summary\")}, \"summary\")   . \" | \" .\n+\t\t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$pr->{'path'};a=shortlog\")}, \"shortlog\") . \" | \" .\n+\t\t      $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$pr->{'path'};a=log\")}, \"log\") .\n \t\t      \"</td>\\n\" .\n \t\t      \"</tr>\\n\";\n \t}\n-- \n1.4.1.1\n"},{"id":"24477","messageId":"7vlkq94325.fsf_-_@assigned-by-dhcp.cox.net","threadId":"5038","inReplyTo":"200608010259.13721.jnareb@gmail.com","subject":"Perhaps an obvious cut and paste error.","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-08-01T02:12:18Z","receivedAt":"2006-08-01T02:12:18Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"diff --git a/gitweb/gitweb.cgi b/gitweb/gitweb.cgi\nindex 4e79390..a4a46d9 100755\n--- a/gitweb/gitweb.cgi\n+++ b/gitweb/gitweb.cgi\n@@ -1441,7 +1434,7 @@ sub git_summary {\n \tmy $headlist = git_read_refs(\"refs/heads\");\n \tif (defined @$headlist) {\n \t\tgit_header_div('heads');\n-\t\tgit_heads_body($taglist, $head, 0, 15,\n+\t\tgit_heads_body($headlist, $head, 0, 15,\n \t\t               $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=heads\")}, \"...\"));\n \t}\n \n"},{"id":"24479","messageId":"7vhd0x42u3.fsf@assigned-by-dhcp.cox.net","threadId":"5038","inReplyTo":"ealk0e$to2$2@sea.gmane.org","subject":"Re: [PATCH 19] gitweb: No need to quote path for list version of open \"-|\"","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-08-01T02:17:08Z","receivedAt":"2006-08-01T02:17:08Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jakub Narebski <jnareb@gmail.com> writes:\n\n> <opublikowany i wysłany>\n>\n> Junio C Hamano wrote:\n>\n>> I suspect the patch title is wrong -- it is not \"no need to\" but\n>> \"quoting path breaks so do not do it\" ;-).\n>> \n>> I guess this fixes the problem I saw last night?\n>\n> If I remember correctly it worked without this patch, for git 1.4.1.1 \n> (i.e. with --full-history option, although not working as advertised: see my\n> comment earlier in thread).\n\nCouldn't have worked, or you have found a bug in whatever\ncommand you invoked.  If it is told to look for a path that\nstarts with a single quote it should have done so and produced\nno history since there is no such file.\n\nIn any case, the patch #19 seems to fix the problem.  Thanks.\n"},{"id":"24480","messageId":"7vac6p42rp.fsf_-_@assigned-by-dhcp.cox.net","threadId":"5038","inReplyTo":"ealk0e$to2$2@sea.gmane.org","subject":"There can be more than two levels of subdirectories","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-08-01T02:18:34Z","receivedAt":"2006-08-01T02:18:34Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Earlier code to read .git/refs/{tags,heads} hierarchy had a\nhardcoded up-to-two-level assumption.  Lift it by using\nFile::Find.\n\nSigned-off-by: Junio C Hamano <junkio@cox.net>\n\n---\ndiff --git a/gitweb/gitweb.cgi b/gitweb/gitweb.cgi\nindex 4e79390..902b96a 100755\n--- a/gitweb/gitweb.cgi\n+++ b/gitweb/gitweb.cgi\n@@ -14,6 +14,7 @@ use CGI::Util qw(unescape);\n use CGI::Carp qw(fatalsToBrowser);\n use Encode;\n use Fcntl ':mode';\n+use File::Find qw();\n binmode STDOUT, ':utf8';\n \n our $cgi = new CGI;\n@@ -697,23 +698,14 @@ sub git_read_refs {\n \tmy @reflist;\n \n \tmy @refs;\n-\topendir my $dh, \"$projectroot/$project/$ref_dir\";\n-\twhile (my $dir = readdir($dh)) {\n-\t\tif ($dir =~ m/^\\./) {\n-\t\t\tnext;\n-\t\t}\n-\t\tif (-d \"$projectroot/$project/$ref_dir/$dir\") {\n-\t\t\topendir my $dh2, \"$projectroot/$project/$ref_dir/$dir\";\n-\t\t\tmy @subdirs = grep !m/^\\./, readdir $dh2;\n-\t\t\tclosedir($dh2);\n-\t\t\tforeach my $subdir (@subdirs) {\n-\t\t\t\tpush @refs, \"$dir/$subdir\"\n-\t\t\t}\n-\t\t\tnext;\n+\tmy $pfxlen = length(\"$projectroot/$project/$ref_dir\");\n+\tFile::Find::find(sub {\n+\t\treturn if (/^\\./);\n+\t\tif (-f $_) {\n+\t\t\tpush @refs, substr($File::Find::name, $pfxlen + 1);\n \t\t}\n-\t\tpush @refs, $dir;\n-\t}\n-\tclosedir($dh);\n+\t}, \"$projectroot/$project/$ref_dir\");\n+\n \tforeach my $ref_file (@refs) {\n \t\tmy $ref_id = git_read_hash(\"$project/$ref_dir/$ref_file\");\n \t\tmy $type = git_get_type($ref_id) || next;\n"},{"id":"24483","messageId":"20060801025029.21850.qmail@web31802.mail.mud.yahoo.com","threadId":"5038","inReplyTo":"E1G7faj-0006W8-17@moooo.ath.cx","subject":"Re: [PATCH] gitweb: use a hash to lookup the sub for an action","fromName":"Luben Tuikov","fromEmail":"ltuikov@yahoo.com","sentAt":"2006-08-01T02:50:29Z","receivedAt":"2006-08-01T02:50:29Z","isPatch":true,"sender":{"key":"ltuikov@yahoo.com","avatar":null},"body":"--- Matthias Lederhofer <matled@gmx.net> wrote:\n> Signed-off-by: Matthias Lederhofer <matled@gmx.net>\n\nThat's a great patch.\n\n   Luben\n\n> ---\n>  gitweb/gitweb.cgi |   81 ++++++++++++++++-------------------------------------\n>  1 files changed, 25 insertions(+), 56 deletions(-)\n> \n> diff --git a/gitweb/gitweb.cgi b/gitweb/gitweb.cgi\n> index c1ee79e..75390c8 100755\n> --- a/gitweb/gitweb.cgi\n> +++ b/gitweb/gitweb.cgi\n> @@ -161,65 +161,34 @@ if (defined $searchtext) {\n>  }\n>  \n>  # dispatch\n> -if (!defined $action || $action eq \"summary\") {\n> -\tgit_summary();\n> -\texit;\n> -} elsif ($action eq \"heads\") {\n> -\tgit_heads();\n> -\texit;\n> -} elsif ($action eq \"tags\") {\n> -\tgit_tags();\n> -\texit;\n> -} elsif ($action eq \"blob\") {\n> -\tgit_blob();\n> -\texit;\n> -} elsif ($action eq \"blob_plain\") {\n> -\tgit_blob_plain();\n> -\texit;\n> -} elsif ($action eq \"tree\") {\n> -\tgit_tree();\n> -\texit;\n> -} elsif ($action eq \"rss\") {\n> -\tgit_rss();\n> -\texit;\n> -} elsif ($action eq \"commit\") {\n> -\tgit_commit();\n> -\texit;\n> -} elsif ($action eq \"log\") {\n> -\tgit_log();\n> -\texit;\n> -} elsif ($action eq \"blobdiff\") {\n> -\tgit_blobdiff();\n> -\texit;\n> -} elsif ($action eq \"blobdiff_plain\") {\n> -\tgit_blobdiff_plain();\n> -\texit;\n> -} elsif ($action eq \"commitdiff\") {\n> -\tgit_commitdiff();\n> -\texit;\n> -} elsif ($action eq \"commitdiff_plain\") {\n> -\tgit_commitdiff_plain();\n> -\texit;\n> -} elsif ($action eq \"history\") {\n> -\tgit_history();\n> -\texit;\n> -} elsif ($action eq \"search\") {\n> -\tgit_search();\n> -\texit;\n> -} elsif ($action eq \"shortlog\") {\n> -\tgit_shortlog();\n> -\texit;\n> -} elsif ($action eq \"tag\") {\n> -\tgit_tag();\n> -\texit;\n> -} elsif ($action eq \"blame\") {\n> -\tgit_blame2();\n> -\texit;\n> -} else {\n> +my %actions = (\n> +\t\"blame\" => \\&git_blame2,\n> +\t\"blobdiff\" => \\&git_blobdiff,\n> +\t\"blobdiff_plain\" => \\&git_blobdiff_plain,\n> +\t\"blob\" => \\&git_blob,\n> +\t\"blob_plain\" => \\&git_blob_plain,\n> +\t\"commitdiff\" => \\&git_commitdiff,\n> +\t\"commitdiff_plain\" => \\&git_commitdiff_plain,\n> +\t\"commit\" => \\&git_commit,\n> +\t\"heads\" => \\&git_heads,\n> +\t\"history\" => \\&git_history,\n> +\t\"log\" => \\&git_log,\n> +\t\"rss\" => \\&git_rss,\n> +\t\"search\" => \\&git_search,\n> +\t\"shortlog\" => \\&git_shortlog,\n> +\t\"summary\" => \\&git_summary,\n> +\t\"tag\" => \\&git_tag,\n> +\t\"tags\" => \\&git_tags,\n> +\t\"tree\" => \\&git_tree,\n> +);\n> +\n> +$action = 'summary' if (!defined($action));\n> +if (!defined($actions{$action})) {\n>  \tundef $action;\n>  \tdie_error(undef, \"Unknown action.\");\n> -\texit;\n>  }\n> +$actions{$action}->();\n> +exit;\n>  \n>  ## ======================================================================\n>  ## validation, quoting/unquoting and escaping\n> -- \n> 1.4.2.rc2.ge0bed\n> \n> -\n> To unsubscribe from this list: send the line \"unsubscribe git\" in\n> the body of a message to majordomo@vger.kernel.org\n> More majordomo info at  http://vger.kernel.org/majordomo-info.html\n> \n"},{"id":"24485","messageId":"7vzmep2icr.fsf_-_@assigned-by-dhcp.cox.net","threadId":"5038","inReplyTo":"200608010259.13721.jnareb@gmail.com","subject":"A few more fixups to gitweb","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-08-01T04:24:52Z","receivedAt":"2006-08-01T04:24:52Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"I've applied most of the recent gitweb changes from the list\n(except the one that processes gitweb.perl into gitweb.cgi, not\nbecause I am opposed to it, but because merging it early would\nmake things a bit more inconvenient while many patches are in\nflight on the list) and fixed up a few things I noticed.  I'll\nbe pushing out the results on \"next\" branch shortly, so if\npeople want to hack on gitweb further please base your changes\non this version (I am CC'ing this message to people who recently\nworked on, or expressed interest in working on gitweb).\n\nOne thing to note.  Please make sure that you do not see\nanything in Apache error log after you make your changes.  I do\nnot remember the details but kernel.org folks were very unhappy\nearlier when gitweb spewed stuff into the error log, and if I\nrecall correctly things that output to the error stream were not\nfriendly to the http-server cache for some reason.\n"},{"id":"24493","messageId":"eamvhf$gfr$1@sea.gmane.org","threadId":"5038","inReplyTo":"7vlkq94325.fsf_-_@assigned-by-dhcp.cox.net","subject":"Re: Perhaps an obvious cut and paste error.","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-08-01T07:23:48Z","receivedAt":"2006-08-01T07:23:48Z","isPatch":false,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Junio C Hamano wrote:\n\n> diff --git a/gitweb/gitweb.cgi b/gitweb/gitweb.cgi\n> index 4e79390..a4a46d9 100755\n> --- a/gitweb/gitweb.cgi\n> +++ b/gitweb/gitweb.cgi\n> @@ -1441,7 +1434,7 @@ sub git_summary {\n>       my $headlist = git_read_refs(\"refs/heads\");\n>       if (defined @$headlist) {\n>               git_header_div('heads');\n> -             git_heads_body($taglist, $head, 0, 15,\n> +             git_heads_body($headlist, $head, 0, 15,\n>                              $cgi->a({-href => \"$my_uri?\" . esc_param(\"p=$project;a=heads\")}, \"...\"));\n>       }\n>  \n> \n\nYes, of course. ACK.\n\n-- \nJakub Narebski\nWarsaw, Poland\nShadeHawk on #git\n"},{"id":"24494","messageId":"ean0a1$irf$1@sea.gmane.org","threadId":"5038","inReplyTo":"7vzmep2icr.fsf_-_@assigned-by-dhcp.cox.net","subject":"Re: A few more fixups to gitweb","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-08-01T07:36:54Z","receivedAt":"2006-08-01T07:36:54Z","isPatch":false,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Junio C Hamano wrote:\n\n> One thing to note.  Please make sure that you do not see\n> anything in Apache error log after you make your changes.  I do\n> not remember the details but kernel.org folks were very unhappy\n> earlier when gitweb spewed stuff into the error log, and if I\n> recall correctly things that output to the error stream were not\n> friendly to the http-server cache for some reason.\n\nBy the way, I wonder why git when cloning/fetching via http protocol\nuses e.g. \"git/1.4.2.rc2.ge0bed\" as User-Agent: string when fetching objects\nand packs, and e.g. \"curl/7.15.4 (i486-pc-linux-gnu) libcurl/7.15.4\nOpenSSL/0.9.8b zlib/1.2.3 libidn/0.6.5\" as User-Agent: when fetching refs\n(heads and tags) and info/refs.\n\n-- \nJakub Narebski\nWarsaw, Poland\nShadeHawk on #git\n"},{"id":"24495","messageId":"7vd5bk3mqo.fsf@assigned-by-dhcp.cox.net","threadId":"5038","inReplyTo":"ean0a1$irf$1@sea.gmane.org","subject":"Re: A few more fixups to gitweb","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-08-01T08:04:47Z","receivedAt":"2006-08-01T08:04:47Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jakub Narebski <jnareb@gmail.com> writes:\n\n> By the way, I wonder why git when cloning/fetching via http protocol\n> uses e.g. \"git/1.4.2.rc2.ge0bed\" as User-Agent: string when fetching objects\n> and packs, and e.g. \"curl/7.15.4 (i486-pc-linux-gnu) libcurl/7.15.4\n> OpenSSL/0.9.8b zlib/1.2.3 libidn/0.6.5\" as User-Agent: when fetching refs\n> (heads and tags) and info/refs.\n\n\"Why?\", meaning if we deliberately do so for some good reason?\n\nThere isn't.\n\ngit-http-fetch uses its own User-Agent string, but the shell\nscript wrappers that use curl executable do not bother setting\ncustomized User-Agent string; that is why.\n"},{"id":"24500","messageId":"200608011134.52006.jnareb@gmail.com","threadId":"5038","inReplyTo":"7vd5bk3mqo.fsf@assigned-by-dhcp.cox.net","subject":"[PATCH 1/2] Use tabs for indent in shell scripts","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-08-01T09:34:48Z","receivedAt":"2006-08-01T09:34:48Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Consistently use tabs for indenting in some shell scripts.  Needs\nchecking for consistency (command1 && command2 && command3 split into\nlines).\n\nSigned-off-by: Jakub Narebski <jnareb@gmail.com>\n---\n git-clone.sh     |   94 +++++-----\n git-fetch.sh     |  493 +++++++++++++++++++++++++++---------------------------\n git-ls-remote.sh |   50 +++--\n 3 files changed, 319 insertions(+), 318 deletions(-)\n\ndiff --git a/git-clone.sh b/git-clone.sh\nindex a92b22a..adb752d 100755\n--- a/git-clone.sh\n+++ b/git-clone.sh\n@@ -18,7 +18,7 @@ get_repo_base() {\n }\n \n if [ -n \"$GIT_SSL_NO_VERIFY\" ]; then\n-    curl_extra_args=\"-k\"\n+\tcurl_extra_args=\"-k\"\n fi\n \n http_fetch () {\n@@ -43,7 +43,7 @@ Perhaps git-update-server-info needs to \n \t\t*^*)\tcontinue;;\n \t\tesac\n \t\tif test -n \"$use_separate_remote\" &&\n-\t\t   branch_name=`expr \"z$name\" : 'zheads/\\(.*\\)'`\n+\t\t\tbranch_name=`expr \"z$name\" : 'zheads/\\(.*\\)'`\n \t\tthen\n \t\t\ttname=\"remotes/$origin/$branch_name\"\n \t\telse\n@@ -119,13 +119,13 @@ while\n \t*,--na|*,--nak|*,--nake|*,--naked|\\\n \t*,-b|*,--b|*,--ba|*,--bar|*,--bare) bare=yes ;;\n \t*,-l|*,--l|*,--lo|*,--loc|*,--loca|*,--local) use_local=yes ;;\n-        *,-s|*,--s|*,--sh|*,--sha|*,--shar|*,--share|*,--shared) \n-          local_shared=yes; use_local=yes ;;\n+\t*,-s|*,--s|*,--sh|*,--sha|*,--shar|*,--share|*,--shared)\n+\t\tlocal_shared=yes; use_local=yes ;;\n \t1,--template) usage ;;\n \t*,--template)\n \t\tshift; template=\"--template=$1\" ;;\n \t*,--template=*)\n-\t  template=\"$1\" ;;\n+\t\ttemplate=\"$1\" ;;\n \t*,-q|*,--quiet) quiet=-q ;;\n \t*,--use-separate-remote)\n \t\tuse_separate_remote=t ;;\n@@ -137,18 +137,18 @@ while\n \t*,-o|*,--or|*,--ori|*,--orig|*,--origi|*,--origin)\n \t\tcase \"$2\" in\n \t\t'')\n-\t\t    usage ;;\n+\t\t\tusage ;;\n \t\t*/*)\n-\t\t    echo >&2 \"'$2' is not suitable for an origin name\"\n-\t\t    exit 1\n+\t\t\techo >&2 \"'$2' is not suitable for an origin name\"\n+\t\t\texit 1\n \t\tesac\n \t\tgit-check-ref-format \"heads/$2\" || {\n-\t\t    echo >&2 \"'$2' is not suitable for a branch name\"\n-\t\t    exit 1\n+\t\t\techo >&2 \"'$2' is not suitable for a branch name\"\n+\t\t\texit 1\n \t\t}\n \t\ttest -z \"$origin_override\" || {\n-\t\t    echo >&2 \"Do not give more than one --origin options.\"\n-\t\t    exit 1\n+\t\t\techo >&2 \"Do not give more than one --origin options.\"\n+\t\t\texit 1\n \t\t}\n \t\torigin_override=yes\n \t\torigin=\"$2\"; shift\n@@ -167,8 +167,8 @@ done\n repo=\"$1\"\n if test -z \"$repo\"\n then\n-    echo >&2 'you must specify a repository to clone.'\n-    exit 1\n+\techo >&2 'you must specify a repository to clone.'\n+\texit 1\n fi\n \n # --bare implies --no-checkout\n@@ -225,9 +225,9 @@ then\n \t\techo \"$reference/objects\" >\"$GIT_DIR/objects/info/alternates\"\n \t\t(cd \"$reference\" && tar cf - refs) |\n \t\t(cd \"$GIT_DIR/refs\" &&\n-\t\t mkdir reference-tmp &&\n-\t\t cd reference-tmp &&\n-\t\t tar xf -)\n+\t\t\tmkdir reference-tmp &&\n+\t\t\tcd reference-tmp &&\n+\t\t\ttar xf -)\n \telse\n \t\techo >&2 \"$reference: not a local directory.\" && usage\n \tfi\n@@ -245,26 +245,26 @@ yes,yes)\n \n \tcase \"$local_shared\" in\n \tno)\n-\t    # See if we can hardlink and drop \"l\" if not.\n-\t    sample_file=$(cd \"$repo\" && \\\n-\t\t\t  find objects -type f -print | sed -e 1q)\n+\t\t# See if we can hardlink and drop \"l\" if not.\n+\t\tsample_file=$(cd \"$repo\" && \\\n+\t\t\tfind objects -type f -print | sed -e 1q)\n \n-\t    # objects directory should not be empty since we are cloning!\n-\t    test -f \"$repo/$sample_file\" || exit\n+\t\t# objects directory should not be empty since we are cloning!\n+\t\ttest -f \"$repo/$sample_file\" || exit\n \n-\t    l=\n-\t    if ln \"$repo/$sample_file\" \"$GIT_DIR/objects/sample\" 2>/dev/null\n-\t    then\n-\t\t    l=l\n-\t    fi &&\n-\t    rm -f \"$GIT_DIR/objects/sample\" &&\n-\t    cd \"$repo\" &&\n-\t    find objects -depth -print | cpio -pumd$l \"$GIT_DIR/\" || exit 1\n-\t    ;;\n+\t\tl=\n+\t\tif ln \"$repo/$sample_file\" \"$GIT_DIR/objects/sample\" 2>/dev/null\n+\t\tthen\n+\t\t\tl=l\n+\t\tfi &&\n+\t\trm -f \"$GIT_DIR/objects/sample\" &&\n+\t\tcd \"$repo\" &&\n+\t\tfind objects -depth -print | cpio -pumd$l \"$GIT_DIR/\" || exit 1\n+\t\t;;\n \tyes)\n-\t    mkdir -p \"$GIT_DIR/objects/info\"\n-\t    echo \"$repo/objects\" >> \"$GIT_DIR/objects/info/alternates\"\n-\t    ;;\n+\t\tmkdir -p \"$GIT_DIR/objects/info\"\n+\t\techo \"$repo/objects\" >> \"$GIT_DIR/objects/info/alternates\"\n+\t\t;;\n \tesac\n \tgit-ls-remote \"$repo\" >\"$GIT_DIR/CLONE_HEAD\" || exit 1\n \t;;\n@@ -282,19 +282,19 @@ yes,yes)\n \t\t\trm -f \"$GIT_DIR/TMP_ALT\"\n \t\tif test -f \"$GIT_DIR/TMP_ALT\"\n \t\tthen\n-\t\t    ( cd \"$D\" &&\n-\t\t      . git-parse-remote &&\n-\t\t      resolve_alternates \"$repo\" <\"$GIT_DIR/TMP_ALT\" ) |\n-\t\t    while read alt\n-\t\t    do\n-\t\t\tcase \"$alt\" in 'bad alternate: '*) die \"$alt\";; esac\n-\t\t\tcase \"$quiet\" in\n-\t\t\t'')\techo >&2 \"Getting alternate: $alt\" ;;\n-\t\t\tesac\n-\t\t\trsync $quiet -av --ignore-existing  \\\n-\t\t\t    --exclude info \"$alt\" \"$GIT_DIR/objects\" || exit\n-\t\t    done\n-\t\t    rm -f \"$GIT_DIR/TMP_ALT\"\n+\t\t\t( cd \"$D\" &&\n+\t\t\t\t. git-parse-remote &&\n+\t\t\t\tresolve_alternates \"$repo\" <\"$GIT_DIR/TMP_ALT\" ) |\n+\t\t\twhile read alt\n+\t\t\tdo\n+\t\t\t\tcase \"$alt\" in 'bad alternate: '*) die \"$alt\";; esac\n+\t\t\t\tcase \"$quiet\" in\n+\t\t\t\t'')\techo >&2 \"Getting alternate: $alt\" ;;\n+\t\t\t\tesac\n+\t\t\t\trsync $quiet -av --ignore-existing  \\\n+\t\t\t\t\t--exclude info \"$alt\" \"$GIT_DIR/objects\" || exit\n+\t\t\tdone\n+\t\t\trm -f \"$GIT_DIR/TMP_ALT\"\n \t\tfi\n \t\tgit-ls-remote \"$repo\" >\"$GIT_DIR/CLONE_HEAD\" || exit 1\n \t\t;;\ndiff --git a/git-fetch.sh b/git-fetch.sh\nindex c2eebee..cea6e0b 100755\n--- a/git-fetch.sh\n+++ b/git-fetch.sh\n@@ -90,124 +90,124 @@ then\n fi\n \n append_fetch_head () {\n-    head_=\"$1\"\n-    remote_=\"$2\"\n-    remote_name_=\"$3\"\n-    remote_nick_=\"$4\"\n-    local_name_=\"$5\"\n-    case \"$6\" in\n-    t) not_for_merge_='not-for-merge' ;;\n-    '') not_for_merge_= ;;\n-    esac\n+\thead_=\"$1\"\n+\tremote_=\"$2\"\n+\tremote_name_=\"$3\"\n+\tremote_nick_=\"$4\"\n+\tlocal_name_=\"$5\"\n+\tcase \"$6\" in\n+\t\tt) not_for_merge_='not-for-merge' ;;\n+\t\t'') not_for_merge_= ;;\n+\tesac\n \n-    # remote-nick is the URL given on the command line (or a shorthand)\n-    # remote-name is the $GIT_DIR relative refs/ path we computed\n-    # for this refspec.\n+\t# remote-nick is the URL given on the command line (or a shorthand)\n+\t# remote-name is the $GIT_DIR relative refs/ path we computed\n+\t# for this refspec.\n \n-    # the $note_ variable will be fed to git-fmt-merge-msg for further\n-    # processing.\n-    case \"$remote_name_\" in\n-    HEAD)\n-\tnote_= ;;\n-    refs/heads/*)\n-\tnote_=\"$(expr \"$remote_name_\" : 'refs/heads/\\(.*\\)')\"\n-\tnote_=\"branch '$note_' of \" ;;\n-    refs/tags/*)\n-\tnote_=\"$(expr \"$remote_name_\" : 'refs/tags/\\(.*\\)')\"\n-\tnote_=\"tag '$note_' of \" ;;\n-    refs/remotes/*)\n-\tnote_=\"$(expr \"$remote_name_\" : 'refs/remotes/\\(.*\\)')\"\n-\tnote_=\"remote branch '$note_' of \" ;;\n-    *)\n-\tnote_=\"$remote_name of \" ;;\n-    esac\n-    remote_1_=$(expr \"z$remote_\" : 'z\\(.*\\)\\.git/*$') &&\n+\t# the $note_ variable will be fed to git-fmt-merge-msg for further\n+\t# processing.\n+\tcase \"$remote_name_\" in\n+\tHEAD)\n+\t\tnote_= ;;\n+\trefs/heads/*)\n+\t\tnote_=\"$(expr \"$remote_name_\" : 'refs/heads/\\(.*\\)')\"\n+\t\tnote_=\"branch '$note_' of \" ;;\n+\trefs/tags/*)\n+\t\tnote_=\"$(expr \"$remote_name_\" : 'refs/tags/\\(.*\\)')\"\n+\t\tnote_=\"tag '$note_' of \" ;;\n+\trefs/remotes/*)\n+\t\tnote_=\"$(expr \"$remote_name_\" : 'refs/remotes/\\(.*\\)')\"\n+\t\tnote_=\"remote branch '$note_' of \" ;;\n+\t*)\n+\t\tnote_=\"$remote_name of \" ;;\n+\tesac\n+\tremote_1_=$(expr \"z$remote_\" : 'z\\(.*\\)\\.git/*$') &&\n \tremote_=\"$remote_1_\"\n-    note_=\"$note_$remote_\"\n+\tnote_=\"$note_$remote_\"\n \n-    # 2.6.11-tree tag would not be happy to be fed to resolve.\n-    if git-cat-file commit \"$head_\" >/dev/null 2>&1\n-    then\n-\theadc_=$(git-rev-parse --verify \"$head_^0\") || exit\n-\techo \"$headc_\t$not_for_merge_\t$note_\" >>\"$GIT_DIR/FETCH_HEAD\"\n-\t[ \"$verbose\" ] && echo >&2 \"* committish: $head_\"\n-\t[ \"$verbose\" ] && echo >&2 \"  $note_\"\n-    else\n-\techo \"$head_\tnot-for-merge\t$note_\" >>\"$GIT_DIR/FETCH_HEAD\"\n-\t[ \"$verbose\" ] && echo >&2 \"* non-commit: $head_\"\n-\t[ \"$verbose\" ] && echo >&2 \"  $note_\"\n-    fi\n-    if test \"$local_name_\" != \"\"\n-    then\n-\t# We are storing the head locally.  Make sure that it is\n-\t# a fast forward (aka \"reverse push\").\n-\tfast_forward_local \"$local_name_\" \"$head_\" \"$note_\"\n-    fi\n+\t# 2.6.11-tree tag would not be happy to be fed to resolve.\n+\tif git-cat-file commit \"$head_\" >/dev/null 2>&1\n+\tthen\n+\t\theadc_=$(git-rev-parse --verify \"$head_^0\") || exit\n+\t\techo \"$headc_\t$not_for_merge_\t$note_\" >>\"$GIT_DIR/FETCH_HEAD\"\n+\t\t[ \"$verbose\" ] && echo >&2 \"* committish: $head_\"\n+\t\t[ \"$verbose\" ] && echo >&2 \"  $note_\"\n+\telse\n+\t\techo \"$head_\tnot-for-merge\t$note_\" >>\"$GIT_DIR/FETCH_HEAD\"\n+\t\t[ \"$verbose\" ] && echo >&2 \"* non-commit: $head_\"\n+\t\t[ \"$verbose\" ] && echo >&2 \"  $note_\"\n+\tfi\n+\tif test \"$local_name_\" != \"\"\n+\tthen\n+\t\t# We are storing the head locally.  Make sure that it is\n+\t\t# a fast forward (aka \"reverse push\").\n+\t\tfast_forward_local \"$local_name_\" \"$head_\" \"$note_\"\n+\tfi\n }\n \n fast_forward_local () {\n-    mkdir -p \"$(dirname \"$GIT_DIR/$1\")\"\n-    case \"$1\" in\n-    refs/tags/*)\n-\t# Tags need not be pointing at commits so there\n-\t# is no way to guarantee \"fast-forward\" anyway.\n-\tif test -f \"$GIT_DIR/$1\"\n-\tthen\n-\t\tif now_=$(cat \"$GIT_DIR/$1\") && test \"$now_\" = \"$2\"\n+\tmkdir -p \"$(dirname \"$GIT_DIR/$1\")\"\n+\tcase \"$1\" in\n+\trefs/tags/*)\n+\t\t# Tags need not be pointing at commits so there\n+\t\t# is no way to guarantee \"fast-forward\" anyway.\n+\t\tif test -f \"$GIT_DIR/$1\"\n \t\tthen\n-\t\t\t[ \"$verbose\" ] && echo >&2 \"* $1: same as $3\" ||:\n+\t\t\tif now_=$(cat \"$GIT_DIR/$1\") && test \"$now_\" = \"$2\"\n+\t\t\tthen\n+\t\t\t\t[ \"$verbose\" ] && echo >&2 \"* $1: same as $3\" ||:\n+\t\t\telse\n+\t\t\t\techo >&2 \"* $1: updating with $3\"\n+\t\t\t\tgit-update-ref -m \"$rloga: updating tag\" \"$1\" \"$2\"\n+\t\t\tfi\n \t\telse\n-\t\t\techo >&2 \"* $1: updating with $3\"\n-\t\t\tgit-update-ref -m \"$rloga: updating tag\" \"$1\" \"$2\"\n+\t\t\techo >&2 \"* $1: storing $3\"\n+\t\t\tgit-update-ref -m \"$rloga: storing tag\" \"$1\" \"$2\"\n \t\tfi\n-\telse\n-\t\techo >&2 \"* $1: storing $3\"\n-\t\tgit-update-ref -m \"$rloga: storing tag\" \"$1\" \"$2\"\n-\tfi\n-\t;;\n+\t\t;;\n \n-    refs/heads/* | refs/remotes/*)\n-\t# $1 is the ref being updated.\n-\t# $2 is the new value for the ref.\n-\tlocal=$(git-rev-parse --verify \"$1^0\" 2>/dev/null)\n-\tif test \"$local\"\n-\tthen\n-\t    # Require fast-forward.\n-\t    mb=$(git-merge-base \"$local\" \"$2\") &&\n-\t    case \"$2,$mb\" in\n-\t    $local,*)\n-\t        if test -n \"$verbose\"\n+\trefs/heads/* | refs/remotes/*)\n+\t\t# $1 is the ref being updated.\n+\t\t# $2 is the new value for the ref.\n+\t\tlocal=$(git-rev-parse --verify \"$1^0\" 2>/dev/null)\n+\t\tif test \"$local\"\n \t\tthen\n-\t\t\techo >&2 \"* $1: same as $3\"\n+\t\t\t# Require fast-forward.\n+\t\t\tmb=$(git-merge-base \"$local\" \"$2\") &&\n+\t\t\tcase \"$2,$mb\" in\n+\t\t\t$local,*)\n+\t\t\t\tif test -n \"$verbose\"\n+\t\t\t\tthen\n+\t\t\t\t\techo >&2 \"* $1: same as $3\"\n+\t\t\t\tfi\n+\t\t\t\t;;\n+\t\t\t*,$local)\n+\t\t\t\techo >&2 \"* $1: fast forward to $3\"\n+\t\t\t\techo >&2 \"  from $local to $2\"\n+\t\t\t\tgit-update-ref -m \"$rloga: fast-forward\" \"$1\" \"$2\" \"$local\"\n+\t\t\t\t;;\n+\t\t\t*)\n+\t\t\t\tfalse\n+\t\t\t\t;;\n+\t\t\tesac || {\n+\t\t\t\techo >&2 \"* $1: does not fast forward to $3;\"\n+\t\t\t\tcase \",$force,$single_force,\" in\n+\t\t\t\t*,t,*)\n+\t\t\t\t\techo >&2 \"  forcing update.\"\n+\t\t\t\t\tgit-update-ref -m \"$rloga: forced-update\" \"$1\" \"$2\" \"$local\"\n+\t\t\t\t\t;;\n+\t\t\t\t*)\n+\t\t\t\t\techo >&2 \"  not updating.\"\n+\t\t\t\t\texit 1\n+\t\t\t\t\t;;\n+\t\t\t\tesac\n+\t\t\t}\n+\t\telse\n+\t\t\techo >&2 \"* $1: storing $3\"\n+\t\t\tgit-update-ref -m \"$rloga: storing head\" \"$1\" \"$2\"\n \t\tfi\n \t\t;;\n-\t    *,$local)\n-\t\techo >&2 \"* $1: fast forward to $3\"\n-\t\techo >&2 \"  from $local to $2\"\n-\t\tgit-update-ref -m \"$rloga: fast-forward\" \"$1\" \"$2\" \"$local\"\n-\t\t;;\n-\t    *)\n-\t\tfalse\n-\t\t;;\n-\t    esac || {\n-\t\techo >&2 \"* $1: does not fast forward to $3;\"\n-\t\tcase \",$force,$single_force,\" in\n-\t\t*,t,*)\n-\t\t\techo >&2 \"  forcing update.\"\n-\t\t\tgit-update-ref -m \"$rloga: forced-update\" \"$1\" \"$2\" \"$local\"\n-\t\t\t;;\n-\t\t*)\n-\t\t\techo >&2 \"  not updating.\"\n-\t\t\texit 1\n-\t\t\t;;\n-\t\tesac\n-\t    }\n-\telse\n-\t    echo >&2 \"* $1: storing $3\"\n-\t    git-update-ref -m \"$rloga: storing head\" \"$1\" \"$2\"\n-\tfi\n-\t;;\n-    esac\n+\tesac\n }\n \n case \"$update_head_ok\" in\n@@ -225,26 +225,27 @@ reflist=$(get_remote_refs_for_fetch \"$@\"\n if test \"$tags\"\n then\n \ttaglist=`IFS=\"\t\" &&\n-\t\t  (\n+\t\t(\n \t\t\tgit-ls-remote $upload_pack --tags \"$remote\" ||\n \t\t\techo fail ouch\n-\t\t  ) |\n-\t          while read sha1 name\n-\t\t  do\n+\t\t) |\n+\t\twhile read sha1 name\n+\t\tdo\n \t\t\tcase \"$sha1\" in\n \t\t\tfail)\n \t\t\t\texit 1\n \t\t\tesac\n \t\t\tcase \"$name\" in\n-\t\t\t*^*) continue ;;\n+\t\t\t*^*)\n+\t\t\t\tcontinue ;;\n \t\t\tesac\n-\t\t  \tif git-check-ref-format \"$name\"\n+\t\t\tif git-check-ref-format \"$name\"\n \t\t\tthen\n-\t\t\t    echo \".${name}:${name}\"\n+\t\t\t\techo \".${name}:${name}\"\n \t\t\telse\n-\t\t\t    echo >&2 \"warning: tag ${name} ignored\"\n+\t\t\t\techo >&2 \"warning: tag ${name} ignored\"\n \t\t\tfi\n-\t\t  done` || exit\n+\t\tdone` || exit\n \tif test \"$#\" -gt 1\n \tthen\n \t\t# remote URL plus explicit refspecs; we need to merge them.\n@@ -256,146 +257,146 @@ then\n fi\n \n fetch_main () {\n-  reflist=\"$1\"\n-  refs=\n+\treflist=\"$1\"\n+\trefs=\n \n-  for ref in $reflist\n-  do\n-      refs=\"$refs$LF$ref\"\n+\tfor ref in $reflist\n+\tdo\n+\t\trefs=\"$refs$LF$ref\"\n \n-      # These are relative path from $GIT_DIR, typically starting at refs/\n-      # but may be HEAD\n-      if expr \"z$ref\" : 'z\\.' >/dev/null\n-      then\n-\t  not_for_merge=t\n-\t  ref=$(expr \"z$ref\" : 'z\\.\\(.*\\)')\n-      else\n-\t  not_for_merge=\n-      fi\n-      if expr \"z$ref\" : 'z+' >/dev/null\n-      then\n-\t  single_force=t\n-\t  ref=$(expr \"z$ref\" : 'z+\\(.*\\)')\n-      else\n-\t  single_force=\n-      fi\n-      remote_name=$(expr \"z$ref\" : 'z\\([^:]*\\):')\n-      local_name=$(expr \"z$ref\" : 'z[^:]*:\\(.*\\)')\n+\t\t# These are relative path from $GIT_DIR, typically starting at refs/\n+\t\t# but may be HEAD\n+\t\tif expr \"z$ref\" : 'z\\.' >/dev/null\n+\t\tthen\n+\t\t\tnot_for_merge=t\n+\t\t\tref=$(expr \"z$ref\" : 'z\\.\\(.*\\)')\n+\t\telse\n+\t\t\tnot_for_merge=\n+\t\tfi\n+\t\tif expr \"z$ref\" : 'z+' >/dev/null\n+\t\tthen\n+\t\t\tsingle_force=t\n+\t\t\tref=$(expr \"z$ref\" : 'z+\\(.*\\)')\n+\t\telse\n+\t\t\tsingle_force=\n+\t\tfi\n+\t\tremote_name=$(expr \"z$ref\" : 'z\\([^:]*\\):')\n+\t\tlocal_name=$(expr \"z$ref\" : 'z[^:]*:\\(.*\\)')\n \n-      rref=\"$rref$LF$remote_name\"\n+\t\trref=\"$rref$LF$remote_name\"\n \n-      # There are transports that can fetch only one head at a time...\n-      case \"$remote\" in\n-      http://* | https://*)\n-\t  if [ -n \"$GIT_SSL_NO_VERIFY\" ]; then\n-\t      curl_extra_args=\"-k\"\n-\t  fi\n-\t  max_depth=5\n-\t  depth=0\n-\t  head=\"ref: $remote_name\"\n-\t  while (expr \"z$head\" : \"zref:\" && expr $depth \\< $max_depth) >/dev/null\n-\t  do\n-\t    remote_name_quoted=$(@@PERL@@ -e '\n-\t      my $u = $ARGV[0];\n-              $u =~ s/^ref:\\s*//;\n-\t      $u =~ s{([^-a-zA-Z0-9/.])}{sprintf\"%%%02x\",ord($1)}eg;\n-\t      print \"$u\";\n-\t  ' \"$head\")\n-\t    head=$(curl -nsfL $curl_extra_args \"$remote/$remote_name_quoted\")\n-\t    depth=$( expr \\( $depth + 1 \\) )\n-\t  done\n-\t  expr \"z$head\" : \"z$_x40\\$\" >/dev/null ||\n-\t      die \"Failed to fetch $remote_name from $remote\"\n-\t  echo >&2 Fetching \"$remote_name from $remote\" using http\n-\t  git-http-fetch -v -a \"$head\" \"$remote/\" || exit\n-\t  ;;\n-      rsync://*)\n-\t  TMP_HEAD=\"$GIT_DIR/TMP_HEAD\"\n-\t  rsync -L -q \"$remote/$remote_name\" \"$TMP_HEAD\" || exit 1\n-\t  head=$(git-rev-parse --verify TMP_HEAD)\n-\t  rm -f \"$TMP_HEAD\"\n-\t  test \"$rsync_slurped_objects\" || {\n-\t      rsync -av --ignore-existing --exclude info \\\n-\t\t  \"$remote/objects/\" \"$GIT_OBJECT_DIRECTORY/\" || exit\n+\t\t# There are transports that can fetch only one head at a time...\n+\t\tcase \"$remote\" in\n+\t\thttp://* | https://*)\n+\t\t\tif [ -n \"$GIT_SSL_NO_VERIFY\" ]; then\n+\t\t\t\tcurl_extra_args=\"-k\"\n+\t\t\tfi\n+\t\t\tmax_depth=5\n+\t\t\tdepth=0\n+\t\t\thead=\"ref: $remote_name\"\n+\t\t\twhile (expr \"z$head\" : \"zref:\" && expr $depth \\< $max_depth) >/dev/null\n+\t\t\tdo\n+\t\t\t\tremote_name_quoted=$(@@PERL@@ -e '\n+\t\t\t\t\tmy $u = $ARGV[0];\n+\t\t\t\t\t$u =~ s/^ref:\\s*//;\n+\t\t\t\t\t$u =~ s{([^-a-zA-Z0-9/.])}{sprintf\"%%%02x\",ord($1)}eg;\n+\t\t\t\t\tprint \"$u\";\n+\t\t\t\t\t' \"$head\")\n+\t\t\t\thead=$(curl -nsfL $curl_extra_args \"$remote/$remote_name_quoted\")\n+\t\t\t\tdepth=$( expr \\( $depth + 1 \\) )\n+\t\t\tdone\n+\t\t\texpr \"z$head\" : \"z$_x40\\$\" >/dev/null ||\n+\t\t\t\tdie \"Failed to fetch $remote_name from $remote\"\n+\t\t\techo >&2 Fetching \"$remote_name from $remote\" using http\n+\t\t\tgit-http-fetch -v -a \"$head\" \"$remote/\" || exit\n+\t\t\t;;\n+\t\trsync://*)\n+\t\t\tTMP_HEAD=\"$GIT_DIR/TMP_HEAD\"\n+\t\t\trsync -L -q \"$remote/$remote_name\" \"$TMP_HEAD\" || exit 1\n+\t\t\thead=$(git-rev-parse --verify TMP_HEAD)\n+\t\t\trm -f \"$TMP_HEAD\"\n+\t\t\ttest \"$rsync_slurped_objects\" || {\n+\t\t\t\trsync -av --ignore-existing --exclude info \\\n+\t\t\t\t\t\"$remote/objects/\" \"$GIT_OBJECT_DIRECTORY/\" || exit\n \n-\t      # Look at objects/info/alternates for rsync -- http will\n-\t      # support it natively and git native ones will do it on\n-\t      # the remote end.  Not having that file is not a crime.\n-\t      rsync -q \"$remote/objects/info/alternates\" \\\n-\t\t  \"$GIT_DIR/TMP_ALT\" 2>/dev/null ||\n-\t\t  rm -f \"$GIT_DIR/TMP_ALT\"\n-\t      if test -f \"$GIT_DIR/TMP_ALT\"\n-\t      then\n-\t\t  resolve_alternates \"$remote\" <\"$GIT_DIR/TMP_ALT\" |\n-\t\t  while read alt\n-\t\t  do\n-\t\t      case \"$alt\" in 'bad alternate: '*) die \"$alt\";; esac\n-\t\t      echo >&2 \"Getting alternate: $alt\"\n-\t\t      rsync -av --ignore-existing --exclude info \\\n-\t\t      \"$alt\" \"$GIT_OBJECT_DIRECTORY/\" || exit\n-\t\t  done\n-\t\t  rm -f \"$GIT_DIR/TMP_ALT\"\n-\t      fi\n-\t      rsync_slurped_objects=t\n-\t  }\n-\t  ;;\n-      *)\n-\t  # We will do git native transport with just one call later.\n-\t  continue ;;\n-      esac\n+\t\t\t# Look at objects/info/alternates for rsync -- http will\n+\t\t\t# support it natively and git native ones will do it on\n+\t\t\t# the remote end.  Not having that file is not a crime.\n+\t\t\trsync -q \"$remote/objects/info/alternates\" \\\n+\t\t\t\t\"$GIT_DIR/TMP_ALT\" 2>/dev/null ||\n+\t\t\t\trm -f \"$GIT_DIR/TMP_ALT\"\n+\t\t\tif test -f \"$GIT_DIR/TMP_ALT\"\n+\t\t\tthen\n+\t\t\t\tresolve_alternates \"$remote\" <\"$GIT_DIR/TMP_ALT\" |\n+\t\t\t\twhile read alt\n+\t\t\t\tdo\n+\t\t\t\t\tcase \"$alt\" in 'bad alternate: '*) die \"$alt\";; esac\n+\t\t\t\t\techo >&2 \"Getting alternate: $alt\"\n+\t\t\t\t\trsync -av --ignore-existing --exclude info \\\n+\t\t\t\t\t\t\"$alt\" \"$GIT_OBJECT_DIRECTORY/\" || exit\n+\t\t\t\tdone\n+\t\t\t\trm -f \"$GIT_DIR/TMP_ALT\"\n+\t\t\tfi\n+\t\t\trsync_slurped_objects=t\n+\t\t\t}\n+\t\t\t;;\n+\t\t*)\n+\t\t\t# We will do git native transport with just one call later.\n+\t\t\tcontinue ;;\n+\t\tesac\n \n-      append_fetch_head \"$head\" \"$remote\" \\\n-\t  \"$remote_name\" \"$remote_nick\" \"$local_name\" \"$not_for_merge\"\n+\t\tappend_fetch_head \"$head\" \"$remote\" \\\n+\t\t\t\"$remote_name\" \"$remote_nick\" \"$local_name\" \"$not_for_merge\"\n \n-  done\n+\tdone\n \n-  case \"$remote\" in\n-  http://* | https://* | rsync://* )\n-      ;; # we are already done.\n-  *)\n-    ( : subshell because we muck with IFS\n-      IFS=\" \t$LF\"\n-      (\n-\t  git-fetch-pack $exec $keep \"$remote\" $rref || echo failed \"$remote\"\n-      ) |\n-      while read sha1 remote_name\n-      do\n-\t  case \"$sha1\" in\n-\t  failed)\n-\t\t  echo >&2 \"Fetch failure: $remote\"\n-\t\t  exit 1 ;;\n-\t  esac\n-\t  found=\n-\t  single_force=\n-\t  for ref in $refs\n-\t  do\n-\t      case \"$ref\" in\n-\t      +$remote_name:*)\n-\t\t  single_force=t\n-\t\t  not_for_merge=\n-\t\t  found=\"$ref\"\n-\t\t  break ;;\n-\t      .+$remote_name:*)\n-\t\t  single_force=t\n-\t\t  not_for_merge=t\n-\t\t  found=\"$ref\"\n-\t\t  break ;;\n-\t      .$remote_name:*)\n-\t\t  not_for_merge=t\n-\t\t  found=\"$ref\"\n-\t\t  break ;;\n-\t      $remote_name:*)\n-\t\t  not_for_merge=\n-\t\t  found=\"$ref\"\n-\t\t  break ;;\n-\t      esac\n-\t  done\n-\t  local_name=$(expr \"z$found\" : 'z[^:]*:\\(.*\\)')\n-\t  append_fetch_head \"$sha1\" \"$remote\" \\\n-\t\t  \"$remote_name\" \"$remote_nick\" \"$local_name\" \"$not_for_merge\"\n-      done\n-    ) || exit ;;\n-  esac\n+\tcase \"$remote\" in\n+\thttp://* | https://* | rsync://* )\n+\t\t;; # we are already done.\n+\t*)\n+\t\t( : subshell because we muck with IFS\n+\t\t\tIFS=\" \t$LF\"\n+\t\t\t(\n+\t\t\t\tgit-fetch-pack $exec $keep \"$remote\" $rref || echo failed \"$remote\"\n+\t\t\t) |\n+\t\t\twhile read sha1 remote_name\n+\t\t\tdo\n+\t\t\t\tcase \"$sha1\" in\n+\t\t\t\tfailed)\n+\t\t\t\t\techo >&2 \"Fetch failure: $remote\"\n+\t\t\t\t\texit 1 ;;\n+\t\t\t\tesac\n+\t\t\t\tfound=\n+\t\t\t\tsingle_force=\n+\t\t\t\tfor ref in $refs\n+\t\t\t\tdo\n+\t\t\t\t\tcase \"$ref\" in\n+\t\t\t\t\t+$remote_name:*)\n+\t\t\t\t\t\tsingle_force=t\n+\t\t\t\t\t\tnot_for_merge=\n+\t\t\t\t\t\tfound=\"$ref\"\n+\t\t\t\t\t\tbreak ;;\n+\t\t\t\t\t.+$remote_name:*)\n+\t\t\t\t\t\tsingle_force=t\n+\t\t\t\t\t\tnot_for_merge=t\n+\t\t\t\t\t\tfound=\"$ref\"\n+\t\t\t\t\t\tbreak ;;\n+\t\t\t\t\t.$remote_name:*)\n+\t\t\t\t\t\tnot_for_merge=t\n+\t\t\t\t\t\tfound=\"$ref\"\n+\t\t\t\t\t\tbreak ;;\n+\t\t\t\t\t$remote_name:*)\n+\t\t\t\t\t\tnot_for_merge=\n+\t\t\t\t\t\tfound=\"$ref\"\n+\t\t\t\t\t\tbreak ;;\n+\t\t\t\t\tesac\n+\t\t\t\tdone\n+\t\t\t\tlocal_name=$(expr \"z$found\" : 'z[^:]*:\\(.*\\)')\n+\t\t\t\tappend_fetch_head \"$sha1\" \"$remote\" \\\n+\t\t\t\t\t\"$remote_name\" \"$remote_nick\" \"$local_name\" \"$not_for_merge\"\n+\t\t\tdone\n+\t\t) || exit ;;\n+\tesac\n \n }\n \n@@ -439,7 +440,7 @@ case \",$update_head_ok,$orig_head,\" in\n \tcurr_head=$(git-rev-parse --verify HEAD 2>/dev/null)\n \tif test \"$curr_head\" != \"$orig_head\"\n \tthen\n-\t    git-update-ref \\\n+\t\tgit-update-ref \\\n \t\t\t-m \"$rloga: Undoing incorrectly fetched HEAD.\" \\\n \t\t\tHEAD \"$orig_head\"\n \t\tdie \"Cannot fetch into the current branch.\"\ndiff --git a/git-ls-remote.sh b/git-ls-remote.sh\nindex 2fdcaf7..38122ad 100755\n--- a/git-ls-remote.sh\n+++ b/git-ls-remote.sh\n@@ -2,36 +2,36 @@ #!/bin/sh\n #\n \n usage () {\n-    echo >&2 \"usage: $0 [--heads] [--tags] [-u|--upload-pack <upload-pack>]\"\n-    echo >&2 \"          <repository> <refs>...\"\n-    exit 1;\n+\techo >&2 \"usage: $0 [--heads] [--tags] [-u|--upload-pack <upload-pack>]\"\n+\techo >&2 \"          <repository> <refs>...\"\n+\texit 1;\n }\n \n die () {\n-    echo >&2 \"$*\"\n-    exit 1\n+\techo >&2 \"$*\"\n+\texit 1\n }\n \n exec=\n while case \"$#\" in 0) break;; esac\n do\n-  case \"$1\" in\n-  -h|--h|--he|--hea|--head|--heads)\n-  heads=heads; shift ;;\n-  -t|--t|--ta|--tag|--tags)\n-  tags=tags; shift ;;\n-  -u|--u|--up|--upl|--uploa|--upload|--upload-|--upload-p|--upload-pa|\\\n-  --upload-pac|--upload-pack)\n-\tshift\n-\texec=\"--exec=$1\"\n-\tshift;;\n-  --)\n-  shift; break ;;\n-  -*)\n-  usage ;;\n-  *)\n-  break ;;\n-  esac\n+\tcase \"$1\" in\n+\t-h|--h|--he|--hea|--head|--heads)\n+\t\theads=heads; shift ;;\n+\t-t|--t|--ta|--tag|--tags)\n+\t\ttags=tags; shift ;;\n+\t-u|--u|--up|--upl|--uploa|--upload|--upload-|--upload-p|--upload-pa|\\\n+\t\t--upload-pac|--upload-pack)\n+\t\tshift\n+\t\texec=\"--exec=$1\"\n+\t\tshift;;\n+\t--)\n+\t\tshift; break ;;\n+\t-*)\n+\t\tusage ;;\n+\t*)\n+\t\tbreak ;;\n+\tesac\n done\n \n case \"$#\" in 0) usage ;; esac\n@@ -50,9 +50,9 @@ tmpdir=$tmp-d\n \n case \"$peek_repo\" in\n http://* | https://* )\n-        if [ -n \"$GIT_SSL_NO_VERIFY\" ]; then\n-            curl_extra_args=\"-k\"\n-        fi\n+\tif [ -n \"$GIT_SSL_NO_VERIFY\" ]; then\n+\t\tcurl_extra_args=\"-k\"\n+\tfi\n \tcurl -nsf $curl_extra_args --header \"Pragma: no-cache\" \"$peek_repo/info/refs\" ||\n \t\techo \"failed\tslurping\"\n \t;;\n-- \n1.4.1.1\n"},{"id":"24499","messageId":"200608011136.54698.jnareb@gmail.com","threadId":"5038","inReplyTo":"200608011134.52006.jnareb@gmail.com","subject":"[PATCH 2/2] Set User-Agent string in shell scripts used for fetching","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-08-01T09:36:54Z","receivedAt":"2006-08-01T09:36:54Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"This needs checking for shell portability.\n\nSigned-off-by: Jakub Narebski <jnareb@gmail.com>\n---\nJunio C Hamano wrote:\n\n> Jakub Narebski <jnareb@gmail.com> writes:\n> \n>> By the way, I wonder why git when cloning/fetching via http protocol\n>> uses e.g. \"git/1.4.2.rc2.ge0bed\" as User-Agent: string when fetching objects\n>> and packs, and e.g. \"curl/7.15.4 (i486-pc-linux-gnu) libcurl/7.15.4\n>> OpenSSL/0.9.8b zlib/1.2.3 libidn/0.6.5\" as User-Agent: when fetching refs\n>> (heads and tags) and info/refs.\n> \n> \"Why?\", meaning if we deliberately do so for some good reason?\n> \n> There isn't.\n> \n> git-http-fetch uses its own User-Agent string, but the shell\n> script wrappers that use curl executable do not bother setting\n> customized User-Agent string; that is why.\n\nSo there :-)\n\n git-clone.sh     |    4 +++-\n git-fetch.sh     |    5 ++++-\n git-ls-remote.sh |    7 +++++--\n 3 files changed, 12 insertions(+), 4 deletions(-)\n\ndiff --git a/git-clone.sh b/git-clone.sh\nindex adb752d..a9676d6 100755\n--- a/git-clone.sh\n+++ b/git-clone.sh\n@@ -20,10 +20,12 @@ get_repo_base() {\n if [ -n \"$GIT_SSL_NO_VERIFY\" ]; then\n \tcurl_extra_args=\"-k\"\n fi\n+curl_user_agent=\"$(git --version)\"\n+curl_user_agent=\"git/${curl_user_agent##git version }\"\n \n http_fetch () {\n \t# $1 = Remote, $2 = Local\n-\tcurl -nsfL $curl_extra_args \"$1\" >\"$2\"\n+\tcurl -nsfL $curl_extra_args $curl_user_agent \"$1\" >\"$2\"\n }\n \n clone_dumb_http () {\ndiff --git a/git-fetch.sh b/git-fetch.sh\nindex cea6e0b..6635bd5 100755\n--- a/git-fetch.sh\n+++ b/git-fetch.sh\n@@ -291,6 +291,8 @@ fetch_main () {\n \t\t\tif [ -n \"$GIT_SSL_NO_VERIFY\" ]; then\n \t\t\t\tcurl_extra_args=\"-k\"\n \t\t\tfi\n+\t\t\tcurl_user_agent=\"$(git --version)\"\n+\t\t\tcurl_user_agent=\"git/${curl_user_agent##git version }\"\n \t\t\tmax_depth=5\n \t\t\tdepth=0\n \t\t\thead=\"ref: $remote_name\"\n@@ -302,7 +304,8 @@ fetch_main () {\n \t\t\t\t\t$u =~ s{([^-a-zA-Z0-9/.])}{sprintf\"%%%02x\",ord($1)}eg;\n \t\t\t\t\tprint \"$u\";\n \t\t\t\t\t' \"$head\")\n-\t\t\t\thead=$(curl -nsfL $curl_extra_args \"$remote/$remote_name_quoted\")\n+\t\t\t\thead=$(curl -nsfL $curl_extra_args $curl_user_agent \\\n+\t\t\t\t\t\"$remote/$remote_name_quoted\")\n \t\t\t\tdepth=$( expr \\( $depth + 1 \\) )\n \t\t\tdone\n \t\t\texpr \"z$head\" : \"z$_x40\\$\" >/dev/null ||\ndiff --git a/git-ls-remote.sh b/git-ls-remote.sh\nindex 38122ad..32b93da 100755\n--- a/git-ls-remote.sh\n+++ b/git-ls-remote.sh\n@@ -53,8 +53,11 @@ http://* | https://* )\n \tif [ -n \"$GIT_SSL_NO_VERIFY\" ]; then\n \t\tcurl_extra_args=\"-k\"\n \tfi\n-\tcurl -nsf $curl_extra_args --header \"Pragma: no-cache\" \"$peek_repo/info/refs\" ||\n-\t\techo \"failed\tslurping\"\n+\tcurl_user_agent=\"$(git --version)\"\n+\tcurl_user_agent=\"git/${curl_user_agent##git version }\"\n+\tcurl -nsf $curl_extra_args $curl_user_agent --header \"Pragma: no-cache\" \\\n+\t\t\"$peek_repo/info/refs\" ||\n+\t\techo \"failed slurping\"\n \t;;\n \n rsync://* )\n-- \n1.4.1.1\n"},{"id":"24501","messageId":"7vr70023aj.fsf@assigned-by-dhcp.cox.net","threadId":"5038","inReplyTo":"200608011134.52006.jnareb@gmail.com","subject":"Re: [PATCH 1/2] Use tabs for indent in shell scripts","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-08-01T09:50:12Z","receivedAt":"2006-08-01T09:50:12Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jakub Narebski <jnareb@gmail.com> writes:\n\n>  if [ -n \"$GIT_SSL_NO_VERIFY\" ]; then\n> -    curl_extra_args=\"-k\"\n> +\tcurl_extra_args=\"-k\"\n>  fi\n\nThings like this makes some sense...\n\n>  \t\tif test -n \"$use_separate_remote\" &&\n> -\t\t   branch_name=`expr \"z$name\" : 'zheads/\\(.*\\)'`\n> +\t\t\tbranch_name=`expr \"z$name\" : 'zheads/\\(.*\\)'`\n>  \t\tthen\n\n... but not this, which is not just indent but an alignment.\n\n>  \t\tcase \"$2\" in\n>  \t\t'')\n> -\t\t    usage ;;\n> +\t\t\tusage ;;\n>  \t\t*/*)\n> -\t\t    echo >&2 \"'$2' is not suitable for an origin name\"\n> -\t\t    exit 1\n> +\t\t\techo >&2 \"'$2' is not suitable for an origin name\"\n> +\t\t\texit 1\n\nAlso shell scripts tend to become too deeply indented, and 4-column\nindentation helps to keep things within typical screen width.\n\nIn short, not very enthused.\n"},{"id":"24502","messageId":"7vmzao238m.fsf@assigned-by-dhcp.cox.net","threadId":"5038","inReplyTo":"200608011136.54698.jnareb@gmail.com","subject":"Re: [PATCH 2/2] Set User-Agent string in shell scripts used for fetching","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-08-01T09:51:21Z","receivedAt":"2006-08-01T09:51:21Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jakub Narebski <jnareb@gmail.com> writes:\n\n>> \"Why?\", meaning if we deliberately do so for some good reason?\n>> \n>> There isn't.\n>> \n>> git-http-fetch uses its own User-Agent string, but the shell\n>> script wrappers that use curl executable do not bother setting\n>> customized User-Agent string; that is why.\n>\n> So there :-)\n\nWho said we want to?  Actually I explicitly said we do not\nbother ;-).\n"},{"id":"24504","messageId":"ean8oq$amb$1@sea.gmane.org","threadId":"5038","inReplyTo":"7vr70023aj.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH 1/2] Use tabs for indent in shell scripts","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-08-01T10:01:19Z","receivedAt":"2006-08-01T10:01:19Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Junio C Hamano wrote:\n\n> Jakub Narebski <jnareb@gmail.com> writes:\n> \n>>  if [ -n \"$GIT_SSL_NO_VERIFY\" ]; then\n>> -    curl_extra_args=\"-k\"\n>> +    curl_extra_args=\"-k\"\n>>  fi\n> \n> Things like this makes some sense...\n> \n>>              if test -n \"$use_separate_remote\" &&\n>> -               branch_name=`expr \"z$name\" : 'zheads/\\(.*\\)'`\n>> +                    branch_name=`expr \"z$name\" : 'zheads/\\(.*\\)'`\n>>              then\n> \n> ... but not this, which is not just indent but an alignment.\n\nSorry, my mistake. Tabs for indent, spaces for align, of course. So discard\nthis chunk, please.\n\n\nI'm not sure how to indent sequences like the following:\n\n  command arg \\\n    arg arg arg \\\n    arg arg arg\n\nThe above I think everybody would agree on.\n\n  command &&\n    command &&\n    command\n\n  command ||\n    command ||\n    command\n\nNot so sure about above\n\n[...]\n> Also shell scripts tend to become too deeply indented, and 4-column\n> indentation helps to keep things within typical screen width.\n> \n> In short, not very enthused.\n\nI use tab-width 2 and script didn't get too indented. All changed scripts\nexcept git-clone.sh fit in 80 column window for tab width 2, and the lines\nin git-clone.sh which do not fit in 80 columns are not indented at all. \n\n-- \nJakub Narebski\nWarsaw, Poland\nShadeHawk on #git\n"},{"id":"24511","messageId":"E1G7tg4-0007bJ-7r@moooo.ath.cx","threadId":"5038","inReplyTo":"200607292239.11034.jnareb@gmail.com","subject":"[PATCH] gitweb: clean up user configuration part","fromName":"Matthias Lederhofer","fromEmail":"matled@gmx.net","sentAt":"2006-08-01T12:48:52Z","receivedAt":"2006-08-01T12:48:52Z","isPatch":true,"sender":{"key":"matled@gmx.net","avatar":null},"body":" * add a marker where the user configuration starts/ends\n * replaced the two $projectroot = lines\n * add a comment to $projectlist\n * reorder the variables\n\nSigned-off-by: Matthias Lederhofer <matled@gmx.net>\n---\nI tried to put the variables at top which will be edited most likely\n(cannot have sane default values).\n---\n gitweb/gitweb.cgi |   58 ++++++++++++++++++++++++++++++++---------------------\n 1 files changed, 35 insertions(+), 23 deletions(-)\n\ndiff --git a/gitweb/gitweb.cgi b/gitweb/gitweb.cgi\nindex 9448b72..ca2ef70 100755\n--- a/gitweb/gitweb.cgi\n+++ b/gitweb/gitweb.cgi\n@@ -18,44 +18,42 @@ use File::Find qw();\n binmode STDOUT, ':utf8';\n \n our $cgi = new CGI;\n-our $version = \"267\";\n-our $my_url = $cgi->url();\n-our $my_uri = $cgi->url(-absolute => 1);\n-our $rss_link = \"\";\n \n-# core git executable to use\n-# this can just be \"git\" if your webserver has a sensible PATH\n-our $GIT = \"/usr/bin/git\";\n+##\n+## BEGIN USER CONFIGURATION\n+##\n \n # absolute fs-path which will be prepended to the project path\n-#our $projectroot = \"/pub/scm\";\n-our $projectroot = \"/home/kay/public_html/pub/scm\";\n+our $projectroot = \"/pub/git\";\n \n-# version of the core git binary\n-our $git_version = qx($GIT --version) =~ m/git version (.*)$/ ? $1 : \"unknown\";\n+# source of projects list\n+# file: list of projects, may use subdirectories\n+# directory: all git repositories in the directory (not subdirectories)\n+our $projects_list = \"index/index.aux\";\n+#our $projects_list = $projectroot;\n \n-# location for temporary files needed for diffs\n-our $git_temp = \"/tmp/gitweb\";\n-if (! -d $git_temp) {\n-\tmkdir($git_temp, 0700) || die_error(\"Couldn't mkdir $git_temp\");\n-}\n+# html text to include at home page\n+our $home_text = \"indextext.html\";\n \n-# target of the home link on top of all pages\n-our $home_link = $my_uri;\n+# core git executable to use\n+# this can just be \"git\" if your webserver has a sensible PATH\n+our $GIT = \"/usr/bin/git\";\n \n # name of your site or organization to appear in page titles\n # replace this with something more descriptive for clearer bookmarks\n our $site_name = $ENV{'SERVER_NAME'} || \"Untitled\";\n \n-# html text to include at home page\n-our $home_text = \"indextext.html\";\n+our $my_url = $cgi->url();\n+our $my_uri = $cgi->url(-absolute => 1);\n+our $rss_link = \"\";\n+# target of the home link on top of all pages\n+our $home_link = $my_uri;\n \n # URI of default stylesheet\n our $stylesheet = \"gitweb.css\";\n \n-# source of projects list\n-#our $projects_list = $projectroot;\n-our $projects_list = \"index/index.aux\";\n+# location for temporary files needed for diffs\n+our $git_temp = \"/tmp/gitweb\";\n \n # default blob_plain mimetype and default charset for text/plain blob\n our $default_blob_plain_mimetype = 'text/plain';\n@@ -65,6 +63,20 @@ # file to use for guessing MIME types be\n # (relative to the current git repository)\n our $mimetypes_file = undef;\n \n+##\n+## END USER CONFIGURATION\n+##\n+\n+# version of the core git binary\n+our $git_version = qx($GIT --version) =~ m/git version (.*)$/ ? $1 : \"unknown\";\n+\n+our $version = \"267\";\n+\n+# create temp directory\n+if (! -d $git_temp) {\n+\tmkdir($git_temp, 0700) || die_error(\"Couldn't mkdir $git_temp\");\n+}\n+\n # input validation and dispatch\n our $action = $cgi->param('a');\n if (defined $action) {\n-- \n1.4.2.rc2.g4713\n"},{"id":"24512","messageId":"E1G7ugo-0001Ym-7r@moooo.ath.cx","threadId":"5038","inReplyTo":"200607292239.11034.jnareb@gmail.com","subject":"[RFC/PATCH] gitweb: include perl files for configuration","fromName":"Matthias Lederhofer","fromEmail":"matled@gmx.net","sentAt":"2006-08-01T13:53:42Z","receivedAt":"2006-08-01T13:53:42Z","isPatch":true,"sender":{"key":"matled@gmx.net","avatar":null},"body":"gitweb will first include all files after __DATA__ and then\n$GITWEB_CONFIG\n\nSigned-off-by: Matthias Lederhofer <matled@gmx.net>\n---\nI really hate upgrading gitweb because every time I've to copy the\nconfiguration part from the old script to the new one.  I do some\nregexp to find the values for some configuration values so I'd prefer\nto include a perl file instead of a normal configuration file.\n\nFor example I'd use this with this patch:\n\n$GIT = \"/usr/local/bin/git\";\n$stylesheet = \"/gitweb.css\";\nif ($ENV{'SCRIPT_NAME'} =~ m#^/([a-z0-9-]+)/#) {\n    $projectroot = \"/home/$1\";\n    $home_text =   $projectroot.\"/gitweb.html\";\n    $projects_list = $projectroot.\"/gitweb.list\";\n} else {\n    $projectroot = \"/home\";\n    $home_text = \"/www/gitweb.html\";\n    $projects_list = \"/www/gitweb.list\";\n}\n\nIn this setup there is one subdirectory per-user which contains a\nsymlink to ../gitweb.cgi allowing them to maintain their own gitweb.\n\nLater (see gitweb.pl post) the Makefile could also add the path to the\nconfiguration file automatically if a certain variable is set (by\nappending the filename to gitweb.cgi).\n\nUsing __DATA__ instead of a variable holding the filename allows to\nadd the configuration file easily without editing the file in an\neditor or trying to replace some part (without breaking something)\nusing sed.\n\nThis patch is on top of my last patch (user configuration cleanup).\n---\n gitweb/gitweb.cgi |   35 ++++++++++++++++++++++++++++++++---\n 1 files changed, 32 insertions(+), 3 deletions(-)\n\ndiff --git a/gitweb/gitweb.cgi b/gitweb/gitweb.cgi\nindex ca2ef70..96f8852 100755\n--- a/gitweb/gitweb.cgi\n+++ b/gitweb/gitweb.cgi\n@@ -23,6 +23,12 @@ ##\n ## BEGIN USER CONFIGURATION\n ##\n \n+# You can let gitweb 'do' (perldoc -f do) configuration files after this\n+# configuration section to override the values.  The configuration files\n+# will be executed in this order:\n+# - files after __DATA__ (first file first)\n+# - file in the $GITWEB_CONFIG environment variable\n+\n # absolute fs-path which will be prepended to the project path\n our $projectroot = \"/pub/git\";\n \n@@ -67,10 +73,31 @@ ##\n ## END USER CONFIGURATION\n ##\n \n-# version of the core git binary\n-our $git_version = qx($GIT --version) =~ m/git version (.*)$/ ? $1 : \"unknown\";\n-\n our $version = \"267\";\n+# die_error uses this, circumvents some warnings\n+our $git_version = 'unknown';\n+\n+# 'do' configuration files\n+for my $file (<DATA>, $ENV{'GITWEB_CONFIG'}) {\n+\tnext if (!defined($file));\n+\t$file =~ s/\\r?\\n$//;\n+\tif (! -e $file) {\n+\t\twarn(\"configuration file '$file' does not exist\");\n+\t\tdie_error('500 Internal Server Error', 'Configuration error');\n+\t}\n+\tundef $@;\n+\tundef $!;\n+\tnext if (defined(do($file)));\n+\tif ($@) {\n+\t\twarn(\"parse error in configuration file '$file': $@\");\n+\t} else {\n+\t\twarn(\"error in configuration file '$file': $!\");\n+\t}\n+\tdie_error('500 Internal Server Error', 'Configuration error');\n+}\n+\n+# version of the core git binary\n+$git_version = qx($GIT --version) =~ m/git version (.*)$/ ? $1 : \"unknown\";\n \n # create temp directory\n if (! -d $git_temp) {\n@@ -2608,3 +2635,5 @@ sub git_opml {\n \t      \"</body>\\n\".\n \t      \"</opml>\\n\";\n }\n+\n+__DATA__\n-- \n1.4.2.rc2.g4713\n"},{"id":"24525","messageId":"20060801201000.96106.qmail@web31809.mail.mud.yahoo.com","threadId":"5038","inReplyTo":"7vzmep2icr.fsf_-_@assigned-by-dhcp.cox.net","subject":"Re: A few more fixups to gitweb","fromName":"Luben Tuikov","fromEmail":"ltuikov@yahoo.com","sentAt":"2006-08-01T20:10:00Z","receivedAt":"2006-08-01T20:10:00Z","isPatch":false,"sender":{"key":"ltuikov@yahoo.com","avatar":null},"body":"--- Junio C Hamano <junkio@cox.net> wrote:\n> One thing to note.  Please make sure that you do not see\n> anything in Apache error log after you make your changes.  I do\n> not remember the details but kernel.org folks were very unhappy\n> earlier when gitweb spewed stuff into the error log, and if I\n> recall correctly things that output to the error stream were not\n> friendly to the http-server cache for some reason.\n\nI've been meaning to mention this as well.  Gitweb patches,\nespecially recent ones, need more (thorough) testing, before\nposted to the list for inclusion.\n\n    Luben\n"}]}