Merge branch 'jk/diff-highlight-graph-fix'
"diff-highlight" filter (in contrib/) learned to undertand "git log --graph" output better. * jk/diff-highlight-graph-fix: diff-highlight: detect --graph by indent diff-highlight: use flush() helper consistently diff-highlight: test graphs with --color diff-highlight: test interleaved parallel lines of history diff-highlight: prefer "echo" to "cat" in tests diff-highlight: use test_tick in graph test diff-highlight: correct test graph diagram
This commit is contained in:
commit
d19e556529
@ -21,37 +21,82 @@ my $RESET = "\x1b[m";
|
||||
my $COLOR = qr/\x1b\[[0-9;]*m/;
|
||||
my $BORING = qr/$COLOR|\s/;
|
||||
|
||||
# The patch portion of git log -p --graph should only ever have preceding | and
|
||||
# not / or \ as merge history only shows up on the commit line.
|
||||
my $GRAPH = qr/$COLOR?\|$COLOR?\s+/;
|
||||
|
||||
my @removed;
|
||||
my @added;
|
||||
my $in_hunk;
|
||||
my $graph_indent = 0;
|
||||
|
||||
our $line_cb = sub { print @_ };
|
||||
our $flush_cb = sub { local $| = 1 };
|
||||
|
||||
sub handle_line {
|
||||
# Count the visible width of a string, excluding any terminal color sequences.
|
||||
sub visible_width {
|
||||
local $_ = shift;
|
||||
my $ret = 0;
|
||||
while (length) {
|
||||
if (s/^$COLOR//) {
|
||||
# skip colors
|
||||
} elsif (s/^.//) {
|
||||
$ret++;
|
||||
}
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
# Return a substring of $str, omitting $len visible characters from the
|
||||
# beginning, where terminal color sequences do not count as visible.
|
||||
sub visible_substr {
|
||||
my ($str, $len) = @_;
|
||||
while ($len > 0) {
|
||||
if ($str =~ s/^$COLOR//) {
|
||||
next
|
||||
}
|
||||
$str =~ s/^.//;
|
||||
$len--;
|
||||
}
|
||||
return $str;
|
||||
}
|
||||
|
||||
sub handle_line {
|
||||
my $orig = shift;
|
||||
local $_ = $orig;
|
||||
|
||||
# match a graph line that begins a commit
|
||||
if (/^(?:$COLOR?\|$COLOR?[ ])* # zero or more leading "|" with space
|
||||
$COLOR?\*$COLOR?[ ] # a "*" with its trailing space
|
||||
(?:$COLOR?\|$COLOR?[ ])* # zero or more trailing "|"
|
||||
[ ]* # trailing whitespace for merges
|
||||
/x) {
|
||||
my $graph_prefix = $&;
|
||||
|
||||
# We must flush before setting graph indent, since the
|
||||
# new commit may be indented differently from what we
|
||||
# queued.
|
||||
flush();
|
||||
$graph_indent = visible_width($graph_prefix);
|
||||
|
||||
} elsif ($graph_indent) {
|
||||
if (length($_) < $graph_indent) {
|
||||
$graph_indent = 0;
|
||||
} else {
|
||||
$_ = visible_substr($_, $graph_indent);
|
||||
}
|
||||
}
|
||||
|
||||
if (!$in_hunk) {
|
||||
$line_cb->($_);
|
||||
$in_hunk = /^$GRAPH*$COLOR*\@\@ /;
|
||||
$line_cb->($orig);
|
||||
$in_hunk = /^$COLOR*\@\@ /;
|
||||
}
|
||||
elsif (/^$GRAPH*$COLOR*-/) {
|
||||
push @removed, $_;
|
||||
elsif (/^$COLOR*-/) {
|
||||
push @removed, $orig;
|
||||
}
|
||||
elsif (/^$GRAPH*$COLOR*\+/) {
|
||||
push @added, $_;
|
||||
elsif (/^$COLOR*\+/) {
|
||||
push @added, $orig;
|
||||
}
|
||||
else {
|
||||
show_hunk(\@removed, \@added);
|
||||
@removed = ();
|
||||
@added = ();
|
||||
|
||||
$line_cb->($_);
|
||||
$in_hunk = /^$GRAPH*$COLOR*[\@ ]/;
|
||||
flush();
|
||||
$line_cb->($orig);
|
||||
$in_hunk = /^$COLOR*[\@ ]/;
|
||||
}
|
||||
|
||||
# Most of the time there is enough output to keep things streaming,
|
||||
@ -71,6 +116,8 @@ sub flush {
|
||||
# Flush any queued hunk (this can happen when there is no trailing
|
||||
# context in the final diff of the input).
|
||||
show_hunk(\@removed, \@added);
|
||||
@removed = ();
|
||||
@added = ();
|
||||
}
|
||||
|
||||
sub highlight_stdin {
|
||||
@ -226,8 +273,8 @@ sub is_pair_interesting {
|
||||
my $suffix_a = join('', @$a[($sa+1)..$#$a]);
|
||||
my $suffix_b = join('', @$b[($sb+1)..$#$b]);
|
||||
|
||||
return $prefix_a !~ /^$GRAPH*$COLOR*-$BORING*$/ ||
|
||||
$prefix_b !~ /^$GRAPH*$COLOR*\+$BORING*$/ ||
|
||||
return visible_substr($prefix_a, $graph_indent) !~ /^$COLOR*-$BORING*$/ ||
|
||||
visible_substr($prefix_b, $graph_indent) !~ /^$COLOR*\+$BORING*$/ ||
|
||||
$suffix_a !~ /^$BORING*$/ ||
|
||||
$suffix_b !~ /^$BORING*$/;
|
||||
}
|
||||
|
@ -52,15 +52,17 @@ test_strip_patch_header () {
|
||||
# dh_test_setup_history generates a contrived graph such that we have at least
|
||||
# 1 nesting (E) and 2 nestings (F).
|
||||
#
|
||||
# A branch
|
||||
# /
|
||||
# D---E---F master
|
||||
# A---B master
|
||||
# /
|
||||
# D---E---F branch
|
||||
#
|
||||
# git log --all --graph
|
||||
# * commit
|
||||
# | A
|
||||
# | B
|
||||
# | * commit
|
||||
# | | F
|
||||
# * | commit
|
||||
# | | A
|
||||
# | * commit
|
||||
# |/
|
||||
# | E
|
||||
@ -68,24 +70,30 @@ test_strip_patch_header () {
|
||||
# D
|
||||
#
|
||||
dh_test_setup_history () {
|
||||
echo "file1" >file1 &&
|
||||
echo "file2" >file2 &&
|
||||
echo "file3" >file3 &&
|
||||
|
||||
cat file1 >file &&
|
||||
echo file1 >file &&
|
||||
git add file &&
|
||||
test_tick &&
|
||||
git commit -m "D" &&
|
||||
|
||||
git checkout -b branch &&
|
||||
cat file2 >file &&
|
||||
git commit -a -m "A" &&
|
||||
|
||||
git checkout master &&
|
||||
cat file2 >file &&
|
||||
echo file2 >file &&
|
||||
test_tick &&
|
||||
git commit -a -m "E" &&
|
||||
|
||||
cat file3 >file &&
|
||||
git commit -a -m "F"
|
||||
git checkout master &&
|
||||
echo file2 >file &&
|
||||
test_tick &&
|
||||
git commit -a -m "A" &&
|
||||
|
||||
git checkout branch &&
|
||||
echo file3 >file &&
|
||||
test_tick &&
|
||||
git commit -a -m "F" &&
|
||||
|
||||
git checkout master &&
|
||||
echo file3 >file &&
|
||||
test_tick &&
|
||||
git commit -a -m "B"
|
||||
}
|
||||
|
||||
left_trim () {
|
||||
@ -246,16 +254,25 @@ test_expect_failure 'diff-highlight treats combining code points as a unit' '
|
||||
test_expect_success 'diff-highlight works with the --graph option' '
|
||||
dh_test_setup_history &&
|
||||
|
||||
# topo-order so that the order of the commits is the same as with --graph
|
||||
# date-order so that the commits are interleaved for both
|
||||
# trim graph elements so we can do a diff
|
||||
# trim leading space because our trim_graph is not perfect
|
||||
git log --branches -p --topo-order |
|
||||
git log --branches -p --date-order |
|
||||
"$DIFF_HIGHLIGHT" | left_trim >graph.exp &&
|
||||
git log --branches -p --graph |
|
||||
git log --branches -p --date-order --graph |
|
||||
"$DIFF_HIGHLIGHT" | trim_graph | left_trim >graph.act &&
|
||||
test_cmp graph.exp graph.act
|
||||
'
|
||||
|
||||
# Just reuse the previous graph test, but with --color. Our trimming
|
||||
# doesn't know about color, so just sanity check that something got
|
||||
# highlighted.
|
||||
test_expect_success 'diff-highlight works with color graph' '
|
||||
git log --branches -p --date-order --graph --color |
|
||||
"$DIFF_HIGHLIGHT" | trim_graph | left_trim >graph &&
|
||||
grep "\[7m" graph
|
||||
'
|
||||
|
||||
# Most combined diffs won't meet diff-highlight's line-number filter. So we
|
||||
# create one here where one side drops a line and the other modifies it. That
|
||||
# should result in a diff like:
|
||||
@ -293,4 +310,32 @@ test_expect_success 'diff-highlight ignores combined diffs' '
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success 'diff-highlight handles --graph with leading dash' '
|
||||
cat >file <<-\EOF &&
|
||||
before
|
||||
the old line
|
||||
-leading dash
|
||||
EOF
|
||||
git add file &&
|
||||
git commit -m before &&
|
||||
|
||||
sed s/old/new/ <file >file.tmp &&
|
||||
mv file.tmp file &&
|
||||
git add file &&
|
||||
git commit -m after &&
|
||||
|
||||
cat >expect <<-EOF &&
|
||||
--- a/file
|
||||
+++ b/file
|
||||
@@ -1,3 +1,3 @@
|
||||
before
|
||||
-the ${CW}old${CR} line
|
||||
+the ${CW}new${CR} line
|
||||
-leading dash
|
||||
EOF
|
||||
git log --graph -p -1 | "$DIFF_HIGHLIGHT" >actual.raw &&
|
||||
trim_graph <actual.raw | sed -n "/^---/,\$p" >actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_done
|
||||
|
Loading…
Reference in New Issue
Block a user