1#!/bin/sh
2
3test_description='core.whitespace rules and git apply'
4
5. ./test-lib.sh
6
7prepare_test_file () {
8
9 # A line that has character X is touched iff RULE is in effect:
10 # X RULE
11 # ! trailing-space
12 # @ space-before-tab
13 # # indent-with-non-tab (default tab width 8)
14 # = indent-with-non-tab,tabwidth=16
15 # % tab-in-indent
16 sed -e "s/_/ /g" -e "s/>/ /" <<-\EOF
17 An_SP in an ordinary line>and a HT.
18 >A HT (%).
19 _>A SP and a HT (@%).
20 _>_A SP, a HT and a SP (@%).
21 _______Seven SP.
22 ________Eight SP (#).
23 _______>Seven SP and a HT (@%).
24 ________>Eight SP and a HT (@#%).
25 _______>_Seven SP, a HT and a SP (@%).
26 ________>_Eight SP, a HT and a SP (@#%).
27 _______________Fifteen SP (#).
28 _______________>Fifteen SP and a HT (@#%).
29 ________________Sixteen SP (#=).
30 ________________>Sixteen SP and a HT (@#%=).
31 _____a__Five SP, a non WS, two SP.
32 A line with a (!) trailing SP_
33 A line with a (!) trailing HT>
34 EOF
35}
36
37apply_patch () {
38 >target &&
39 sed -e "s|\([ab]\)/file|\1/target|" <patch |
40 git apply "$@"
41}
42
43test_fix () {
44 # fix should not barf
45 apply_patch --whitespace=fix || return 1
46
47 # find touched lines
48 $DIFF file target | sed -n -e "s/^> //p" >fixed
49
50 # the changed lines are all expected to change
51 fixed_cnt=$(wc -l <fixed)
52 case "$1" in
53 '') expect_cnt=$fixed_cnt ;;
54 ?*) expect_cnt=$(grep "[$1]" <fixed | wc -l) ;;
55 esac
56 test $fixed_cnt -eq $expect_cnt || return 1
57
58 # and we are not missing anything
59 case "$1" in
60 '') expect_cnt=0 ;;
61 ?*) expect_cnt=$(grep "[$1]" <file | wc -l) ;;
62 esac
63 test $fixed_cnt -eq $expect_cnt || return 1
64
65 # Get the patch actually applied
66 git diff-files -p target >fixed-patch
67 test -s fixed-patch && return 0
68
69 # Make sure it is complaint-free
70 >target
71 git apply --whitespace=error-all <fixed-patch
72
73}
74
75test_expect_success setup '
76
77 >file &&
78 git add file &&
79 prepare_test_file >file &&
80 git diff-files -p >patch &&
81 >target &&
82 git add target
83
84'
85
86test_expect_success 'whitespace=nowarn, default rule' '
87
88 apply_patch --whitespace=nowarn &&
89 test_cmp file target
90
91'
92
93test_expect_success 'whitespace=warn, default rule' '
94
95 apply_patch --whitespace=warn &&
96 test_cmp file target
97
98'
99
100test_expect_success 'whitespace=error-all, default rule' '
101
102 apply_patch --whitespace=error-all && return 1
103 test -s target && return 1
104 : happy
105
106'
107
108test_expect_success 'whitespace=error-all, no rule' '
109
110 git config core.whitespace -trailing,-space-before,-indent &&
111 apply_patch --whitespace=error-all &&
112 test_cmp file target
113
114'
115
116test_expect_success 'whitespace=error-all, no rule (attribute)' '
117
118 git config --unset core.whitespace &&
119 echo "target -whitespace" >.gitattributes &&
120 apply_patch --whitespace=error-all &&
121 test_cmp file target
122
123'
124
125test_expect_success 'spaces inserted by tab-in-indent' '
126
127 git config core.whitespace -trailing,-space,-indent,tab &&
128 rm -f .gitattributes &&
129 test_fix % &&
130 sed -e "s/_/ /g" -e "s/>/ /" <<-\EOF >expect &&
131 An_SP in an ordinary line>and a HT.
132 ________A HT (%).
133 ________A SP and a HT (@%).
134 _________A SP, a HT and a SP (@%).
135 _______Seven SP.
136 ________Eight SP (#).
137 ________Seven SP and a HT (@%).
138 ________________Eight SP and a HT (@#%).
139 _________Seven SP, a HT and a SP (@%).
140 _________________Eight SP, a HT and a SP (@#%).
141 _______________Fifteen SP (#).
142 ________________Fifteen SP and a HT (@#%).
143 ________________Sixteen SP (#=).
144 ________________________Sixteen SP and a HT (@#%=).
145 _____a__Five SP, a non WS, two SP.
146 A line with a (!) trailing SP_
147 A line with a (!) trailing HT>
148 EOF
149 test_cmp expect target
150
151'
152
153for t in - ''
154do
155 case "$t" in '') tt='!' ;; *) tt= ;; esac
156 for s in - ''
157 do
158 case "$s" in '') ts='@' ;; *) ts= ;; esac
159 for i in - ''
160 do
161 case "$i" in '') ti='#' ti16='=';; *) ti= ti16= ;; esac
162 for h in - ''
163 do
164 [ -z "$h$i" ] && continue
165 case "$h" in '') th='%' ;; *) th= ;; esac
166 rule=${t}trailing,${s}space,${i}indent,${h}tab
167
168 rm -f .gitattributes
169 test_expect_success "rule=$rule" '
170 git config core.whitespace "$rule" &&
171 test_fix "$tt$ts$ti$th"
172 '
173
174 test_expect_success "rule=$rule,tabwidth=16" '
175 git config core.whitespace "$rule,tabwidth=16" &&
176 test_fix "$tt$ts$ti16$th"
177 '
178
179 test_expect_success "rule=$rule (attributes)" '
180 git config --unset core.whitespace &&
181 echo "target whitespace=$rule" >.gitattributes &&
182 test_fix "$tt$ts$ti$th"
183 '
184
185 test_expect_success "rule=$rule,tabwidth=16 (attributes)" '
186 echo "target whitespace=$rule,tabwidth=16" >.gitattributes &&
187 test_fix "$tt$ts$ti16$th"
188 '
189
190 done
191 done
192 done
193done
194
195create_patch () {
196 sed -e "s/_/ /" <<-\EOF
197 diff --git a/target b/target
198 index e69de29..8bd6648 100644
199 --- a/target
200 +++ b/target
201 @@ -0,0 +1,3 @@
202 +An empty line follows
203 +
204 +A line with trailing whitespace and no newline_
205 \ No newline at end of file
206 EOF
207}
208
209test_expect_success 'trailing whitespace & no newline at the end of file' '
210 >target &&
211 create_patch >patch-file &&
212 git apply --whitespace=fix patch-file &&
213 grep "newline$" target &&
214 grep "^$" target
215'
216
217test_expect_success 'blank at EOF with --whitespace=fix (1)' '
218 test_might_fail git config --unset core.whitespace &&
219 rm -f .gitattributes &&
220
221 { echo a; echo b; echo c; } >one &&
222 git add one &&
223 { echo a; echo b; echo c; } >expect &&
224 { cat expect; echo; } >one &&
225 git diff -- one >patch &&
226
227 git checkout one &&
228 git apply --whitespace=fix patch &&
229 test_cmp expect one
230'
231
232test_expect_success 'blank at EOF with --whitespace=fix (2)' '
233 { echo a; echo b; echo c; } >one &&
234 git add one &&
235 { echo a; echo c; } >expect &&
236 { cat expect; echo; echo; } >one &&
237 git diff -- one >patch &&
238
239 git checkout one &&
240 git apply --whitespace=fix patch &&
241 test_cmp expect one
242'
243
244test_expect_success 'blank at EOF with --whitespace=fix (3)' '
245 { echo a; echo b; echo; } >one &&
246 git add one &&
247 { echo a; echo c; echo; } >expect &&
248 { cat expect; echo; echo; } >one &&
249 git diff -- one >patch &&
250
251 git checkout one &&
252 git apply --whitespace=fix patch &&
253 test_cmp expect one
254'
255
256test_expect_success 'blank at end of hunk, not at EOF with --whitespace=fix' '
257 { echo a; echo b; echo; echo; echo; echo; echo; echo d; } >one &&
258 git add one &&
259 { echo a; echo c; echo; echo; echo; echo; echo; echo; echo d; } >expect &&
260 cp expect one &&
261 git diff -- one >patch &&
262
263 git checkout one &&
264 git apply --whitespace=fix patch &&
265 test_cmp expect one
266'
267
268test_expect_success 'blank at EOF with --whitespace=warn' '
269 { echo a; echo b; echo c; } >one &&
270 git add one &&
271 echo >>one &&
272 cat one >expect &&
273 git diff -- one >patch &&
274
275 git checkout one &&
276 git apply --whitespace=warn patch 2>error &&
277 test_cmp expect one &&
278 grep "new blank line at EOF" error
279'
280
281test_expect_success 'blank at EOF with --whitespace=error' '
282 { echo a; echo b; echo c; } >one &&
283 git add one &&
284 cat one >expect &&
285 echo >>one &&
286 git diff -- one >patch &&
287
288 git checkout one &&
289 test_must_fail git apply --whitespace=error patch 2>error &&
290 test_cmp expect one &&
291 grep "new blank line at EOF" error
292'
293
294test_expect_success 'blank but not empty at EOF' '
295 { echo a; echo b; echo c; } >one &&
296 git add one &&
297 echo " " >>one &&
298 cat one >expect &&
299 git diff -- one >patch &&
300
301 git checkout one &&
302 git apply --whitespace=warn patch 2>error &&
303 test_cmp expect one &&
304 grep "new blank line at EOF" error
305'
306
307test_expect_success 'applying beyond EOF requires one non-blank context line' '
308 { echo; echo; echo; echo; } >one &&
309 git add one &&
310 { echo b; } >>one &&
311 git diff -- one >patch &&
312
313 git checkout one &&
314 { echo a; echo; } >one &&
315 cp one expect &&
316 test_must_fail git apply --whitespace=fix patch &&
317 test_cmp one expect &&
318 test_must_fail git apply --ignore-space-change --whitespace=fix patch &&
319 test_cmp one expect
320'
321
322test_expect_success 'tons of blanks at EOF should not apply' '
323 for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16; do
324 echo; echo; echo; echo;
325 done >one &&
326 git add one &&
327 echo a >>one &&
328 git diff -- one >patch &&
329
330 >one &&
331 test_must_fail git apply --whitespace=fix patch &&
332 test_must_fail git apply --ignore-space-change --whitespace=fix patch
333'
334
335test_expect_success 'missing blank line at end with --whitespace=fix' '
336 echo a >one &&
337 echo >>one &&
338 git add one &&
339 echo b >>one &&
340 cp one expect &&
341 git diff -- one >patch &&
342 echo a >one &&
343 cp one saved-one &&
344 test_must_fail git apply patch &&
345 git apply --whitespace=fix patch &&
346 test_cmp one expect &&
347 mv saved-one one &&
348 git apply --ignore-space-change --whitespace=fix patch &&
349 test_cmp one expect
350'
351
352test_expect_success 'two missing blank lines at end with --whitespace=fix' '
353 { echo a; echo; echo b; echo c; } >one &&
354 cp one no-blank-lines &&
355 { echo; echo; } >>one &&
356 git add one &&
357 echo d >>one &&
358 cp one expect &&
359 echo >>one &&
360 git diff -- one >patch &&
361 cp no-blank-lines one &&
362 test_must_fail git apply patch &&
363 git apply --whitespace=fix patch &&
364 test_cmp one expect &&
365 mv no-blank-lines one &&
366 test_must_fail git apply patch &&
367 git apply --ignore-space-change --whitespace=fix patch &&
368 test_cmp one expect
369'
370
371test_expect_success 'missing blank line at end, insert before end, --whitespace=fix' '
372 { echo a; echo; } >one &&
373 git add one &&
374 { echo b; echo a; echo; } >one &&
375 cp one expect &&
376 git diff -- one >patch &&
377 echo a >one &&
378 test_must_fail git apply patch &&
379 git apply --whitespace=fix patch &&
380 test_cmp one expect
381'
382
383test_expect_success 'shrink file with tons of missing blanks at end of file' '
384 { echo a; echo b; echo c; } >one &&
385 cp one no-blank-lines &&
386 for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16; do
387 echo; echo; echo; echo;
388 done >>one &&
389 git add one &&
390 echo a >one &&
391 cp one expect &&
392 git diff -- one >patch &&
393 cp no-blank-lines one &&
394 test_must_fail git apply patch &&
395 git apply --whitespace=fix patch &&
396 test_cmp one expect &&
397 mv no-blank-lines one &&
398 git apply --ignore-space-change --whitespace=fix patch &&
399 test_cmp one expect
400'
401
402test_expect_success 'missing blanks at EOF must only match blank lines' '
403 { echo a; echo b; } >one &&
404 git add one &&
405 { echo c; echo d; } >>one &&
406 git diff -- one >patch &&
407
408 echo a >one &&
409 test_must_fail git apply patch &&
410 test_must_fail git apply --whitespace=fix patch &&
411 test_must_fail git apply --ignore-space-change --whitespace=fix patch
412'
413
414sed -e's/Z//' >one <<EOF
415a
416b
417c
418 Z
419EOF
420
421test_expect_success 'missing blank line should match context line with spaces' '
422 git add one &&
423 echo d >>one &&
424 git diff -- one >patch &&
425 { echo a; echo b; echo c; } >one &&
426 cp one expect &&
427 { echo; echo d; } >>expect &&
428 git add one &&
429
430 git apply --whitespace=fix patch &&
431 test_cmp one expect
432'
433
434sed -e's/Z//' >one <<EOF
435a
436b
437c
438 Z
439EOF
440
441test_expect_success 'same, but with the --ignore-space-option' '
442 git add one &&
443 echo d >>one &&
444 cp one expect &&
445 git diff -- one >patch &&
446 { echo a; echo b; echo c; } >one &&
447 git add one &&
448
449 git checkout-index -f one &&
450 git apply --ignore-space-change --whitespace=fix patch &&
451 test_cmp one expect
452'
453
454test_expect_success 'same, but with CR-LF line endings && cr-at-eol set' '
455 git config core.whitespace cr-at-eol &&
456 printf "a\r\n" >one &&
457 printf "b\r\n" >>one &&
458 printf "c\r\n" >>one &&
459 cp one save-one &&
460 printf " \r\n" >>one &&
461 git add one &&
462 printf "d\r\n" >>one &&
463 cp one expect &&
464 git diff -- one >patch &&
465 mv save-one one &&
466
467 git apply --ignore-space-change --whitespace=fix patch &&
468 test_cmp one expect
469'
470
471test_expect_success 'same, but with CR-LF line endings && cr-at-eol unset' '
472 git config --unset core.whitespace &&
473 printf "a\r\n" >one &&
474 printf "b\r\n" >>one &&
475 printf "c\r\n" >>one &&
476 cp one save-one &&
477 printf " \r\n" >>one &&
478 git add one &&
479 cp one expect &&
480 printf "d\r\n" >>one &&
481 git diff -- one >patch &&
482 mv save-one one &&
483 echo d >>expect &&
484
485 git apply --ignore-space-change --whitespace=fix patch &&
486 test_cmp one expect
487'
488
489test_expect_success 'whitespace=fix to expand' '
490 qz_to_tab_space >preimage <<-\EOF &&
491 QQa
492 QQb
493 QQc
494 ZZZZZZZZZZZZZZZZd
495 QQe
496 QQf
497 QQg
498 EOF
499 qz_to_tab_space >patch <<-\EOF &&
500 diff --git a/preimage b/preimage
501 --- a/preimage
502 +++ b/preimage
503 @@ -1,7 +1,6 @@
504 QQa
505 QQb
506 QQc
507 -QQd
508 QQe
509 QQf
510 QQg
511 EOF
512 git -c core.whitespace=tab-in-indent apply --whitespace=fix patch
513'
514
515test_expect_success 'whitespace check skipped for excluded paths' '
516 git config core.whitespace blank-at-eol &&
517 >used &&
518 >unused &&
519 git add used unused &&
520 echo "used" >used &&
521 echo "unused " >unused &&
522 git diff-files -p used unused >patch &&
523 git apply --include=used --stat --whitespace=error <patch
524'
525
526test_done