Merge branch 'np/pack-broken-boundary'
[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         #       %  tab-in-indent
15         sed -e "s/_/ /g" -e "s/>/       /" <<-\EOF
16                 An_SP in an ordinary line>and a HT.
17                 >A HT (%).
18                 _>A SP and a HT (@%).
19                 _>_A SP, a HT and a SP (@%).
20                 _______Seven SP.
21                 ________Eight SP (#).
22                 _______>Seven SP and a HT (@%).
23                 ________>Eight SP and a HT (@#%).
24                 _______>_Seven SP, a HT and a SP (@%).
25                 ________>_Eight SP, a HT and a SP (@#%).
26                 _______________Fifteen SP (#).
27                 _______________>Fifteen SP and a HT (@#%).
28                 ________________Sixteen SP (#).
29                 ________________>Sixteen SP and a HT (@#%).
30                 _____a__Five SP, a non WS, two SP.
31                 A line with a (!) trailing SP_
32                 A line with a (!) trailing HT>
33         EOF
34 }
35
36 apply_patch () {
37         >target &&
38         sed -e "s|\([ab]\)/file|\1/target|" <patch |
39         git apply "$@"
40 }
41
42 test_fix () {
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         test_cmp file target
89
90 '
91
92 test_expect_success 'whitespace=warn, default rule' '
93
94         apply_patch --whitespace=warn &&
95         test_cmp 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         test_cmp 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         test_cmp 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                         for h in - ''
134                         do
135                                 [ -z "$h$i" ] && continue
136                                 case "$h" in '') th='%' ;; *) th= ;; esac
137                                 rule=${t}trailing,${s}space,${i}indent,${h}tab
138
139                                 rm -f .gitattributes
140                                 test_expect_success "rule=$rule" '
141                                         git config core.whitespace "$rule" &&
142                                         test_fix "$tt$ts$ti$th"
143                                 '
144
145                                 test_expect_success "rule=$rule (attributes)" '
146                                         git config --unset core.whitespace &&
147                                         echo "target whitespace=$rule" >.gitattributes &&
148                                         test_fix "$tt$ts$ti$th"
149                                 '
150
151                         done
152                 done
153         done
154 done
155
156 create_patch () {
157         sed -e "s/_/ /" <<-\EOF
158                 diff --git a/target b/target
159                 index e69de29..8bd6648 100644
160                 --- a/target
161                 +++ b/target
162                 @@ -0,0 +1,3 @@
163                 +An empty line follows
164                 +
165                 +A line with trailing whitespace and no newline_
166                 \ No newline at end of file
167         EOF
168 }
169
170 test_expect_success 'trailing whitespace & no newline at the end of file' '
171         >target &&
172         create_patch >patch-file &&
173         git apply --whitespace=fix patch-file &&
174         grep "newline$" target &&
175         grep "^$" target
176 '
177
178 test_expect_success 'blank at EOF with --whitespace=fix (1)' '
179         test_might_fail git config --unset core.whitespace &&
180         rm -f .gitattributes &&
181
182         { echo a; echo b; echo c; } >one &&
183         git add one &&
184         { echo a; echo b; echo c; } >expect &&
185         { cat expect; echo; } >one &&
186         git diff -- one >patch &&
187
188         git checkout one &&
189         git apply --whitespace=fix patch &&
190         test_cmp expect one
191 '
192
193 test_expect_success 'blank at EOF with --whitespace=fix (2)' '
194         { echo a; echo b; echo c; } >one &&
195         git add one &&
196         { echo a; echo c; } >expect &&
197         { cat expect; echo; echo; } >one &&
198         git diff -- one >patch &&
199
200         git checkout one &&
201         git apply --whitespace=fix patch &&
202         test_cmp expect one
203 '
204
205 test_expect_success 'blank at EOF with --whitespace=fix (3)' '
206         { echo a; echo b; echo; } >one &&
207         git add one &&
208         { echo a; echo c; echo; } >expect &&
209         { cat expect; echo; echo; } >one &&
210         git diff -- one >patch &&
211
212         git checkout one &&
213         git apply --whitespace=fix patch &&
214         test_cmp expect one
215 '
216
217 test_expect_success 'blank at end of hunk, not at EOF with --whitespace=fix' '
218         { echo a; echo b; echo; echo; echo; echo; echo; echo d; } >one &&
219         git add one &&
220         { echo a; echo c; echo; echo; echo; echo; echo; echo; echo d; } >expect &&
221         cp expect one &&
222         git diff -- one >patch &&
223
224         git checkout one &&
225         git apply --whitespace=fix patch &&
226         test_cmp expect one
227 '
228
229 test_expect_success 'blank at EOF with --whitespace=warn' '
230         { echo a; echo b; echo c; } >one &&
231         git add one &&
232         echo >>one &&
233         cat one >expect &&
234         git diff -- one >patch &&
235
236         git checkout one &&
237         git apply --whitespace=warn patch 2>error &&
238         test_cmp expect one &&
239         grep "new blank line at EOF" error
240 '
241
242 test_expect_success 'blank at EOF with --whitespace=error' '
243         { echo a; echo b; echo c; } >one &&
244         git add one &&
245         cat one >expect &&
246         echo >>one &&
247         git diff -- one >patch &&
248
249         git checkout one &&
250         test_must_fail git apply --whitespace=error patch 2>error &&
251         test_cmp expect one &&
252         grep "new blank line at EOF" error
253 '
254
255 test_expect_success 'blank but not empty at EOF' '
256         { echo a; echo b; echo c; } >one &&
257         git add one &&
258         echo "   " >>one &&
259         cat one >expect &&
260         git diff -- one >patch &&
261
262         git checkout one &&
263         git apply --whitespace=warn patch 2>error &&
264         test_cmp expect one &&
265         grep "new blank line at EOF" error
266 '
267
268 test_expect_success 'applying beyond EOF requires one non-blank context line' '
269         { echo; echo; echo; echo; } >one &&
270         git add one &&
271         { echo b; } >>one &&
272         git diff -- one >patch &&
273
274         git checkout one &&
275         { echo a; echo; } >one &&
276         cp one expect &&
277         test_must_fail git apply --whitespace=fix patch &&
278         test_cmp one expect &&
279         test_must_fail git apply --ignore-space-change --whitespace=fix patch &&
280         test_cmp one expect
281 '
282
283 test_expect_success 'tons of blanks at EOF should not apply' '
284         for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16; do
285                 echo; echo; echo; echo;
286         done >one &&
287         git add one &&
288         echo a >>one &&
289         git diff -- one >patch &&
290
291         >one &&
292         test_must_fail git apply --whitespace=fix patch &&
293         test_must_fail git apply --ignore-space-change --whitespace=fix patch
294 '
295
296 test_expect_success 'missing blank line at end with --whitespace=fix' '
297         echo a >one &&
298         echo >>one &&
299         git add one &&
300         echo b >>one &&
301         cp one expect &&
302         git diff -- one >patch &&
303         echo a >one &&
304         cp one saved-one &&
305         test_must_fail git apply patch &&
306         git apply --whitespace=fix patch &&
307         test_cmp one expect &&
308         mv saved-one one &&
309         git apply --ignore-space-change --whitespace=fix patch &&
310         test_cmp one expect
311 '
312
313 test_expect_success 'two missing blank lines at end with --whitespace=fix' '
314         { echo a; echo; echo b; echo c; } >one &&
315         cp one no-blank-lines &&
316         { echo; echo; } >>one &&
317         git add one &&
318         echo d >>one &&
319         cp one expect &&
320         echo >>one &&
321         git diff -- one >patch &&
322         cp no-blank-lines one &&
323         test_must_fail git apply patch &&
324         git apply --whitespace=fix patch &&
325         test_cmp one expect &&
326         mv no-blank-lines one &&
327         test_must_fail git apply patch &&
328         git apply --ignore-space-change --whitespace=fix patch &&
329         test_cmp one expect
330 '
331
332 test_expect_success 'missing blank line at end, insert before end, --whitespace=fix' '
333         { echo a; echo; } >one &&
334         git add one &&
335         { echo b; echo a; echo; } >one &&
336         cp one expect &&
337         git diff -- one >patch &&
338         echo a >one &&
339         test_must_fail git apply patch &&
340         git apply --whitespace=fix patch &&
341         test_cmp one expect
342 '
343
344 test_expect_success 'shrink file with tons of missing blanks at end of file' '
345         { echo a; echo b; echo c; } >one &&
346         cp one no-blank-lines &&
347         for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16; do
348                 echo; echo; echo; echo;
349         done >>one &&
350         git add one &&
351         echo a >one &&
352         cp one expect &&
353         git diff -- one >patch &&
354         cp no-blank-lines one &&
355         test_must_fail git apply patch &&
356         git apply --whitespace=fix patch &&
357         test_cmp one expect &&
358         mv no-blank-lines one &&
359         git apply --ignore-space-change --whitespace=fix patch &&
360         test_cmp one expect
361 '
362
363 test_expect_success 'missing blanks at EOF must only match blank lines' '
364         { echo a; echo b; } >one &&
365         git add one &&
366         { echo c; echo d; } >>one &&
367         git diff -- one >patch &&
368
369         echo a >one &&
370         test_must_fail git apply patch &&
371         test_must_fail git apply --whitespace=fix patch &&
372         test_must_fail git apply --ignore-space-change --whitespace=fix patch
373 '
374
375 sed -e's/Z//' >one <<EOF
376 a
377 b
378 c
379                       Z
380 EOF
381
382 test_expect_success 'missing blank line should match context line with spaces' '
383         git add one &&
384         echo d >>one &&
385         git diff -- one >patch &&
386         { echo a; echo b; echo c; } >one &&
387         cp one expect &&
388         { echo; echo d; } >>expect &&
389         git add one &&
390
391         git apply --whitespace=fix patch &&
392         test_cmp one expect
393 '
394
395 sed -e's/Z//' >one <<EOF
396 a
397 b
398 c
399                       Z
400 EOF
401
402 test_expect_success 'same, but with the --ignore-space-option' '
403         git add one &&
404         echo d >>one &&
405         cp one expect &&
406         git diff -- one >patch &&
407         { echo a; echo b; echo c; } >one &&
408         git add one &&
409
410         git checkout-index -f one &&
411         git apply --ignore-space-change --whitespace=fix patch &&
412         test_cmp one expect
413 '
414
415 test_expect_success 'same, but with CR-LF line endings && cr-at-eol set' '
416         git config core.whitespace cr-at-eol &&
417         printf "a\r\n" >one &&
418         printf "b\r\n" >>one &&
419         printf "c\r\n" >>one &&
420         cp one save-one &&
421         printf "                 \r\n" >>one &&
422         git add one &&
423         printf "d\r\n" >>one &&
424         cp one expect &&
425         git diff -- one >patch &&
426         mv save-one one &&
427
428         git apply --ignore-space-change --whitespace=fix patch &&
429         test_cmp one expect
430 '
431
432 test_expect_success 'same, but with CR-LF line endings && cr-at-eol unset' '
433         git config --unset core.whitespace &&
434         printf "a\r\n" >one &&
435         printf "b\r\n" >>one &&
436         printf "c\r\n" >>one &&
437         cp one save-one &&
438         printf "                 \r\n" >>one &&
439         git add one &&
440         cp one expect &&
441         printf "d\r\n" >>one &&
442         git diff -- one >patch &&
443         mv save-one one &&
444         echo d >>expect &&
445
446         git apply --ignore-space-change --whitespace=fix patch &&
447         test_cmp one expect
448 '
449
450 test_done