+ print "<div class=\"page_nav\">\n" .
+ $cgi->a({-href => "$my_uri?p=$project;a=summary"}, "summary") .
+ " | " . $cgi->a({-href => "$my_uri?p=$project;a=shortlog"}, "shortlog") .
+ " | " . $cgi->a({-href => "$my_uri?p=$project;a=log"}, "log") .
+ " | " . $cgi->a({-href => "$my_uri?p=$project;a=commit;h=$head"}, "commit") .
+ " | " . $cgi->a({-href => "$my_uri?p=$project;a=commitdiff;h=$head"}, "commitdiff") .
+ " | " . $cgi->a({-href => "$my_uri?p=$project;a=tree;hb=$head"}, "tree") . "<br/>\n" .
+ "<br/>\n" .
+ "</div>\n";
+ my $taglist = git_read_refs("refs/tags");
+ print "<div>\n" .
+ $cgi->a({-href => "$my_uri?p=$project;a=summary", -class => "title"}, " ") .
+ "</div>\n";
+ print "<table cellspacing=\"0\">\n";
+ my $alternate = 0;
+ if (defined @$taglist) {
+ foreach my $entry (@$taglist) {
+ my %tag = %$entry;
+ my $comment_lines = $tag{'comment'};
+ my $comment = shift @$comment_lines;
+ if (defined($comment)) {
+ $comment = chop_str($comment, 30, 5);
+ }
+ if ($alternate) {
+ print "<tr class=\"dark\">\n";
+ } else {
+ print "<tr class=\"light\">\n";
+ }
+ $alternate ^= 1;
+ print "<td><i>$tag{'age'}</i></td>\n" .
+ "<td>" .
+ $cgi->a({-href => "$my_uri?p=$project;a=$tag{'reftype'};h=$tag{'refid'}", -class => "list"},
+ "<b>" . escapeHTML($tag{'name'}) . "</b>") .
+ "</td>\n" .
+ "<td>";
+ if (defined($comment)) {
+ print $cgi->a({-class => "list", -href => "$my_uri?p=$project;a=tag;h=$tag{'id'}"}, $comment);
+ }
+ print "</td>\n" .
+ "<td class=\"link\">";
+ if ($tag{'type'} eq "tag") {
+ print $cgi->a({-href => "$my_uri?p=$project;a=tag;h=$tag{'id'}"}, "tag") . " | ";
+ }
+ print $cgi->a({-href => "$my_uri?p=$project;a=$tag{'reftype'};h=$tag{'refid'}"}, $tag{'reftype'});
+ if ($tag{'reftype'} eq "commit") {
+ print " | " . $cgi->a({-href => "$my_uri?p=$project;a=shortlog;h=$tag{'name'}"}, "shortlog") .
+ " | " . $cgi->a({-href => "$my_uri?p=$project;a=log;h=$tag{'refid'}"}, "log");
+ }
+ print "</td>\n" .
+ "</tr>";
+ }
+ }
+ print "</table\n>";
+ git_footer_html();
+}
+
+sub git_branches {
+ my $head = git_read_hash("$project/HEAD");
+ git_header_html();
+ print "<div class=\"page_nav\">\n" .
+ $cgi->a({-href => "$my_uri?p=$project;a=summary"}, "summary") .
+ " | " . $cgi->a({-href => "$my_uri?p=$project;a=shortlog"}, "shortlog") .
+ " | " . $cgi->a({-href => "$my_uri?p=$project;a=log"}, "log") .
+ " | " . $cgi->a({-href => "$my_uri?p=$project;a=commit;h=$head"}, "commit") .
+ " | " . $cgi->a({-href => "$my_uri?p=$project;a=commitdiff;h=$head"}, "commitdiff") .
+ " | " . $cgi->a({-href => "$my_uri?p=$project;a=tree;hb=$head"}, "tree") . "<br/>\n" .
+ "<br/>\n" .
+ "</div>\n";
+ my $taglist = git_read_refs("refs/heads");
+ print "<div>\n" .
+ $cgi->a({-href => "$my_uri?p=$project;a=summary", -class => "title"}, " ") .
+ "</div>\n";
+ print "<table cellspacing=\"0\">\n";
+ my $alternate = 0;
+ if (defined @$taglist) {
+ foreach my $entry (@$taglist) {
+ my %tag = %$entry;
+ if ($alternate) {
+ print "<tr class=\"dark\">\n";
+ } else {
+ print "<tr class=\"light\">\n";
+ }
+ $alternate ^= 1;
+ print "<td><i>$tag{'age'}</i></td>\n" .
+ "<td>" .
+ $cgi->a({-href => "$my_uri?p=$project;a=shortlog;h=$tag{'name'}", -class => "list"}, "<b>" . escapeHTML($tag{'name'}) . "</b>") .
+ "</td>\n" .
+ "<td class=\"link\">" .
+ $cgi->a({-href => "$my_uri?p=$project;a=shortlog;h=$tag{'name'}"}, "shortlog") .
+ " | " . $cgi->a({-href => "$my_uri?p=$project;a=log;h=$tag{'name'}"}, "log") .
+ "</td>\n" .
+ "</tr>";
+ }
+ }
+ print "</table\n>";
+ git_footer_html();
+}
+
+sub git_get_hash_by_path {
+ my $base = shift;
+ my $path = shift || return undef;
+
+ my $tree = $base;
+ my @parts = split '/', $path;
+ while (my $part = shift @parts) {
+ open my $fd, "-|", "$gitbin/git-ls-tree $tree" or die_error(undef, "Open git-ls-tree failed.");
+ my (@entries) = map { chomp; $_ } <$fd>;
+ close $fd or return undef;
+ foreach my $line (@entries) {
+ #'100644 blob 0fa3f3a66fb6a137f6ec2c19351ed4d807070ffa panic.c'
+ $line =~ m/^([0-9]+) (.+) ([0-9a-fA-F]{40})\t(.+)$/;
+ my $t_mode = $1;
+ my $t_type = $2;
+ my $t_hash = $3;
+ my $t_name = $4;
+ if ($t_name eq $part) {
+ if (!(@parts)) {
+ return $t_hash;
+ }
+ if ($t_type eq "tree") {
+ $tree = $t_hash;
+ }
+ last;
+ }
+ }
+ }
+}
+
+sub git_blob {
+ if (!defined $hash && defined $file_name) {
+ my $base = $hash_base || git_read_hash("$project/HEAD");
+ $hash = git_get_hash_by_path($base, $file_name, "blob");
+ }
+ open my $fd, "-|", "$gitbin/git-cat-file blob $hash" or die_error(undef, "Open failed.");
+ my $base = $file_name || "";
+ git_header_html();
+ if (defined $hash_base && (my %co = git_read_commit($hash_base))) {
+ print "<div class=\"page_nav\">\n" .
+ $cgi->a({-href => "$my_uri?p=$project;a=summary"}, "summary") .
+ " | " . $cgi->a({-href => "$my_uri?p=$project;a=shortlog"}, "shortlog") .
+ " | " . $cgi->a({-href => "$my_uri?p=$project;a=log"}, "log") .
+ " | " . $cgi->a({-href => "$my_uri?p=$project;a=commit;h=$hash_base"}, "commit") .
+ " | " . $cgi->a({-href => "$my_uri?p=$project;a=commitdiff;h=$hash_base"}, "commitdiff") .
+ " | " . $cgi->a({-href => "$my_uri?p=$project;a=tree;h=$co{'tree'};hb=$hash_base"}, "tree") . "<br/>\n";
+ print $cgi->a({-href => "$my_uri?p=$project;a=blob_plain;h=$hash"}, "plain") . "<br/>\n" .
+ "</div>\n";
+ print "<div>" .
+ $cgi->a({-href => "$my_uri?p=$project;a=commit;h=$hash_base", -class => "title"}, escapeHTML($co{'title'})) .
+ "</div>\n";
+ } else {
+ print "<div class=\"page_nav\">\n" .
+ "<br/><br/></div>\n" .
+ "<div class=\"title\">$hash</div>\n";
+ }
+ if (defined $file_name) {
+ print "<div class=\"page_path\"><b>$file_name</b></div>\n";
+ }
+ print "<div class=\"page_body\">\n";