1#!/bin/sh
2
3test_description='word diff colors'
4
5. ./test-lib.sh
6. "$TEST_DIRECTORY"/lib-diff.sh
7
8cat >pre.simple <<-\EOF
9	h(4)
10
11	a = b + c
12EOF
13cat >post.simple <<-\EOF
14	h(4),hh[44]
15
16	a = b + c
17
18	aa = a
19
20	aeff = aeff * ( aaa )
21EOF
22pre=$(git rev-parse --short $(git hash-object pre.simple))
23post=$(git rev-parse --short $(git hash-object post.simple))
24cat >expect.letter-runs-are-words <<-EOF
25	<BOLD>diff --git a/pre b/post<RESET>
26	<BOLD>index $pre..$post 100644<RESET>
27	<BOLD>--- a/pre<RESET>
28	<BOLD>+++ b/post<RESET>
29	<CYAN>@@ -1,3 +1,7 @@<RESET>
30	h(4),<GREEN>hh<RESET>[44]
31
32	a = b + c<RESET>
33
34	<GREEN>aa = a<RESET>
35
36	<GREEN>aeff = aeff * ( aaa<RESET> )
37EOF
38cat >expect.non-whitespace-is-word <<-EOF
39	<BOLD>diff --git a/pre b/post<RESET>
40	<BOLD>index $pre..$post 100644<RESET>
41	<BOLD>--- a/pre<RESET>
42	<BOLD>+++ b/post<RESET>
43	<CYAN>@@ -1,3 +1,7 @@<RESET>
44	h(4)<GREEN>,hh[44]<RESET>
45
46	a = b + c<RESET>
47
48	<GREEN>aa = a<RESET>
49
50	<GREEN>aeff = aeff * ( aaa )<RESET>
51EOF
52
53word_diff () {
54	pre=$(git rev-parse --short $(git hash-object pre)) &&
55	post=$(git rev-parse --short $(git hash-object post)) &&
56	test_must_fail git diff --no-index "$@" pre post >output &&
57	test_decode_color <output >output.decrypted &&
58	sed -e "2s/index [^ ]*/index $pre..$post/" expect >expected
59	test_cmp expected output.decrypted
60}
61
62test_language_driver () {
63	lang=$1
64	test_expect_success "diff driver '$lang'" '
65		cp "$TEST_DIRECTORY/t4034/'"$lang"'/pre" \
66			"$TEST_DIRECTORY/t4034/'"$lang"'/post" \
67			"$TEST_DIRECTORY/t4034/'"$lang"'/expect" . &&
68		echo "* diff='"$lang"'" >.gitattributes &&
69		word_diff --color-words
70	'
71}
72
73test_expect_success setup '
74	git config diff.color.old red &&
75	git config diff.color.new green &&
76	git config diff.color.func magenta
77'
78
79test_expect_success 'set up pre and post with runs of whitespace' '
80	cp pre.simple pre &&
81	cp post.simple post
82'
83
84test_expect_success 'word diff with runs of whitespace' '
85	cat >expect <<-EOF &&
86		<BOLD>diff --git a/pre b/post<RESET>
87		<BOLD>index $pre..$post 100644<RESET>
88		<BOLD>--- a/pre<RESET>
89		<BOLD>+++ b/post<RESET>
90		<CYAN>@@ -1,3 +1,7 @@<RESET>
91		<RED>h(4)<RESET><GREEN>h(4),hh[44]<RESET>
92
93		a = b + c<RESET>
94
95		<GREEN>aa = a<RESET>
96
97		<GREEN>aeff = aeff * ( aaa )<RESET>
98	EOF
99	word_diff --color-words &&
100	word_diff --word-diff=color &&
101	word_diff --color --word-diff=color
102'
103
104test_expect_success '--word-diff=porcelain' '
105	sed "s/#.*$//" >expect <<-EOF &&
106		diff --git a/pre b/post
107		index $pre..$post 100644
108		--- a/pre
109		+++ b/post
110		@@ -1,3 +1,7 @@
111		-h(4)
112		+h(4),hh[44]
113		~
114		 # significant space
115		~
116		 a = b + c
117		~
118		~
119		+aa = a
120		~
121		~
122		+aeff = aeff * ( aaa )
123		~
124	EOF
125	word_diff --word-diff=porcelain
126'
127
128test_expect_success '--word-diff=plain' '
129	cat >expect <<-EOF &&
130		diff --git a/pre b/post
131		index $pre..$post 100644
132		--- a/pre
133		+++ b/post
134		@@ -1,3 +1,7 @@
135		[-h(4)-]{+h(4),hh[44]+}
136
137		a = b + c
138
139		{+aa = a+}
140
141		{+aeff = aeff * ( aaa )+}
142	EOF
143	word_diff --word-diff=plain &&
144	word_diff --word-diff=plain --no-color
145'
146
147test_expect_success '--word-diff=plain --color' '
148	cat >expect <<-EOF &&
149		<BOLD>diff --git a/pre b/post<RESET>
150		<BOLD>index $pre..$post 100644<RESET>
151		<BOLD>--- a/pre<RESET>
152		<BOLD>+++ b/post<RESET>
153		<CYAN>@@ -1,3 +1,7 @@<RESET>
154		<RED>[-h(4)-]<RESET><GREEN>{+h(4),hh[44]+}<RESET>
155
156		a = b + c<RESET>
157
158		<GREEN>{+aa = a+}<RESET>
159
160		<GREEN>{+aeff = aeff * ( aaa )+}<RESET>
161	EOF
162	word_diff --word-diff=plain --color
163'
164
165test_expect_success 'word diff without context' '
166	cat >expect <<-EOF &&
167		<BOLD>diff --git a/pre b/post<RESET>
168		<BOLD>index $pre..$post 100644<RESET>
169		<BOLD>--- a/pre<RESET>
170		<BOLD>+++ b/post<RESET>
171		<CYAN>@@ -1 +1 @@<RESET>
172		<RED>h(4)<RESET><GREEN>h(4),hh[44]<RESET>
173		<CYAN>@@ -3,0 +4,4 @@<RESET> <RESET><MAGENTA>a = b + c<RESET>
174
175		<GREEN>aa = a<RESET>
176
177		<GREEN>aeff = aeff * ( aaa )<RESET>
178	EOF
179	word_diff --color-words --unified=0
180'
181
182test_expect_success 'word diff with a regular expression' '
183	cp expect.letter-runs-are-words expect &&
184	word_diff --color-words="[a-z]+"
185'
186
187test_expect_success 'word diff with zero length matches' '
188	cp expect.letter-runs-are-words expect &&
189	word_diff --color-words="[a-z${LF}]*"
190'
191
192test_expect_success 'set up a diff driver' '
193	git config diff.testdriver.wordRegex "[^[:space:]]" &&
194	cat <<-\EOF >.gitattributes
195		pre diff=testdriver
196		post diff=testdriver
197	EOF
198'
199
200test_expect_success 'option overrides .gitattributes' '
201	cp expect.letter-runs-are-words expect &&
202	word_diff --color-words="[a-z]+"
203'
204
205test_expect_success 'use regex supplied by driver' '
206	cp expect.non-whitespace-is-word expect &&
207	word_diff --color-words
208'
209
210test_expect_success 'set up diff.wordRegex option' '
211	git config diff.wordRegex "[[:alnum:]]+"
212'
213
214test_expect_success 'command-line overrides config' '
215	cp expect.letter-runs-are-words expect &&
216	word_diff --color-words="[a-z]+"
217'
218
219test_expect_success 'command-line overrides config: --word-diff-regex' '
220	cat >expect <<-EOF &&
221		<BOLD>diff --git a/pre b/post<RESET>
222		<BOLD>index $pre..$post 100644<RESET>
223		<BOLD>--- a/pre<RESET>
224		<BOLD>+++ b/post<RESET>
225		<CYAN>@@ -1,3 +1,7 @@<RESET>
226		h(4),<GREEN>{+hh+}<RESET>[44]
227
228		a = b + c<RESET>
229
230		<GREEN>{+aa = a+}<RESET>
231
232		<GREEN>{+aeff = aeff * ( aaa+}<RESET> )
233	EOF
234	word_diff --color --word-diff-regex="[a-z]+"
235'
236
237test_expect_success '.gitattributes override config' '
238	cp expect.non-whitespace-is-word expect &&
239	word_diff --color-words
240'
241
242test_expect_success 'setup: remove diff driver regex' '
243	test_unconfig diff.testdriver.wordRegex
244'
245
246test_expect_success 'use configured regex' '
247	cat >expect <<-EOF &&
248		<BOLD>diff --git a/pre b/post<RESET>
249		<BOLD>index $pre..$post 100644<RESET>
250		<BOLD>--- a/pre<RESET>
251		<BOLD>+++ b/post<RESET>
252		<CYAN>@@ -1,3 +1,7 @@<RESET>
253		h(4),<GREEN>hh[44<RESET>]
254
255		a = b + c<RESET>
256
257		<GREEN>aa = a<RESET>
258
259		<GREEN>aeff = aeff * ( aaa<RESET> )
260	EOF
261	word_diff --color-words
262'
263
264test_expect_success 'test parsing words for newline' '
265	echo "aaa (aaa)" >pre &&
266	echo "aaa (aaa) aaa" >post &&
267	pre=$(git rev-parse --short $(git hash-object pre)) &&
268	post=$(git rev-parse --short $(git hash-object post)) &&
269	cat >expect <<-EOF &&
270		<BOLD>diff --git a/pre b/post<RESET>
271		<BOLD>index $pre..$post 100644<RESET>
272		<BOLD>--- a/pre<RESET>
273		<BOLD>+++ b/post<RESET>
274		<CYAN>@@ -1 +1 @@<RESET>
275		aaa (aaa) <GREEN>aaa<RESET>
276	EOF
277	word_diff --color-words="a+"
278'
279
280test_expect_success 'test when words are only removed at the end' '
281	echo "(:" >pre &&
282	echo "(" >post &&
283	pre=$(git rev-parse --short $(git hash-object pre)) &&
284	post=$(git rev-parse --short $(git hash-object post)) &&
285	cat >expect <<-EOF &&
286		<BOLD>diff --git a/pre b/post<RESET>
287		<BOLD>index $pre..$post 100644<RESET>
288		<BOLD>--- a/pre<RESET>
289		<BOLD>+++ b/post<RESET>
290		<CYAN>@@ -1 +1 @@<RESET>
291		(<RED>:<RESET>
292	EOF
293	word_diff --color-words=.
294'
295
296test_expect_success '--word-diff=none' '
297	echo "(:" >pre &&
298	echo "(" >post &&
299	pre=$(git rev-parse --short $(git hash-object pre)) &&
300	post=$(git rev-parse --short $(git hash-object post)) &&
301	cat >expect <<-EOF &&
302		diff --git a/pre b/post
303		index $pre..$post 100644
304		--- a/pre
305		+++ b/post
306		@@ -1 +1 @@
307		-(:
308		+(
309	EOF
310	word_diff --word-diff=plain --word-diff=none
311'
312
313test_expect_success 'unset default driver' '
314	test_unconfig diff.wordregex
315'
316
317test_language_driver ada
318test_language_driver bibtex
319test_language_driver cpp
320test_language_driver csharp
321test_language_driver css
322test_language_driver dts
323test_language_driver fortran
324test_language_driver html
325test_language_driver java
326test_language_driver matlab
327test_language_driver objc
328test_language_driver pascal
329test_language_driver perl
330test_language_driver php
331test_language_driver python
332test_language_driver ruby
333test_language_driver scheme
334test_language_driver tex
335
336test_expect_success 'word-diff with diff.sbe' '
337	cat >pre <<-\EOF &&
338	a
339
340	b
341	EOF
342	cat >post <<-\EOF &&
343	a
344
345	c
346	EOF
347	pre=$(git rev-parse --short $(git hash-object pre)) &&
348	post=$(git rev-parse --short $(git hash-object post)) &&
349	cat >expect <<-EOF &&
350	diff --git a/pre b/post
351	index $pre..$post 100644
352	--- a/pre
353	+++ b/post
354	@@ -1,3 +1,3 @@
355	a
356
357	[-b-]{+c+}
358	EOF
359	test_config diff.suppress-blank-empty true &&
360	word_diff --word-diff=plain
361'
362
363test_expect_success 'word-diff with no newline at EOF' '
364	printf "%s" "a a a a a" >pre &&
365	printf "%s" "a a ab a a" >post &&
366	pre=$(git rev-parse --short $(git hash-object pre)) &&
367	post=$(git rev-parse --short $(git hash-object post)) &&
368	cat >expect <<-EOF &&
369	diff --git a/pre b/post
370	index $pre..$post 100644
371	--- a/pre
372	+++ b/post
373	@@ -1 +1 @@
374	a a [-a-]{+ab+} a a
375	EOF
376	word_diff --word-diff=plain
377'
378
379test_expect_success 'setup history with two files' '
380	echo "a b; c" >a.tex &&
381	echo "a b; c" >z.txt &&
382	git add a.tex z.txt &&
383	git commit -minitial &&
384
385	# modify both
386	echo "a bx; c" >a.tex &&
387	echo "a bx; c" >z.txt &&
388	git commit -mmodified -a
389'
390
391test_expect_success 'wordRegex for the first file does not apply to the second' '
392	echo "*.tex diff=tex" >.gitattributes &&
393	test_config diff.tex.wordRegex "[a-z]+|." &&
394	cat >expect <<-\EOF &&
395		diff --git a/a.tex b/a.tex
396		--- a/a.tex
397		+++ b/a.tex
398		@@ -1 +1 @@
399		a [-b-]{+bx+}; c
400		diff --git a/z.txt b/z.txt
401		--- a/z.txt
402		+++ b/z.txt
403		@@ -1 +1 @@
404		a [-b;-]{+bx;+} c
405	EOF
406	git diff --word-diff HEAD~ >actual &&
407	compare_diff_patch expect actual
408'
409
410test_done
411