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
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
35apply_patch () {
36 >target &&
37 sed -e "s|\([ab]\)/file|\1/target|" <patch |
38 git apply "$@"
39}
40
41test_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
74test_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
85test_expect_success 'whitespace=nowarn, default rule' '
86
87 apply_patch --whitespace=nowarn &&
88 diff file target
89
90'
91
92test_expect_success 'whitespace=warn, default rule' '
93
94 apply_patch --whitespace=warn &&
95 diff file target
96
97'
98
99test_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
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 diff 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 diff file target
121
122'
123
124for t in - ''
125do
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
149done
150
151create_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
165test_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
173test_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
189test_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
201test_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
213test_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
225test_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
238test_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
251test_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
264test_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
279test_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
292test_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
309test_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
328test_expect_success 'shrink file with tons of missing blanks at end of file' '
329 { echo a; echo b; echo c; } >one &&
330 cp one no-blank-lines &&
331 for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16; do
332 echo; echo; echo; echo;
333 done >>one &&
334 git add one &&
335 echo a >one &&
336 cp one expect &&
337 git diff -- one >patch &&
338 cp no-blank-lines one &&
339 test_must_fail git apply patch &&
340 git apply --whitespace=fix patch &&
341 test_cmp one expect &&
342 mv no-blank-lines one &&
343 git apply --ignore-space-change --whitespace=fix patch &&
344 test_cmp one expect
345'
346
347test_expect_success 'missing blanks at EOF must only match blank lines' '
348 { echo a; echo b; } >one &&
349 git add one &&
350 { echo c; echo d; } >>one &&
351 git diff -- one >patch &&
352
353 echo a >one &&
354 test_must_fail git apply patch
355 test_must_fail git apply --whitespace=fix patch &&
356 test_must_fail git apply --ignore-space-change --whitespace=fix patch
357'
358
359sed -e's/Z//' >one <<EOF
360a
361b
362c
363 Z
364EOF
365
366test_expect_success 'missing blank line should match context line with spaces' '
367 git add one &&
368 echo d >>one &&
369 git diff -- one >patch &&
370 { echo a; echo b; echo c; } >one &&
371 cp one expect &&
372 { echo; echo d; } >>expect &&
373 git add one &&
374
375 git apply --whitespace=fix patch &&
376 test_cmp one expect
377'
378
379sed -e's/Z//' >one <<EOF
380a
381b
382c
383 Z
384EOF
385
386test_expect_success 'same, but with the --ignore-space-option' '
387 git add one &&
388 echo d >>one &&
389 cp one expect &&
390 git diff -- one >patch &&
391 { echo a; echo b; echo c; } >one &&
392 git add one &&
393
394 git checkout-index -f one &&
395 git apply --ignore-space-change --whitespace=fix patch &&
396 test_cmp one expect
397'
398
399test_expect_success 'same, but with CR-LF line endings && cr-at-eol set' '
400 git config core.whitespace cr-at-eol &&
401 printf "a\r\n" >one &&
402 printf "b\r\n" >>one &&
403 printf "c\r\n" >>one &&
404 cp one save-one &&
405 printf " \r\n" >>one
406 git add one &&
407 printf "d\r\n" >>one &&
408 cp one expect &&
409 git diff -- one >patch &&
410 mv save-one one &&
411
412 git apply --ignore-space-change --whitespace=fix patch &&
413 test_cmp one expect
414'
415
416test_expect_success 'same, but with CR-LF line endings && cr-at-eol unset' '
417 git config --unset core.whitespace &&
418 printf "a\r\n" >one &&
419 printf "b\r\n" >>one &&
420 printf "c\r\n" >>one &&
421 cp one save-one &&
422 printf " \r\n" >>one
423 git add one &&
424 cp one expect &&
425 printf "d\r\n" >>one &&
426 git diff -- one >patch &&
427 mv save-one one &&
428 echo d >>expect &&
429
430 git apply --ignore-space-change --whitespace=fix patch &&
431 test_cmp one expect
432'
433
434test_done