diff options
author | Florian Forster <octo@verplant.org> | 2006-06-11 19:45:19 +0400 |
---|---|---|
committer | Junio C Hamano <junkio@cox.net> | 2006-06-17 09:45:11 +0400 |
commit | e34ef621482a14143187bb99a8e341fad885c5d5 (patch) | |
tree | 9aff666f6b0b219590349eb7669ab54263bc7710 | |
parent | 8f732649bc4d5619a1b399e5808b3f4c662ad200 (diff) |
gitweb: Adding a `blame' interface.
This patch adds an interface for `git-blame' to `gitweb.cgi'.
Links to it are placed in `git_blob'.
Internally the code uses `git-annotate' because `git-blame's output
differs for files that have been renamed in the past. However, I like
the term `blame' better.
[jc: blame can be told to produce the compatible format btw...]
Signed-off-by: Florian Forster <octo@verplant.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
-rwxr-xr-x | gitweb/gitweb.cgi | 108 |
1 files changed, 107 insertions, 1 deletions
diff --git a/gitweb/gitweb.cgi b/gitweb/gitweb.cgi index ea21fbe88a..91c075df3a 100755 --- a/gitweb/gitweb.cgi +++ b/gitweb/gitweb.cgi @@ -203,6 +203,9 @@ if (!defined $action || $action eq "summary") { } elsif ($action eq "tag") { git_tag(); exit; +} elsif ($action eq "blame") { + git_blame(); + exit; } else { undef $action; die_error(undef, "Unknown action."); @@ -1228,6 +1231,107 @@ sub git_tag { git_footer_html(); } +sub git_blame { + my $fd; + die_error('404 Not Found', "What file will it be, master?") if (!$file_name); + $hash_base ||= git_read_head($project); + die_error(undef, "Reading commit failed.") unless ($hash_base); + my %co = git_read_commit($hash_base) + or die_error(undef, "Reading commit failed."); + if (!defined $hash) { + $hash = git_get_hash_by_path($hash_base, $file_name, "blob") + or die_error(undef, "Error lookup file."); + } + open ($fd, "-|", "$gitbin/git-annotate", '-l', '-t', '-r', $file_name, $hash_base) + or die_error(undef, "Open failed."); + git_header_html(); + print "<div class=\"page_nav\">\n" . + $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=summary")}, "summary") . + " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=shortlog")}, "shortlog") . + " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=log")}, "log") . + " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commit;h=$hash_base")}, "commit") . + " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commitdiff;h=$hash_base")}, "commitdiff") . + " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=tree;h=$co{'tree'};hb=$hash_base")}, "tree") . "<br/>\n"; + print $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=blob;h=$hash;hb=$hash_base;f=$file_name")}, "blob") . + " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=blame;f=$file_name")}, "head") . "<br/>\n"; + print "</div>\n". + "<div>" . + $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commit;h=$hash_base"), -class => "title"}, esc_html($co{'title'})) . + "</div>\n"; + print "<div class=\"page_path\"><b>" . esc_html($file_name) . "</b></div>\n"; + print "<div class=\"page_body\">\n"; + print <<HTML; +<table style="border-collapse: collapse;"> + <tr> + <th>Commit</th> + <th>Age</th> + <th>Author</th> + <th>Line</th> + <th>Data</th> + </tr> +HTML + my @line_class = (qw(light dark)); + my $line_class_len = scalar (@line_class); + my $line_class_num = $#line_class; + while (my $line = <$fd>) { + my $long_rev; + my $short_rev; + my $author; + my $time; + my $lineno; + my $data; + my $age; + my $age_str; + my $age_style; + + chomp $line; + $line_class_num = ($line_class_num + 1) % $line_class_len; + + if ($line =~ m/^([0-9a-fA-F]{40})\t\(\s*([^\t]+)\t(\d+) \+\d\d\d\d\t(\d+)\)(.*)$/) { + $long_rev = $1; + $author = $2; + $time = $3; + $lineno = $4; + $data = $5; + } else { + print qq( <tr><td colspan="5" style="color: red; background-color: yellow;">Unable to parse: $line</td></tr>\n); + next; + } + $short_rev = substr ($long_rev, 0, 8); + $age = time () - $time; + $age_str = age_string ($age); + $age_str =~ s/ / /g; + $age_style = 'font-style: italic;'; + $age_style .= ' color: #009900; background: transparent;' if ($age < 60*60*24*2); + $age_style .= ' font-weight: bold;' if ($age < 60*60*2); + $author = esc_html ($author); + $author =~ s/ / /g; + # escape tabs + while ((my $pos = index($data, "\t")) != -1) { + if (my $count = (8 - ($pos % 8))) { + my $spaces = ' ' x $count; + $data =~ s/\t/$spaces/; + } + } + $data = esc_html ($data); + $data =~ s/ / /g; + + print <<HTML; + <tr class="$line_class[$line_class_num]"> + <td style="font-family: monospace;"><a href="$my_uri?${\esc_param ("p=$project;a=commit;h=$long_rev")}" class="text">$short_rev..</a></td> + <td style="$age_style">$age_str</td> + <td>$author</td> + <td style="text-align: right;"><a id="$lineno" href="#$lineno" class="linenr">$lineno</a></td> + <td style="font-family: monospace;">$data</td> + </tr> +HTML + } # while (my $line = <$fd>) + print "</table>\n\n"; + close $fd or print "Reading blob failed.\n"; + print "</div>"; + git_footer_html(); +} + sub git_tags { my $head = git_read_head($project); git_header_html(); @@ -1375,7 +1479,8 @@ sub git_blob { " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commitdiff;h=$hash_base")}, "commitdiff") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=tree;h=$co{'tree'};hb=$hash_base")}, "tree") . "<br/>\n"; if (defined $file_name) { - print $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=blob_plain;h=$hash;f=$file_name")}, "plain") . + print $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=blame;h=$hash;hb=$hash_base;f=$file_name")}, "blame") . + " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=blob_plain;h=$hash;f=$file_name")}, "plain") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=blob;hb=HEAD;f=$file_name")}, "head") . "<br/>\n"; } else { print $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=blob_plain;h=$hash")}, "plain") . "<br/>\n"; @@ -1496,6 +1601,7 @@ sub git_tree { "</td>\n" . "<td class=\"link\">" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=blob;h=$t_hash$base_key;f=$base$t_name")}, "blob") . +# " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=blame;h=$t_hash$base_key;f=$base$t_name")}, "blame") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=history;h=$hash_base;f=$base$t_name")}, "history") . "</td>\n"; } elsif ($t_type eq "tree") { |