binmode STDOUT, ':utf8';
BEGIN {
- CGI->compile() if $ENV{MOD_PERL};
+ CGI->compile() if $ENV{'MOD_PERL'};
}
our $cgi = new CGI;
my %opts = @_;
$str = to_utf8($str);
- $str = escapeHTML($str);
+ $str = $cgi->escapeHTML($str);
if ($opts{'-nbsp'}) {
$str =~ s/ / /g;
}
my %opts = @_;
$str = to_utf8($str);
- $str = escapeHTML($str);
+ $str = $cgi->escapeHTML($str);
if ($opts{'-nbsp'}) {
$str =~ s/ / /g;
}
## ----------------------------------------------------------------------
## functions returning short HTML fragments, or transforming HTML fragments
-## which don't beling to other sections
+## which don't belong to other sections
# format line of commit message.
sub format_log_line_html {
$key =~ s/^gitweb\.//;
return if ($key =~ m/\W/);
- my @x = (git_cmd(), 'repo-config');
+ my @x = (git_cmd(), 'config');
if (defined $type) { push @x, $type; }
push @x, "--get";
push @x, "gitweb.$key";
my $title = "$site_name";
if (defined $project) {
- $title .= " - $project";
+ $title .= " - " . to_utf8($project);
if (defined $action) {
$title .= "/$action";
if (defined $file_name) {
$cgi->hidden(-name => "a") . "\n" .
$cgi->hidden(-name => "h") . "\n" .
$cgi->popup_menu(-name => 'st', -default => 'commit',
- -values => ['commit', 'author', 'committer', 'pickaxe']) .
+ -values => ['commit', 'author', 'committer', 'pickaxe']) .
$cgi->sup($cgi->a({-href => href(action=>"search_help")}, "?")) .
" search:\n",
$cgi->textfield(-name => "s", -value => $searchtext) . "\n" .
my %arg = map { $_ => {action=>$_} } @navs;
if (defined $head) {
for (qw(commit commitdiff)) {
- $arg{$_}{hash} = $head;
+ $arg{$_}{'hash'} = $head;
}
if ($current =~ m/^(tree | log | shortlog | commit | commitdiff | search)$/x) {
for (qw(shortlog log)) {
- $arg{$_}{hash} = $head;
+ $arg{$_}{'hash'} = $head;
}
}
}
- $arg{tree}{hash} = $treehead if defined $treehead;
- $arg{tree}{hash_base} = $treebase if defined $treebase;
+ $arg{'tree'}{'hash'} = $treehead if defined $treehead;
+ $arg{'tree'}{'hash_base'} = $treebase if defined $treebase;
print "<div class=\"page_nav\">\n" .
(join " | ",
my ($action, $title, $hash, $hash_base) = @_;
my %args = ();
- $args{action} = $action;
- $args{hash} = $hash if $hash;
- $args{hash_base} = $hash_base if $hash_base;
+ $args{'action'} = $action;
+ $args{'hash'} = $hash if $hash;
+ $args{'hash_base'} = $hash_base if $hash_base;
print "<div class=\"header\">\n" .
$cgi->a({-href => href(%args), -class => "title"},
print "<div class=\"page_path\">";
print $cgi->a({-href => href(action=>"tree", hash_base=>$hb),
- -title => 'tree root'}, "[$project]");
+ -title => 'tree root'}, to_utf8("[$project]"));
print " / ";
if (defined $name) {
my @dirname = split '/', $name;
$fullname .= ($fullname ? '/' : '') . $dir;
print $cgi->a({-href => href(action=>"tree", file_name=>$fullname,
hash_base=>$hb),
- -title => esc_html($fullname)}, esc_path($dir));
+ -title => $fullname}, esc_path($dir));
print " / ";
}
if (defined $type && $type eq 'blob') {
print $cgi->a({-href => href(action=>"blob_plain", file_name=>$file_name,
hash_base=>$hb),
- -title => esc_html($name)}, esc_path($basename));
+ -title => $name}, esc_path($basename));
} elsif (defined $type && $type eq 'tree') {
print $cgi->a({-href => href(action=>"tree", file_name=>$file_name,
hash_base=>$hb),
- -title => esc_html($name)}, esc_path($basename));
+ -title => $name}, esc_path($basename));
print " / ";
} else {
print esc_path($basename);
}
print $cgi->a({-href => href(action=>"blob", hash=>$diff{'to_id'},
hash_base=>$hash, file_name=>$diff{'file'})},
- "blob") . " | ";
+ "blob");
print "</td>\n";
} elsif ($diff{'status'} eq "D") { # deleted
my $patch_line;
my $diffinfo;
my (%from, %to);
- my ($from_id, $to_id);
print "<div class=\"patchset\">\n";
PATCH:
while ($patch_line) {
my @diff_header;
+ my ($from_id, $to_id);
# git diff header
#assert($patch_line =~ m/^diff /) if DEBUG;
while ($patch_line = <$fd>) {
chomp $patch_line;
- last EXTENDED_HEADER if ($patch_line =~ m/^--- /);
+ last EXTENDED_HEADER if ($patch_line =~ m/^--- |^diff /);
if ($patch_line =~ m/^index ([0-9a-fA-F]{40})..([0-9a-fA-F]{40})/) {
$from_id = $1;
push @diff_header, $patch_line;
}
- #last PATCH unless $patch_line;
my $last_patch_line = $patch_line;
# check if current patch belong to current raw line
$from{'href'} = href(action=>"blob", hash_base=>$hash_parent,
hash=>$diffinfo->{'from_id'},
file_name=>$from{'file'});
+ } else {
+ delete $from{'href'};
}
if ($diffinfo->{'status'} ne "D") { # not deleted file
$to{'href'} = href(action=>"blob", hash_base=>$hash,
hash=>$diffinfo->{'to_id'},
file_name=>$to{'file'});
+ } else {
+ delete $to{'href'};
}
# this is first patch for raw difftree line with $patch_idx index
# we index @$difftree array from 0, but number patches from 1
# match <path>
if ($patch_line =~ s!^((copy|rename) from ).*$!$1! && $from{'href'}) {
$patch_line .= $cgi->a({-href=>$from{'href'}, -class=>"path"},
- esc_path($from{'file'}));
+ esc_path($from{'file'}));
}
if ($patch_line =~ s!^((copy|rename) to ).*$!$1! && $to{'href'}) {
- $patch_line = $cgi->a({-href=>$to{'href'}, -class=>"path"},
- esc_path($to{'file'}));
+ $patch_line .= $cgi->a({-href=>$to{'href'}, -class=>"path"},
+ esc_path($to{'file'}));
}
# match <mode>
if ($patch_line =~ m/\s(\d{6})$/) {
# from-file/to-file diff header
$patch_line = $last_patch_line;
+ if (! $patch_line) {
+ print "</div>\n"; # class="patch"
+ last PATCH;
+ }
+ next PATCH if ($patch_line =~ m/^diff /);
#assert($patch_line =~ m/^---/) if DEBUG;
- if ($from{'href'}) {
+ if ($from{'href'} && $patch_line =~ m!^--- "?a/!) {
$patch_line = '--- a/' .
$cgi->a({-href=>$from{'href'}, -class=>"path"},
esc_path($from{'file'}));
print "<div class=\"diff from_file\">$patch_line</div>\n";
$patch_line = <$fd>;
- #last PATCH unless $patch_line;
chomp $patch_line;
#assert($patch_line =~ m/^+++/) if DEBUG;
- if ($to{'href'}) {
+ if ($to{'href'} && $patch_line =~ m!^\+\+\+ "?b/!) {
$patch_line = '+++ b/' .
$cgi->a({-href=>$to{'href'}, -class=>"path"},
esc_path($to{'file'}));
print "<tr class=\"light\">\n";
}
$alternate ^= 1;
- print "<td><i>$tag{'age'}</i></td>\n" .
- "<td>" .
+ if (defined $tag{'age'}) {
+ print "<td><i>$tag{'age'}</i></td>\n";
+ } else {
+ print "<td></td>\n";
+ }
+ print "<td>" .
$cgi->a({-href => href(action=>$tag{'reftype'}, hash=>$tag{'refid'}),
-class => "list name"}, esc_html($tag{'name'})) .
"</td>\n" .
git_project_list_body(\@forklist, undef, 0, 15,
$#forklist <= 15 ? undef :
$cgi->a({-href => href(action=>"forks")}, "..."),
- 'noheader');
+ 'noheader');
}
git_footer_html();
}
$ftype = git_get_type($hash);
if ($ftype !~ "blob") {
- die_error("400 Bad Request", "Object is not a blob");
+ die_error('400 Bad Request', "Object is not a blob");
}
open ($fd, "-|", git_cmd(), "blame", '-p', '--',
$file_name, $hash_base)
my $rev = substr($full_rev, 0, 8);
my $author = $meta->{'author'};
my %date = parse_date($meta->{'author-time'},
- $meta->{'author-tz'});
+ $meta->{'author-tz'});
my $date = $date{'iso-tz'};
if ($group_size) {
$current_color = ++$current_color % $num_colors;
print " rowspan=\"$group_size\"" if ($group_size > 1);
print ">";
print $cgi->a({-href => href(action=>"commit",
- hash=>$full_rev,
- file_name=>$file_name)},
- esc_html($rev));
+ hash=>$full_rev,
+ file_name=>$file_name)},
+ esc_html($rev));
print "</td>\n";
}
+ open (my $dd, "-|", git_cmd(), "rev-parse", "$full_rev^")
+ or die_error(undef, "Open git-rev-parse failed");
+ my $parent_commit = <$dd>;
+ close $dd;
+ chomp($parent_commit);
my $blamed = href(action => 'blame',
- file_name => $meta->{'filename'},
- hash_base => $full_rev);
+ file_name => $meta->{'filename'},
+ hash_base => $parent_commit);
print "<td class=\"linenr\">";
print $cgi->a({ -href => "$blamed#l$orig_lineno",
- -id => "l$lineno",
- -class => "linenr" },
- esc_html($lineno));
+ -id => "l$lineno",
+ -class => "linenr" },
+ esc_html($lineno));
print "</td>";
print "<td class=\"pre\">" . esc_html($data) . "</td>\n";
print "</tr>\n";
$hash = git_get_head_hash($project);
}
- my $filename = basename($project) . "-$hash.tar.$suffix";
+ my $filename = to_utf8(basename($project)) . "-$hash.tar.$suffix";
print $cgi->header(
-type => "application/$ctype",
my $name = $project;
$name =~ s/\047/\047\\\047\047/g;
open my $fd, "-|",
- "$git archive --format=tar --prefix=\'$name\'/ $hash | $command"
- or die_error(undef, "Execute git-tar-tree failed.");
+ "$git archive --format=tar --prefix=\'$name\'/ $hash | $command"
+ or die_error(undef, "Execute git-tar-tree failed");
binmode STDOUT, ':raw';
print <$fd>;
binmode STDOUT, ':utf8'; # as set at the beginning of gitweb.cgi
$formats_nav .=
'(merge: ' .
join(' ', map {
- $cgi->a({-href => href(action=>"commitdiff",
+ $cgi->a({-href => href(action=>"commit",
hash=>$_)},
esc_html(substr($_, 0, 7)));
} @$parents ) .
# difftree output is not printed for merges
open my $fd, "-|", git_cmd(), "diff-tree", '-r', "--no-commit-id",
@diff_opts, $parent, $hash, "--"
- or die_error(undef, "Open git-diff-tree failed");
+ or die_error(undef, "Open git-diff-tree failed");
@difftree = map { chomp; $_ } <$fd>;
close $fd or die_error(undef, "Reading git-diff-tree failed");
}
# read raw output
open $fd, "-|", git_cmd(), "diff-tree", '-r', @diff_opts,
$hash_parent_base, $hash_base,
- "--", $file_name
+ "--", (defined $file_parent ? $file_parent : ()), $file_name
or die_error(undef, "Open git-diff-tree failed");
@difftree = map { chomp; $_ } <$fd>;
close $fd
# open patch output
open $fd, "-|", git_cmd(), "diff-tree", '-r', @diff_opts,
- '-p', $hash_parent_base, $hash_base,
- "--", $file_name
+ '-p', ($format eq 'html' ? "--full-index" : ()),
+ $hash_parent_base, $hash_base,
+ "--", (defined $file_parent ? $file_parent : ()), $file_name
or die_error(undef, "Open git-diff-tree failed");
}
}
# open patch output
- open $fd, "-|", git_cmd(), "diff", '-p', @diff_opts,
+ open $fd, "-|", git_cmd(), "diff", @diff_opts,
+ '-p', ($format eq 'html' ? "--full-index" : ()),
$hash_parent, $hash, "--"
or die_error(undef, "Open git-diff failed");
} else {
if ($page > 0) {
$paging_nav .=
$cgi->a({-href => href(action=>"search", hash=>$hash,
- searchtext=>$searchtext, searchtype=>$searchtype)},
- "first");
+ searchtext=>$searchtext, searchtype=>$searchtype)},
+ "first");
$paging_nav .= " ⋅ " .
$cgi->a({-href => href(action=>"search", hash=>$hash,
- searchtext=>$searchtext, searchtype=>$searchtype,
- page=>$page-1),
- -accesskey => "p", -title => "Alt-p"}, "prev");
+ searchtext=>$searchtext, searchtype=>$searchtype,
+ page=>$page-1),
+ -accesskey => "p", -title => "Alt-p"}, "prev");
} else {
$paging_nav .= "first";
$paging_nav .= " ⋅ prev";
if ($#commitlist >= 100) {
$paging_nav .= " ⋅ " .
$cgi->a({-href => href(action=>"search", hash=>$hash,
- searchtext=>$searchtext, searchtype=>$searchtype,
- page=>$page+1),
- -accesskey => "n", -title => "Alt-n"}, "next");
+ searchtext=>$searchtext, searchtype=>$searchtype,
+ page=>$page+1),
+ -accesskey => "n", -title => "Alt-n"}, "next");
} else {
$paging_nav .= " ⋅ next";
}
if ($#commitlist >= 100) {
$next_link =
$cgi->a({-href => href(action=>"search", hash=>$hash,
- searchtext=>$searchtext, searchtype=>$searchtype,
- page=>$page+1),
- -accesskey => "n", -title => "Alt-n"}, "next");
+ searchtext=>$searchtext, searchtype=>$searchtype,
+ page=>$page+1),
+ -accesskey => "n", -title => "Alt-n"}, "next");
}
git_print_page_nav('','', $hash,$co{'tree'},$hash, $paging_nav);
}
my $refs = git_get_references();
- my @commitlist = parse_commits($head, 101, (100 * $page));
+ my @commitlist = parse_commits($hash, 101, (100 * $page));
my $paging_nav = format_paging_nav('shortlog', $hash, $head, $page, (100 * ($page+1)));
my $next_link = '';