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 test_must_fail apply_patch --whitespace=error-all &&
103 ! test -s target
104
105'
106
107test_expect_success 'whitespace=error-all, no rule' '
108
109 git config core.whitespace -trailing,-space-before,-indent &&
110 apply_patch --whitespace=error-all &&
111 test_cmp file target
112
113'
114
115test_expect_success 'whitespace=error-all, no rule (attribute)' '
116
117 git config --unset core.whitespace &&
118 echo "target -whitespace" >.gitattributes &&
119 apply_patch --whitespace=error-all &&
120 test_cmp file target
121
122'
123
124test_expect_success 'spaces inserted by tab-in-indent' '
125
126 git config core.whitespace -trailing,-space,-indent,tab &&
127 rm -f .gitattributes &&
128 test_fix % &&
129 sed -e "s/_/ /g" -e "s/>/ /" <<-\EOF >expect &&
130 An_SP in an ordinary line>and a HT.
131 ________A HT (%).
132 ________A SP and a HT (@%).
133 _________A SP, a HT and a SP (@%).
134 _______Seven SP.
135 ________Eight SP (#).
136 ________Seven SP and a HT (@%).
137 ________________Eight SP and a HT (@#%).
138 _________Seven SP, a HT and a SP (@%).
139 _________________Eight SP, a HT and a SP (@#%).
140 _______________Fifteen SP (#).
141 ________________Fifteen SP and a HT (@#%).
142 ________________Sixteen SP (#=).
143 ________________________Sixteen SP and a HT (@#%=).
144 _____a__Five SP, a non WS, two SP.
145 A line with a (!) trailing SP_
146 A line with a (!) trailing HT>
147 EOF
148 test_cmp expect target
149
150'
151
152for t in - ''
153do
154 case "$t" in '') tt='!' ;; *) tt= ;; esac
155 for s in - ''
156 do
157 case "$s" in '') ts='@' ;; *) ts= ;; esac
158 for i in - ''
159 do
160 case "$i" in '') ti='#' ti16='=';; *) ti= ti16= ;; esac
161 for h in - ''
162 do
163 [ -z "$h$i" ] && continue
164 case "$h" in '') th='%' ;; *) th= ;; esac
165 rule=${t}trailing,${s}space,${i}indent,${h}tab
166
167 rm -f .gitattributes
168 test_expect_success "rule=$rule" '
169 git config core.whitespace "$rule" &&
170 test_fix "$tt$ts$ti$th"
171 '
172
173 test_expect_success "rule=$rule,tabwidth=16" '
174 git config core.whitespace "$rule,tabwidth=16" &&
175 test_fix "$tt$ts$ti16$th"
176 '
177
178 test_expect_success "rule=$rule (attributes)" '
179 git config --unset core.whitespace &&
180 echo "target whitespace=$rule" >.gitattributes &&
181 test_fix "$tt$ts$ti$th"
182 '
183
184 test_expect_success "rule=$rule,tabwidth=16 (attributes)" '
185 echo "target whitespace=$rule,tabwidth=16" >.gitattributes &&
186 test_fix "$tt$ts$ti16$th"
187 '
188
189 done
190 done
191 done
192done
193
194create_patch () {
195 sed -e "s/_/ /" <<-\EOF
196 diff --git a/target b/target
197 index e69de29..8bd6648 100644
198 --- a/target
199 +++ b/target
200 @@ -0,0 +1,3 @@
201 +An empty line follows
202 +
203 +A line with trailing whitespace and no newline_
204 \ No newline at end of file
205 EOF
206}
207
208test_expect_success 'trailing whitespace & no newline at the end of file' '
209 >target &&
210 create_patch >patch-file &&
211 git apply --whitespace=fix patch-file &&
212 grep "newline$" target &&
213 grep "^$" target
214'
215
216test_expect_success 'blank at EOF with --whitespace=fix (1)' '
217 test_might_fail git config --unset core.whitespace &&
218 rm -f .gitattributes &&
219
220 { echo a; echo b; echo c; } >one &&
221 git add one &&
222 { echo a; echo b; echo c; } >expect &&
223 { cat expect; echo; } >one &&
224 git diff -- one >patch &&
225
226 git checkout one &&
227 git apply --whitespace=fix patch &&
228 test_cmp expect one
229'
230
231test_expect_success 'blank at EOF with --whitespace=fix (2)' '
232 { echo a; echo b; echo c; } >one &&
233 git add one &&
234 { echo a; echo c; } >expect &&
235 { cat expect; echo; echo; } >one &&
236 git diff -- one >patch &&
237
238 git checkout one &&
239 git apply --whitespace=fix patch &&
240 test_cmp expect one
241'
242
243test_expect_success 'blank at EOF with --whitespace=fix (3)' '
244 { echo a; echo b; echo; } >one &&
245 git add one &&
246 { echo a; echo c; echo; } >expect &&
247 { cat expect; echo; echo; } >one &&
248 git diff -- one >patch &&
249
250 git checkout one &&
251 git apply --whitespace=fix patch &&
252 test_cmp expect one
253'
254
255test_expect_success 'blank at end of hunk, not at EOF with --whitespace=fix' '
256 { echo a; echo b; echo; echo; echo; echo; echo; echo d; } >one &&
257 git add one &&
258 { echo a; echo c; echo; echo; echo; echo; echo; echo; echo d; } >expect &&
259 cp expect one &&
260 git diff -- one >patch &&
261
262 git checkout one &&
263 git apply --whitespace=fix patch &&
264 test_cmp expect one
265'
266
267test_expect_success 'blank at EOF with --whitespace=warn' '
268 { echo a; echo b; echo c; } >one &&
269 git add one &&
270 echo >>one &&
271 cat one >expect &&
272 git diff -- one >patch &&
273
274 git checkout one &&
275 git apply --whitespace=warn patch 2>error &&
276 test_cmp expect one &&
277 grep "new blank line at EOF" error
278'
279
280test_expect_success 'blank at EOF with --whitespace=error' '
281 { echo a; echo b; echo c; } >one &&
282 git add one &&
283 cat one >expect &&
284 echo >>one &&
285 git diff -- one >patch &&
286
287 git checkout one &&
288 test_must_fail git apply --whitespace=error patch 2>error &&
289 test_cmp expect one &&
290 grep "new blank line at EOF" error
291'
292
293test_expect_success 'blank but not empty at EOF' '
294 { echo a; echo b; echo c; } >one &&
295 git add one &&
296 echo " " >>one &&
297 cat one >expect &&
298 git diff -- one >patch &&
299
300 git checkout one &&
301 git apply --whitespace=warn patch 2>error &&
302 test_cmp expect one &&
303 grep "new blank line at EOF" error
304'
305
306test_expect_success 'applying beyond EOF requires one non-blank context line' '
307 { echo; echo; echo; echo; } >one &&
308 git add one &&
309 { echo b; } >>one &&
310 git diff -- one >patch &&
311
312 git checkout one &&
313 { echo a; echo; } >one &&
314 cp one expect &&
315 test_must_fail git apply --whitespace=fix patch &&
316 test_cmp one expect &&
317 test_must_fail git apply --ignore-space-change --whitespace=fix patch &&
318 test_cmp one expect
319'
320
321test_expect_success 'tons of blanks at EOF should not apply' '
322 for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16; do
323 echo; echo; echo; echo;
324 done >one &&
325 git add one &&
326 echo a >>one &&
327 git diff -- one >patch &&
328
329 >one &&
330 test_must_fail git apply --whitespace=fix patch &&
331 test_must_fail git apply --ignore-space-change --whitespace=fix patch
332'
333
334test_expect_success 'missing blank line at end with --whitespace=fix' '
335 echo a >one &&
336 echo >>one &&
337 git add one &&
338 echo b >>one &&
339 cp one expect &&
340 git diff -- one >patch &&
341 echo a >one &&
342 cp one saved-one &&
343 test_must_fail git apply patch &&
344 git apply --whitespace=fix patch &&
345 test_cmp one expect &&
346 mv saved-one one &&
347 git apply --ignore-space-change --whitespace=fix patch &&
348 test_cmp one expect
349'
350
351test_expect_success 'two missing blank lines at end with --whitespace=fix' '
352 { echo a; echo; echo b; echo c; } >one &&
353 cp one no-blank-lines &&
354 { echo; echo; } >>one &&
355 git add one &&
356 echo d >>one &&
357 cp one expect &&
358 echo >>one &&
359 git diff -- one >patch &&
360 cp no-blank-lines one &&
361 test_must_fail git apply patch &&
362 git apply --whitespace=fix patch &&
363 test_cmp one expect &&
364 mv no-blank-lines one &&
365 test_must_fail git apply patch &&
366 git apply --ignore-space-change --whitespace=fix patch &&
367 test_cmp one expect
368'
369
370test_expect_success 'missing blank line at end, insert before end, --whitespace=fix' '
371 { echo a; echo; } >one &&
372 git add one &&
373 { echo b; echo a; echo; } >one &&
374 cp one expect &&
375 git diff -- one >patch &&
376 echo a >one &&
377 test_must_fail git apply patch &&
378 git apply --whitespace=fix patch &&
379 test_cmp one expect
380'
381
382test_expect_success 'shrink file with tons of missing blanks at end of file' '
383 { echo a; echo b; echo c; } >one &&
384 cp one no-blank-lines &&
385 for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16; do
386 echo; echo; echo; echo;
387 done >>one &&
388 git add one &&
389 echo a >one &&
390 cp one expect &&
391 git diff -- one >patch &&
392 cp no-blank-lines one &&
393 test_must_fail git apply patch &&
394 git apply --whitespace=fix patch &&
395 test_cmp one expect &&
396 mv no-blank-lines one &&
397 git apply --ignore-space-change --whitespace=fix patch &&
398 test_cmp one expect
399'
400
401test_expect_success 'missing blanks at EOF must only match blank lines' '
402 { echo a; echo b; } >one &&
403 git add one &&
404 { echo c; echo d; } >>one &&
405 git diff -- one >patch &&
406
407 echo a >one &&
408 test_must_fail git apply patch &&
409 test_must_fail git apply --whitespace=fix patch &&
410 test_must_fail git apply --ignore-space-change --whitespace=fix patch
411'
412
413sed -e's/Z//' >one <<EOF
414a
415b
416c
417 Z
418EOF
419
420test_expect_success 'missing blank line should match context line with spaces' '
421 git add one &&
422 echo d >>one &&
423 git diff -- one >patch &&
424 { echo a; echo b; echo c; } >one &&
425 cp one expect &&
426 { echo; echo d; } >>expect &&
427 git add one &&
428
429 git apply --whitespace=fix patch &&
430 test_cmp one expect
431'
432
433sed -e's/Z//' >one <<EOF
434a
435b
436c
437 Z
438EOF
439
440test_expect_success 'same, but with the --ignore-space-option' '
441 git add one &&
442 echo d >>one &&
443 cp one expect &&
444 git diff -- one >patch &&
445 { echo a; echo b; echo c; } >one &&
446 git add one &&
447
448 git checkout-index -f one &&
449 git apply --ignore-space-change --whitespace=fix patch &&
450 test_cmp one expect
451'
452
453test_expect_success 'same, but with CR-LF line endings && cr-at-eol set' '
454 git config core.whitespace cr-at-eol &&
455 printf "a\r\n" >one &&
456 printf "b\r\n" >>one &&
457 printf "c\r\n" >>one &&
458 cp one save-one &&
459 printf " \r\n" >>one &&
460 git add one &&
461 printf "d\r\n" >>one &&
462 cp one expect &&
463 git diff -- one >patch &&
464 mv save-one one &&
465
466 git apply --ignore-space-change --whitespace=fix patch &&
467 test_cmp one expect
468'
469
470test_expect_success 'CR-LF line endings && add line && text=auto' '
471 git config --unset core.whitespace &&
472 printf "a\r\n" >one &&
473 cp one save-one &&
474 git add one &&
475 printf "b\r\n" >>one &&
476 cp one expect &&
477 git diff -- one >patch &&
478 mv save-one one &&
479 echo "one text=auto" >.gitattributes &&
480 git apply patch &&
481 test_cmp one expect
482'
483
484test_expect_success 'CR-LF line endings && change line && text=auto' '
485 printf "a\r\n" >one &&
486 cp one save-one &&
487 git add one &&
488 printf "b\r\n" >one &&
489 cp one expect &&
490 git diff -- one >patch &&
491 mv save-one one &&
492 echo "one text=auto" >.gitattributes &&
493 git apply patch &&
494 test_cmp one expect
495'
496
497test_expect_success 'LF in repo, CRLF in worktree && change line && text=auto' '
498 printf "a\n" >one &&
499 git add one &&
500 printf "b\r\n" >one &&
501 git diff -- one >patch &&
502 printf "a\r\n" >one &&
503 echo "one text=auto" >.gitattributes &&
504 git -c core.eol=CRLF apply patch &&
505 printf "b\r\n" >expect &&
506 test_cmp one expect
507'
508
509test_expect_success 'whitespace=fix to expand' '
510 qz_to_tab_space >preimage <<-\EOF &&
511 QQa
512 QQb
513 QQc
514 ZZZZZZZZZZZZZZZZd
515 QQe
516 QQf
517 QQg
518 EOF
519 qz_to_tab_space >patch <<-\EOF &&
520 diff --git a/preimage b/preimage
521 --- a/preimage
522 +++ b/preimage
523 @@ -1,7 +1,6 @@
524 QQa
525 QQb
526 QQc
527 -QQd
528 QQe
529 QQf
530 QQg
531 EOF
532 git -c core.whitespace=tab-in-indent apply --whitespace=fix patch
533'
534
535test_expect_success 'whitespace check skipped for excluded paths' '
536 git config core.whitespace blank-at-eol &&
537 >used &&
538 >unused &&
539 git add used unused &&
540 echo "used" >used &&
541 echo "unused " >unused &&
542 git diff-files -p used unused >patch &&
543 git apply --include=used --stat --whitespace=error <patch
544'
545
546test_done