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