Skip to content

Commit 51ef7a6

Browse files
mkiedrowiczgitster
authored andcommitted
gitweb: Refinement highlightning in combined diffs
The highlightning of combined diffs is currently disabled. This is because output from a combined diff is much harder to highlight because it is not obvious which removed and added lines should be compared. Current code requires that the number of added lines is equal to the number of removed lines and only skips first +/- character, treating second +/- as a line content, Thus, it is not possible to simply use existing algorithm unchanged for combined diffs. Let's start with a simple case: only highlight changes that come from one parent, i.e. when every removed line has a corresponding added line for the same parent. This way the highlightning cannot get wrong. For example, following diffs would be highlighted: - removed line for first parent + added line for first parent context line -removed line for second parent +added line for second parent or - removed line for first parent -removed line for second parent + added line for first parent +added line for second parent but following output will not: - removed line for first parent -removed line for second parent +added line for second parent ++added line for both parents In other words, we require that pattern of '-'-es in pre-image matches pattern of '+'-es in post-image. Further changes may introduce more intelligent approach that better handles combined diffs. Signed-off-by: Michał Kiedrowicz <[email protected]> Acked-by: Jakub Narębski <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 5fb6ddf commit 51ef7a6

File tree

1 file changed

+42
-13
lines changed

1 file changed

+42
-13
lines changed

gitweb/gitweb.perl

Lines changed: 42 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5064,7 +5064,7 @@ sub print_inline_diff_lines {
50645064
# Format removed and added line, mark changed part and HTML-format them.
50655065
# Implementation is based on contrib/diff-highlight
50665066
sub format_rem_add_lines_pair {
5067-
my ($rem, $add) = @_;
5067+
my ($rem, $add, $num_parents) = @_;
50685068

50695069
# We need to untabify lines before split()'ing them;
50705070
# otherwise offsets would be invalid.
@@ -5076,8 +5076,8 @@ sub format_rem_add_lines_pair {
50765076
my @rem = split(//, $rem);
50775077
my @add = split(//, $add);
50785078
my ($esc_rem, $esc_add);
5079-
# Ignore +/- character, thus $prefix_len is set to 1.
5080-
my ($prefix_len, $suffix_len) = (1, 0);
5079+
# Ignore leading +/- characters for each parent.
5080+
my ($prefix_len, $suffix_len) = ($num_parents, 0);
50815081
my ($prefix_has_nonspace, $suffix_has_nonspace);
50825082

50835083
my $shorter = (@rem < @add) ? @rem : @add;
@@ -5115,15 +5115,43 @@ sub format_rem_add_lines_pair {
51155115

51165116
# HTML-format diff context, removed and added lines.
51175117
sub format_ctx_rem_add_lines {
5118-
my ($ctx, $rem, $add, $is_combined) = @_;
5118+
my ($ctx, $rem, $add, $num_parents) = @_;
51195119
my (@new_ctx, @new_rem, @new_add);
5120+
my $can_highlight = 0;
5121+
my $is_combined = ($num_parents > 1);
51205122

51215123
# Highlight if every removed line has a corresponding added line.
5122-
# Combined diffs are not supported at this moment.
5123-
if (!$is_combined && @$add > 0 && @$add == @$rem) {
5124+
if (@$add > 0 && @$add == @$rem) {
5125+
$can_highlight = 1;
5126+
5127+
# Highlight lines in combined diff only if the chunk contains
5128+
# diff between the same version, e.g.
5129+
#
5130+
# - a
5131+
# - b
5132+
# + c
5133+
# + d
5134+
#
5135+
# Otherwise the highlightling would be confusing.
5136+
if ($is_combined) {
5137+
for (my $i = 0; $i < @$add; $i++) {
5138+
my $prefix_rem = substr($rem->[$i], 0, $num_parents);
5139+
my $prefix_add = substr($add->[$i], 0, $num_parents);
5140+
5141+
$prefix_rem =~ s/-/+/g;
5142+
5143+
if ($prefix_rem ne $prefix_add) {
5144+
$can_highlight = 0;
5145+
last;
5146+
}
5147+
}
5148+
}
5149+
}
5150+
5151+
if ($can_highlight) {
51245152
for (my $i = 0; $i < @$add; $i++) {
51255153
my ($line_rem, $line_add) = format_rem_add_lines_pair(
5126-
$rem->[$i], $add->[$i]);
5154+
$rem->[$i], $add->[$i], $num_parents);
51275155
push @new_rem, $line_rem;
51285156
push @new_add, $line_add;
51295157
}
@@ -5139,10 +5167,11 @@ sub format_ctx_rem_add_lines {
51395167

51405168
# Print context lines and then rem/add lines.
51415169
sub print_diff_lines {
5142-
my ($ctx, $rem, $add, $diff_style, $is_combined) = @_;
5170+
my ($ctx, $rem, $add, $diff_style, $num_parents) = @_;
5171+
my $is_combined = $num_parents > 1;
51435172

51445173
($ctx, $rem, $add) = format_ctx_rem_add_lines($ctx, $rem, $add,
5145-
$is_combined);
5174+
$num_parents);
51465175

51475176
if ($diff_style eq 'sidebyside' && !$is_combined) {
51485177
print_sidebyside_diff_lines($ctx, $rem, $add);
@@ -5153,7 +5182,7 @@ sub print_diff_lines {
51535182
}
51545183

51555184
sub print_diff_chunk {
5156-
my ($diff_style, $is_combined, $from, $to, @chunk) = @_;
5185+
my ($diff_style, $num_parents, $from, $to, @chunk) = @_;
51575186
my (@ctx, @rem, @add);
51585187

51595188
# The class of the previous line.
@@ -5188,7 +5217,7 @@ sub print_diff_chunk {
51885217
if (!$class || ((@rem || @add) && $class eq 'ctx') ||
51895218
(@rem && @add && $class ne $prev_class)) {
51905219
print_diff_lines(\@ctx, \@rem, \@add,
5191-
$diff_style, $is_combined);
5220+
$diff_style, $num_parents);
51925221
@ctx = @rem = @add = ();
51935222
}
51945223

@@ -5331,7 +5360,7 @@ sub git_patchset_body {
53315360
my $class = diff_line_class($patch_line, \%from, \%to);
53325361

53335362
if ($class eq 'chunk_header') {
5334-
print_diff_chunk($diff_style, $is_combined, \%from, \%to, @chunk);
5363+
print_diff_chunk($diff_style, scalar @hash_parents, \%from, \%to, @chunk);
53355364
@chunk = ();
53365365
}
53375366

@@ -5340,7 +5369,7 @@ sub git_patchset_body {
53405369

53415370
} continue {
53425371
if (@chunk) {
5343-
print_diff_chunk($diff_style, $is_combined, \%from, \%to, @chunk);
5372+
print_diff_chunk($diff_style, scalar @hash_parents, \%from, \%to, @chunk);
53445373
@chunk = ();
53455374
}
53465375
print "</div>\n"; # class="patch"

0 commit comments

Comments
 (0)