X-Git-Url: https://git.ladys.computer/Gitweb/blobdiff_plain/2ccb4d626f1a8d6c0e15e0c0253e100178d1fc7de65b383e9e090d2f20978bea..9ce9037e27bd821d2e70218588f6f0e673630acda5b2462742cdbb91d518ea60:/gitweb.perl diff --git a/gitweb.perl b/gitweb.perl index 244bde6..0ac67c9 100755 --- a/gitweb.perl +++ b/gitweb.perl @@ -2431,19 +2431,25 @@ sub format_cc_diff_chunk_header { } # process patch (diff) line (not to be used for diff headers), -# returning HTML-formatted (but not wrapped) line +# returning HTML-formatted (but not wrapped) line. +# If the line is passed as a reference, it is treated as HTML and not +# esc_html()'ed. sub format_diff_line { my ($line, $diff_class, $from, $to) = @_; - chomp $line; - $line = untabify($line); - - if ($from && $to && $line =~ m/^\@{2} /) { - $line = format_unidiff_chunk_header($line, $from, $to); - } elsif ($from && $to && $line =~ m/^\@{3}/) { - $line = format_cc_diff_chunk_header($line, $from, $to); + if (ref($line)) { + $line = $$line; } else { - $line = esc_html($line, -nbsp=>1); + chomp $line; + $line = untabify($line); + + if ($from && $to && $line =~ m/^\@{2} /) { + $line = format_unidiff_chunk_header($line, $from, $to); + } elsif ($from && $to && $line =~ m/^\@{3}/) { + $line = format_cc_diff_chunk_header($line, $from, $to); + } else { + $line = esc_html($line, -nbsp=>1); + } } my $diff_classes = "diff"; @@ -3007,9 +3013,11 @@ sub git_get_projects_list { } if (check_export_ok("$projectroot/$path")) { my $pr = { - path => $path, - owner => to_utf8($owner), + path => $path }; + if ($owner) { + $pr->{'owner'} = to_utf8($owner); + } push @list, $pr; } } @@ -5057,9 +5065,117 @@ sub print_inline_diff_lines { print @$ctx, @$rem, @$add; } +# Format removed and added line, mark changed part and HTML-format them. +# Implementation is based on contrib/diff-highlight +sub format_rem_add_lines_pair { + my ($rem, $add, $num_parents) = @_; + + # We need to untabify lines before split()'ing them; + # otherwise offsets would be invalid. + chomp $rem; + chomp $add; + $rem = untabify($rem); + $add = untabify($add); + + my @rem = split(//, $rem); + my @add = split(//, $add); + my ($esc_rem, $esc_add); + # Ignore leading +/- characters for each parent. + my ($prefix_len, $suffix_len) = ($num_parents, 0); + my ($prefix_has_nonspace, $suffix_has_nonspace); + + my $shorter = (@rem < @add) ? @rem : @add; + while ($prefix_len < $shorter) { + last if ($rem[$prefix_len] ne $add[$prefix_len]); + + $prefix_has_nonspace = 1 if ($rem[$prefix_len] !~ /\s/); + $prefix_len++; + } + + while ($prefix_len + $suffix_len < $shorter) { + last if ($rem[-1 - $suffix_len] ne $add[-1 - $suffix_len]); + + $suffix_has_nonspace = 1 if ($rem[-1 - $suffix_len] !~ /\s/); + $suffix_len++; + } + + # Mark lines that are different from each other, but have some common + # part that isn't whitespace. If lines are completely different, don't + # mark them because that would make output unreadable, especially if + # diff consists of multiple lines. + if ($prefix_has_nonspace || $suffix_has_nonspace) { + $esc_rem = esc_html_hl_regions($rem, 'marked', + [$prefix_len, @rem - $suffix_len], -nbsp=>1); + $esc_add = esc_html_hl_regions($add, 'marked', + [$prefix_len, @add - $suffix_len], -nbsp=>1); + } else { + $esc_rem = esc_html($rem, -nbsp=>1); + $esc_add = esc_html($add, -nbsp=>1); + } + + return format_diff_line(\$esc_rem, 'rem'), + format_diff_line(\$esc_add, 'add'); +} + +# HTML-format diff context, removed and added lines. +sub format_ctx_rem_add_lines { + my ($ctx, $rem, $add, $num_parents) = @_; + my (@new_ctx, @new_rem, @new_add); + my $can_highlight = 0; + my $is_combined = ($num_parents > 1); + + # Highlight if every removed line has a corresponding added line. + if (@$add > 0 && @$add == @$rem) { + $can_highlight = 1; + + # Highlight lines in combined diff only if the chunk contains + # diff between the same version, e.g. + # + # - a + # - b + # + c + # + d + # + # Otherwise the highlightling would be confusing. + if ($is_combined) { + for (my $i = 0; $i < @$add; $i++) { + my $prefix_rem = substr($rem->[$i], 0, $num_parents); + my $prefix_add = substr($add->[$i], 0, $num_parents); + + $prefix_rem =~ s/-/+/g; + + if ($prefix_rem ne $prefix_add) { + $can_highlight = 0; + last; + } + } + } + } + + if ($can_highlight) { + for (my $i = 0; $i < @$add; $i++) { + my ($line_rem, $line_add) = format_rem_add_lines_pair( + $rem->[$i], $add->[$i], $num_parents); + push @new_rem, $line_rem; + push @new_add, $line_add; + } + } else { + @new_rem = map { format_diff_line($_, 'rem') } @$rem; + @new_add = map { format_diff_line($_, 'add') } @$add; + } + + @new_ctx = map { format_diff_line($_, 'ctx') } @$ctx; + + return (\@new_ctx, \@new_rem, \@new_add); +} + # Print context lines and then rem/add lines. sub print_diff_lines { - my ($ctx, $rem, $add, $diff_style, $is_combined) = @_; + my ($ctx, $rem, $add, $diff_style, $num_parents) = @_; + my $is_combined = $num_parents > 1; + + ($ctx, $rem, $add) = format_ctx_rem_add_lines($ctx, $rem, $add, + $num_parents); if ($diff_style eq 'sidebyside' && !$is_combined) { print_sidebyside_diff_lines($ctx, $rem, $add); @@ -5070,7 +5186,7 @@ sub print_diff_lines { } sub print_diff_chunk { - my ($diff_style, $is_combined, $from, $to, @chunk) = @_; + my ($diff_style, $num_parents, $from, $to, @chunk) = @_; my (@ctx, @rem, @add); # The class of the previous line. @@ -5092,11 +5208,9 @@ sub print_diff_chunk { foreach my $line_info (@chunk) { my ($class, $line) = @$line_info; - $line = format_diff_line($line, $class, $from, $to); - # print chunk headers if ($class && $class eq 'chunk_header') { - print $line; + print format_diff_line($line, $class, $from, $to); next; } @@ -5107,7 +5221,7 @@ sub print_diff_chunk { if (!$class || ((@rem || @add) && $class eq 'ctx') || (@rem && @add && $class ne $prev_class)) { print_diff_lines(\@ctx, \@rem, \@add, - $diff_style, $is_combined); + $diff_style, $num_parents); @ctx = @rem = @add = (); } @@ -5250,7 +5364,7 @@ sub git_patchset_body { my $class = diff_line_class($patch_line, \%from, \%to); if ($class eq 'chunk_header') { - print_diff_chunk($diff_style, $is_combined, \%from, \%to, @chunk); + print_diff_chunk($diff_style, scalar @hash_parents, \%from, \%to, @chunk); @chunk = (); } @@ -5259,7 +5373,7 @@ sub git_patchset_body { } continue { if (@chunk) { - print_diff_chunk($diff_style, $is_combined, \%from, \%to, @chunk); + print_diff_chunk($diff_style, scalar @hash_parents, \%from, \%to, @chunk); @chunk = (); } print "\n"; # class="patch"