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 $COLOR = qr/\x1b\[[0-9;]*m/;
|
||||||
my $BORING = qr/$COLOR|\s/;
|
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 @removed;
|
||||||
my @added;
|
my @added;
|
||||||
my $in_hunk;
|
my $in_hunk;
|
||||||
|
my $graph_indent = 0;
|
||||||
|
|
||||||
our $line_cb = sub { print @_ };
|
our $line_cb = sub { print @_ };
|
||||||
our $flush_cb = sub { local $| = 1 };
|
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;
|
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) {
|
if (!$in_hunk) {
|
||||||
$line_cb->($_);
|
$line_cb->($orig);
|
||||||
$in_hunk = /^$GRAPH*$COLOR*\@\@ /;
|
$in_hunk = /^$COLOR*\@\@ /;
|
||||||
}
|
}
|
||||||
elsif (/^$GRAPH*$COLOR*-/) {
|
elsif (/^$COLOR*-/) {
|
||||||
push @removed, $_;
|
push @removed, $orig;
|
||||||
}
|
}
|
||||||
elsif (/^$GRAPH*$COLOR*\+/) {
|
elsif (/^$COLOR*\+/) {
|
||||||
push @added, $_;
|
push @added, $orig;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
show_hunk(\@removed, \@added);
|
flush();
|
||||||
@removed = ();
|
$line_cb->($orig);
|
||||||
@added = ();
|
$in_hunk = /^$COLOR*[\@ ]/;
|
||||||
|
|
||||||
$line_cb->($_);
|
|
||||||
$in_hunk = /^$GRAPH*$COLOR*[\@ ]/;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Most of the time there is enough output to keep things streaming,
|
# 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
|
# Flush any queued hunk (this can happen when there is no trailing
|
||||||
# context in the final diff of the input).
|
# context in the final diff of the input).
|
||||||
show_hunk(\@removed, \@added);
|
show_hunk(\@removed, \@added);
|
||||||
|
@removed = ();
|
||||||
|
@added = ();
|
||||||
}
|
}
|
||||||
|
|
||||||
sub highlight_stdin {
|
sub highlight_stdin {
|
||||||
@ -226,8 +273,8 @@ sub is_pair_interesting {
|
|||||||
my $suffix_a = join('', @$a[($sa+1)..$#$a]);
|
my $suffix_a = join('', @$a[($sa+1)..$#$a]);
|
||||||
my $suffix_b = join('', @$b[($sb+1)..$#$b]);
|
my $suffix_b = join('', @$b[($sb+1)..$#$b]);
|
||||||
|
|
||||||
return $prefix_a !~ /^$GRAPH*$COLOR*-$BORING*$/ ||
|
return visible_substr($prefix_a, $graph_indent) !~ /^$COLOR*-$BORING*$/ ||
|
||||||
$prefix_b !~ /^$GRAPH*$COLOR*\+$BORING*$/ ||
|
visible_substr($prefix_b, $graph_indent) !~ /^$COLOR*\+$BORING*$/ ||
|
||||||
$suffix_a !~ /^$BORING*$/ ||
|
$suffix_a !~ /^$BORING*$/ ||
|
||||||
$suffix_b !~ /^$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
|
# dh_test_setup_history generates a contrived graph such that we have at least
|
||||||
# 1 nesting (E) and 2 nestings (F).
|
# 1 nesting (E) and 2 nestings (F).
|
||||||
#
|
#
|
||||||
# A branch
|
# A---B master
|
||||||
# /
|
# /
|
||||||
# D---E---F master
|
# D---E---F branch
|
||||||
#
|
#
|
||||||
# git log --all --graph
|
# git log --all --graph
|
||||||
# * commit
|
# * commit
|
||||||
# | A
|
# | B
|
||||||
# | * commit
|
# | * commit
|
||||||
# | | F
|
# | | F
|
||||||
|
# * | commit
|
||||||
|
# | | A
|
||||||
# | * commit
|
# | * commit
|
||||||
# |/
|
# |/
|
||||||
# | E
|
# | E
|
||||||
@ -68,24 +70,30 @@ test_strip_patch_header () {
|
|||||||
# D
|
# D
|
||||||
#
|
#
|
||||||
dh_test_setup_history () {
|
dh_test_setup_history () {
|
||||||
echo "file1" >file1 &&
|
echo file1 >file &&
|
||||||
echo "file2" >file2 &&
|
|
||||||
echo "file3" >file3 &&
|
|
||||||
|
|
||||||
cat file1 >file &&
|
|
||||||
git add file &&
|
git add file &&
|
||||||
|
test_tick &&
|
||||||
git commit -m "D" &&
|
git commit -m "D" &&
|
||||||
|
|
||||||
git checkout -b branch &&
|
git checkout -b branch &&
|
||||||
cat file2 >file &&
|
echo file2 >file &&
|
||||||
git commit -a -m "A" &&
|
test_tick &&
|
||||||
|
|
||||||
git checkout master &&
|
|
||||||
cat file2 >file &&
|
|
||||||
git commit -a -m "E" &&
|
git commit -a -m "E" &&
|
||||||
|
|
||||||
cat file3 >file &&
|
git checkout master &&
|
||||||
git commit -a -m "F"
|
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 () {
|
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' '
|
test_expect_success 'diff-highlight works with the --graph option' '
|
||||||
dh_test_setup_history &&
|
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 graph elements so we can do a diff
|
||||||
# trim leading space because our trim_graph is not perfect
|
# 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 &&
|
"$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 &&
|
"$DIFF_HIGHLIGHT" | trim_graph | left_trim >graph.act &&
|
||||||
test_cmp graph.exp 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
|
# 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
|
# create one here where one side drops a line and the other modifies it. That
|
||||||
# should result in a diff like:
|
# should result in a diff like:
|
||||||
@ -293,4 +310,32 @@ test_expect_success 'diff-highlight ignores combined diffs' '
|
|||||||
test_cmp expect actual
|
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
|
test_done
|
||||||
|
Loading…
Reference in New Issue
Block a user