X-Git-Url: https://git.ladys.computer/Gitweb/blobdiff_plain/7028df23897649c2a5a51b69ef58f4e53e330aa179a95227d5f809c88688f427..2f7a833204640ff60aa57cb577ffe5b32c8409e91acea52b4602d6e85b4d7a30:/gitweb.perl diff --git a/gitweb.perl b/gitweb.perl index dcef80a..4673a69 100755 --- a/gitweb.perl +++ b/gitweb.perl @@ -760,6 +760,7 @@ our @cgi_param_mapping = ( extra_options => "opt", search_use_regexp => "sr", ctag => "by_tag", + diff_style => "ds", # this must be last entry (for manipulation from JavaScript) javascript => "js" ); @@ -2318,28 +2319,27 @@ sub format_cc_diff_chunk_header { return $line; } -# format patch (diff) line (not to be used for diff headers) -sub format_diff_line { +# process patch (diff) line (not to be used for diff headers), +# returning class and HTML-formatted (but not wrapped) line +sub process_diff_line { my $line = shift; my ($from, $to) = @_; my $diff_class = diff_line_class($line, $from, $to); - my $diff_classes = "diff"; - $diff_classes .= " $diff_class" if ($diff_class); chomp $line; $line = untabify($line); if ($from && $to && $line =~ m/^\@{2} /) { $line = format_unidiff_chunk_header($line, $from, $to); - return "
$line
\n"; + return $diff_class, $line; } elsif ($from && $to && $line =~ m/^\@{3}/) { $line = format_cc_diff_chunk_header($line, $from, $to); - return "
$line
\n"; + return $diff_class, $line; } - return "
" . esc_html($line, -nbsp=>1) . "
\n"; + return $diff_class, esc_html($line, -nbsp=>1); } # Generates undef or something like "_snapshot_" or "snapshot (_tbz2_ _zip_)", @@ -4861,8 +4861,97 @@ sub git_difftree_body { print "\n"; } +sub print_sidebyside_diff_chunk { + my @chunk = @_; + my (@ctx, @rem, @add); + + return unless @chunk; + + # incomplete last line might be among removed or added lines, + # or both, or among context lines: find which + for (my $i = 1; $i < @chunk; $i++) { + if ($chunk[$i][0] eq 'incomplete') { + $chunk[$i][0] = $chunk[$i-1][0]; + } + } + + # guardian + push @chunk, ["", ""]; + + foreach my $line_info (@chunk) { + my ($class, $line) = @$line_info; + + # print chunk headers + if ($class && $class eq 'chunk_header') { + print $line; + next; + } + + ## print from accumulator when type of class of lines change + # empty contents block on start rem/add block, or end of chunk + if (@ctx && (!$class || $class eq 'rem' || $class eq 'add')) { + print join '', + '
', + '
', + @ctx, + '
', + '
', + @ctx, + '
', + '
'; + @ctx = (); + } + # empty add/rem block on start context block, or end of chunk + if ((@rem || @add) && (!$class || $class eq 'ctx')) { + if (!@add) { + # pure removal + print join '', + '
', + '
', + @rem, + '
', + '
'; + } elsif (!@rem) { + # pure addition + print join '', + '
', + '
', + @add, + '
', + '
'; + } else { + # assume that it is change + print join '', + '
', + '
', + @rem, + '
', + '
', + @add, + '
', + '
'; + } + @rem = @add = (); + } + + ## adding lines to accumulator + # guardian value + last unless $line; + # rem, add or change + if ($class eq 'rem') { + push @rem, $line; + } elsif ($class eq 'add') { + push @add, $line; + } + # context line + if ($class eq 'ctx') { + push @ctx, $line; + } + } +} + sub git_patchset_body { - my ($fd, $difftree, $hash, @hash_parents) = @_; + my ($fd, $diff_style, $difftree, $hash, @hash_parents) = @_; my ($hash_parent) = $hash_parents[0]; my $is_combined = (@hash_parents > 1); @@ -4872,6 +4961,7 @@ sub git_patchset_body { my $diffinfo; my $to_name; my (%from, %to); + my @chunk; # for side-by-side diff print "
\n"; @@ -4978,10 +5068,29 @@ sub git_patchset_body { next PATCH if ($patch_line =~ m/^diff /); - print format_diff_line($patch_line, \%from, \%to); + my ($class, $line) = process_diff_line($patch_line, \%from, \%to); + my $diff_classes = "diff"; + $diff_classes .= " $class" if ($class); + $line = "
$line
\n"; + + if ($diff_style eq 'sidebyside' && !$is_combined) { + if ($class eq 'chunk_header') { + print_sidebyside_diff_chunk(@chunk); + @chunk = ( [ $class, $line ] ); + } else { + push @chunk, [ $class, $line ]; + } + } else { + # default 'inline' style and unknown styles + print $line; + } } } continue { + if (@chunk) { + print_sidebyside_diff_chunk(@chunk); + @chunk = (); + } print "
\n"; # class="patch" } @@ -6977,6 +7086,7 @@ sub git_object { sub git_blobdiff { my $format = shift || 'html'; + my $diff_style = $input_params{'diff_style'} || 'inline'; my $fd; my @difftree; @@ -7086,7 +7196,8 @@ sub git_blobdiff { if ($format eq 'html') { print "
\n"; - git_patchset_body($fd, [ \%diffinfo ], $hash_base, $hash_parent_base); + git_patchset_body($fd, $diff_style, + [ \%diffinfo ], $hash_base, $hash_parent_base); close $fd; print "
\n"; # class="page_body" @@ -7114,6 +7225,7 @@ sub git_blobdiff_plain { sub git_commitdiff { my %params = @_; my $format = $params{-format} || 'html'; + my $diff_style = $input_params{'diff_style'} || 'inline'; my ($patch_max) = gitweb_get_feature('patches'); if ($format eq 'patch') { @@ -7317,7 +7429,8 @@ sub git_commitdiff { $use_parents ? @{$co{'parents'}} : $hash_parent); print "
\n"; - git_patchset_body($fd, \@difftree, $hash, + git_patchset_body($fd, $diff_style, + \@difftree, $hash, $use_parents ? @{$co{'parents'}} : $hash_parent); close $fd; print "\n"; # class="page_body"