sub href(%) {
my %params = @_;
- my $href = $my_uri;
+ # default is to use -absolute url() i.e. $my_uri
+ my $href = $params{-full} ? $my_url : $my_uri;
# XXX: Warning: If you touch this, check the search form for updating,
# too.
}
}
+# format patch (diff) line (rather not to be used for diff headers)
sub format_diff_line {
my $line = shift;
+ my ($from, $to) = @_;
my $char = substr($line, 0, 1);
my $diff_class = "";
$diff_class = " incomplete";
}
$line = untabify($line);
+ if ($from && $to && $line =~ m/^\@{2} /) {
+ my ($from_text, $from_start, $from_lines, $to_text, $to_start, $to_lines, $section) =
+ $line =~ m/^\@{2} (-(\d+)(?:,(\d+))?) (\+(\d+)(?:,(\d+))?) \@{2}(.*)$/;
+
+ $from_lines = 0 unless defined $from_lines;
+ $to_lines = 0 unless defined $to_lines;
+
+ if ($from->{'href'}) {
+ $from_text = $cgi->a({-href=>"$from->{'href'}#l$from_start",
+ -class=>"list"}, $from_text);
+ }
+ if ($to->{'href'}) {
+ $to_text = $cgi->a({-href=>"$to->{'href'}#l$to_start",
+ -class=>"list"}, $to_text);
+ }
+ $line = "<span class=\"chunk_info\">@@ $from_text $to_text @@</span>" .
+ "<span class=\"section\">" . esc_html($section, -nbsp=>1) . "</span>";
+ return "<div class=\"diff$diff_class\">$line</div>\n";
+ }
return "<div class=\"diff$diff_class\">" . esc_html($line, -nbsp=>1) . "</div>\n";
}
my ($fd, $difftree, $hash, $hash_parent) = @_;
my $patch_idx = 0;
- my $in_header = 0;
- my $patch_found = 0;
+ my $patch_line;
my $diffinfo;
my (%from, %to);
+ my ($from_id, $to_id);
print "<div class=\"patchset\">\n";
- LINE:
- while (my $patch_line = <$fd>) {
+ # skip to first patch
+ while ($patch_line = <$fd>) {
chomp $patch_line;
- if ($patch_line =~ m/^diff /) { # "git diff" header
- # beginning of patch (in patchset)
- if ($patch_found) {
- # close extended header for previous empty patch
- if ($in_header) {
- print "</div>\n" # class="diff extended_header"
- }
- # close previous patch
- print "</div>\n"; # class="patch"
- } else {
- # first patch in patchset
- $patch_found = 1;
+ last if ($patch_line =~ m/^diff /);
+ }
+
+ PATCH:
+ while ($patch_line) {
+ my @diff_header;
+
+ # git diff header
+ #assert($patch_line =~ m/^diff /) if DEBUG;
+ #assert($patch_line !~ m!$/$!) if DEBUG; # is chomp-ed
+ push @diff_header, $patch_line;
+
+ # extended diff header
+ EXTENDED_HEADER:
+ while ($patch_line = <$fd>) {
+ chomp $patch_line;
+
+ last EXTENDED_HEADER if ($patch_line =~ m/^--- /);
+
+ if ($patch_line =~ m/^index ([0-9a-fA-F]{40})..([0-9a-fA-F]{40})/) {
+ $from_id = $1;
+ $to_id = $2;
}
- print "<div class=\"patch\" id=\"patch". ($patch_idx+1) ."\">\n";
+
+ 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
+ # and parse raw git-diff line if needed
+ if (defined $diffinfo &&
+ $diffinfo->{'from_id'} eq $from_id &&
+ $diffinfo->{'to_id'} eq $to_id) {
+ # this is split patch
+ print "<div class=\"patch cont\">\n";
+ } else {
+ # advance raw git-diff output if needed
+ $patch_idx++ if defined $diffinfo;
# read and prepare patch information
if (ref($difftree->[$patch_idx]) eq "HASH") {
hash=>$diffinfo->{'to_id'},
file_name=>$to{'file'});
}
- $patch_idx++;
-
- # print "git diff" header
- $patch_line =~ s!^(diff (.*?) )"?a/.*$!$1!;
- if ($from{'href'}) {
- $patch_line .= $cgi->a({-href => $from{'href'}, -class => "path"},
- 'a/' . esc_path($from{'file'}));
- } else { # file was added
- $patch_line .= 'a/' . esc_path($from{'file'});
- }
- $patch_line .= ' ';
- if ($to{'href'}) {
- $patch_line .= $cgi->a({-href => $to{'href'}, -class => "path"},
- 'b/' . esc_path($to{'file'}));
- } else { # file was deleted
- $patch_line .= 'b/' . esc_path($to{'file'});
- }
-
- print "<div class=\"diff header\">$patch_line</div>\n";
- print "<div class=\"diff extended_header\">\n";
- $in_header = 1;
- next LINE;
+ # this is first patch for raw difftree line with $patch_idx index
+ # we index @$difftree array from 0, but number patches from 1
+ print "<div class=\"patch\" id=\"patch". ($patch_idx+1) ."\">\n";
}
- if ($in_header) {
- if ($patch_line !~ m/^---/) {
- # 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'}));
- }
- if ($patch_line =~ s!^((copy|rename) to ).*$!$1! && $to{'href'}) {
- $patch_line = $cgi->a({-href=>$to{'href'}, -class=>"path"},
- esc_path($to{'file'}));
- }
- # match <mode>
- if ($patch_line =~ m/\s(\d{6})$/) {
- $patch_line .= '<span class="info"> (' .
- file_type_long($1) .
- ')</span>';
+ # print "git diff" header
+ $patch_line = shift @diff_header;
+ $patch_line =~ s!^(diff (.*?) )"?a/.*$!$1!;
+ if ($from{'href'}) {
+ $patch_line .= $cgi->a({-href => $from{'href'}, -class => "path"},
+ 'a/' . esc_path($from{'file'}));
+ } else { # file was added
+ $patch_line .= 'a/' . esc_path($from{'file'});
+ }
+ $patch_line .= ' ';
+ if ($to{'href'}) {
+ $patch_line .= $cgi->a({-href => $to{'href'}, -class => "path"},
+ 'b/' . esc_path($to{'file'}));
+ } else { # file was deleted
+ $patch_line .= 'b/' . esc_path($to{'file'});
+ }
+ print "<div class=\"diff header\">$patch_line</div>\n";
+
+ # print extended diff header
+ print "<div class=\"diff extended_header\">\n" if (@diff_header > 0);
+ EXTENDED_HEADER:
+ foreach $patch_line (@diff_header) {
+ # 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'}));
+ }
+ if ($patch_line =~ s!^((copy|rename) to ).*$!$1! && $to{'href'}) {
+ $patch_line = $cgi->a({-href=>$to{'href'}, -class=>"path"},
+ esc_path($to{'file'}));
+ }
+ # match <mode>
+ if ($patch_line =~ m/\s(\d{6})$/) {
+ $patch_line .= '<span class="info"> (' .
+ file_type_long($1) .
+ ')</span>';
+ }
+ # match <hash>
+ if ($patch_line =~ m/^index/) {
+ my ($from_link, $to_link);
+ if ($from{'href'}) {
+ $from_link = $cgi->a({-href=>$from{'href'}, -class=>"hash"},
+ substr($diffinfo->{'from_id'},0,7));
+ } else {
+ $from_link = '0' x 7;
}
- # match <hash>
- if ($patch_line =~ m/^index/) {
- my ($from_link, $to_link);
- if ($from{'href'}) {
- $from_link = $cgi->a({-href=>$from{'href'}, -class=>"hash"},
- substr($diffinfo->{'from_id'},0,7));
- } else {
- $from_link = '0' x 7;
- }
- if ($to{'href'}) {
- $to_link = $cgi->a({-href=>$to{'href'}, -class=>"hash"},
- substr($diffinfo->{'to_id'},0,7));
- } else {
- $to_link = '0' x 7;
- }
- my ($from_id, $to_id) = ($diffinfo->{'from_id'}, $diffinfo->{'to_id'});
- $patch_line =~ s!$from_id\.\.$to_id!$from_link..$to_link!;
+ if ($to{'href'}) {
+ $to_link = $cgi->a({-href=>$to{'href'}, -class=>"hash"},
+ substr($diffinfo->{'to_id'},0,7));
+ } else {
+ $to_link = '0' x 7;
}
- print $patch_line . "<br/>\n";
-
- } else {
- #$in_header && $patch_line =~ m/^---/;
- print "</div>\n"; # class="diff extended_header"
- $in_header = 0;
+ #affirm {
+ # my ($from_hash, $to_hash) =
+ # ($patch_line =~ m/^index ([0-9a-fA-F]{40})..([0-9a-fA-F]{40})/);
+ # my ($from_id, $to_id) =
+ # ($diffinfo->{'from_id'}, $diffinfo->{'to_id'});
+ # ($from_hash eq $from_id) && ($to_hash eq $to_id);
+ #} if DEBUG;
+ my ($from_id, $to_id) = ($diffinfo->{'from_id'}, $diffinfo->{'to_id'});
+ $patch_line =~ s!$from_id\.\.$to_id!$from_link..$to_link!;
+ }
+ print $patch_line . "<br/>\n";
+ }
+ print "</div>\n" if (@diff_header > 0); # class="diff extended_header"
+
+ # from-file/to-file diff header
+ $patch_line = $last_patch_line;
+ #assert($patch_line =~ m/^---/) if DEBUG;
+ if ($from{'href'}) {
+ $patch_line = '--- a/' .
+ $cgi->a({-href=>$from{'href'}, -class=>"path"},
+ esc_path($from{'file'}));
+ }
+ print "<div class=\"diff from_file\">$patch_line</div>\n";
- if ($from{'href'}) {
- $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;
- $patch_line = <$fd>;
- chomp $patch_line;
+ #assert($patch_line =~ m/^+++/) if DEBUG;
+ if ($to{'href'}) {
+ $patch_line = '+++ b/' .
+ $cgi->a({-href=>$to{'href'}, -class=>"path"},
+ esc_path($to{'file'}));
+ }
+ print "<div class=\"diff to_file\">$patch_line</div>\n";
- #$patch_line =~ m/^+++/;
- if ($to{'href'}) {
- $patch_line = '+++ b/' .
- $cgi->a({-href=>$to{'href'}, -class=>"path"},
- esc_path($to{'file'}));
- }
- print "<div class=\"diff to_file\">$patch_line</div>\n";
+ # the patch itself
+ LINE:
+ while ($patch_line = <$fd>) {
+ chomp $patch_line;
- }
+ next PATCH if ($patch_line =~ m/^diff /);
- next LINE;
+ print format_diff_line($patch_line, \%from, \%to);
}
- print format_diff_line($patch_line);
+ } continue {
+ print "</div>\n"; # class="patch"
}
- print "</div>\n" if $patch_found; # class="patch"
print "</div>\n"; # class="patchset"
}
$pr->{'age_string'} . "</td>\n" .
"<td class=\"link\">" .
$cgi->a({-href => href(project=>$pr->{'path'}, action=>"summary")}, "summary") . " | " .
- $cgi->a({-href => '/git-browser/by-commit.html?r='.$pr->{'path'}}, "graphiclog") . " | " .
+ $cgi->a({-href => href(project=>$pr->{'path'}, action=>"shortlog")}, "shortlog") . " | " .
$cgi->a({-href => href(project=>$pr->{'path'}, action=>"log")}, "log") . " | " .
$cgi->a({-href => href(project=>$pr->{'path'}, action=>"tree")}, "tree") .
($pr->{'forks'} ? " | " . $cgi->a({-href => href(project=>$pr->{'path'}, action=>"forks")}, "forks") : '') .
}
sub git_commit {
+ $hash ||= $hash_base || "HEAD";
my %co = parse_commit($hash);
if (!%co) {
die_error(undef, "Unknown commit object");
sub git_commitdiff {
my $format = shift || 'html';
+ $hash ||= $hash_base || "HEAD";
my %co = parse_commit($hash);
if (!%co) {
die_error(undef, "Unknown commit object");
$hash_parent, $hash, "--"
or die_error(undef, "Open git-diff-tree failed");
- while (chomp(my $line = <$fd>)) {
+ while (my $line = <$fd>) {
+ chomp $line;
# empty line ends raw part of diff-tree output
last unless $line;
push @difftree, $line;