4a369fcb518c0dcbada86968a83e1d7d137de706
1#!/bin/sh
2
3test_description='add -i basic tests'
4. ./test-lib.sh
5. "$TEST_DIRECTORY"/lib-terminal.sh
6
7if ! test_have_prereq PERL
8then
9 skip_all='skipping add -i tests, perl not available'
10 test_done
11fi
12
13test_expect_success 'setup (initial)' '
14 echo content >file &&
15 git add file &&
16 echo more >>file &&
17 echo lines >>file
18'
19test_expect_success 'status works (initial)' '
20 git add -i </dev/null >output &&
21 grep "+1/-0 *+2/-0 file" output
22'
23
24test_expect_success 'setup expected' '
25 cat >expected <<-\EOF
26 new file mode 100644
27 index 0000000..d95f3ad
28 --- /dev/null
29 +++ b/file
30 @@ -0,0 +1 @@
31 +content
32 EOF
33'
34
35test_expect_success 'diff works (initial)' '
36 (echo d; echo 1) | git add -i >output &&
37 sed -ne "/new file/,/content/p" <output >diff &&
38 test_cmp expected diff
39'
40test_expect_success 'revert works (initial)' '
41 git add file &&
42 (echo r; echo 1) | git add -i &&
43 git ls-files >output &&
44 ! grep . output
45'
46
47test_expect_success 'setup (commit)' '
48 echo baseline >file &&
49 git add file &&
50 git commit -m commit &&
51 echo content >>file &&
52 git add file &&
53 echo more >>file &&
54 echo lines >>file
55'
56test_expect_success 'status works (commit)' '
57 git add -i </dev/null >output &&
58 grep "+1/-0 *+2/-0 file" output
59'
60
61test_expect_success 'setup expected' '
62 cat >expected <<-\EOF
63 index 180b47c..b6f2c08 100644
64 --- a/file
65 +++ b/file
66 @@ -1 +1,2 @@
67 baseline
68 +content
69 EOF
70'
71
72test_expect_success 'diff works (commit)' '
73 (echo d; echo 1) | git add -i >output &&
74 sed -ne "/^index/,/content/p" <output >diff &&
75 test_cmp expected diff
76'
77test_expect_success 'revert works (commit)' '
78 git add file &&
79 (echo r; echo 1) | git add -i &&
80 git add -i </dev/null >output &&
81 grep "unchanged *+3/-0 file" output
82'
83
84
85test_expect_success 'setup expected' '
86 cat >expected <<-\EOF
87 EOF
88'
89
90test_expect_success 'dummy edit works' '
91 test_set_editor : &&
92 (echo e; echo a) | git add -p &&
93 git diff > diff &&
94 test_cmp expected diff
95'
96
97test_expect_success 'setup patch' '
98 cat >patch <<-\EOF
99 @@ -1,1 +1,4 @@
100 this
101 +patch
102 -does not
103 apply
104 EOF
105'
106
107test_expect_success 'setup fake editor' '
108 write_script "fake_editor.sh" <<-\EOF &&
109 mv -f "$1" oldpatch &&
110 mv -f patch "$1"
111 EOF
112 test_set_editor "$(pwd)/fake_editor.sh"
113'
114
115test_expect_success 'bad edit rejected' '
116 git reset &&
117 (echo e; echo n; echo d) | git add -p >output &&
118 grep "hunk does not apply" output
119'
120
121test_expect_success 'setup patch' '
122 cat >patch <<-\EOF
123 this patch
124 is garbage
125 EOF
126'
127
128test_expect_success 'garbage edit rejected' '
129 git reset &&
130 (echo e; echo n; echo d) | git add -p >output &&
131 grep "hunk does not apply" output
132'
133
134test_expect_success 'setup patch' '
135 cat >patch <<-\EOF
136 @@ -1,0 +1,0 @@
137 baseline
138 +content
139 +newcontent
140 +lines
141 EOF
142'
143
144test_expect_success 'setup expected' '
145 cat >expected <<-\EOF
146 diff --git a/file b/file
147 index b5dd6c9..f910ae9 100644
148 --- a/file
149 +++ b/file
150 @@ -1,4 +1,4 @@
151 baseline
152 content
153 -newcontent
154 +more
155 lines
156 EOF
157'
158
159test_expect_success 'real edit works' '
160 (echo e; echo n; echo d) | git add -p &&
161 git diff >output &&
162 test_cmp expected output
163'
164
165test_expect_success 'skip files similarly as commit -a' '
166 git reset &&
167 echo file >.gitignore &&
168 echo changed >file &&
169 echo y | git add -p file &&
170 git diff >output &&
171 git reset &&
172 git commit -am commit &&
173 git diff >expected &&
174 test_cmp expected output &&
175 git reset --hard HEAD^
176'
177rm -f .gitignore
178
179test_expect_success FILEMODE 'patch does not affect mode' '
180 git reset --hard &&
181 echo content >>file &&
182 chmod +x file &&
183 printf "n\\ny\\n" | git add -p &&
184 git show :file | grep content &&
185 git diff file | grep "new mode"
186'
187
188test_expect_success FILEMODE 'stage mode but not hunk' '
189 git reset --hard &&
190 echo content >>file &&
191 chmod +x file &&
192 printf "y\\nn\\n" | git add -p &&
193 git diff --cached file | grep "new mode" &&
194 git diff file | grep "+content"
195'
196
197
198test_expect_success FILEMODE 'stage mode and hunk' '
199 git reset --hard &&
200 echo content >>file &&
201 chmod +x file &&
202 printf "y\\ny\\n" | git add -p &&
203 git diff --cached file | grep "new mode" &&
204 git diff --cached file | grep "+content" &&
205 test -z "$(git diff file)"
206'
207
208# end of tests disabled when filemode is not usable
209
210test_expect_success 'setup again' '
211 git reset --hard &&
212 test_chmod +x file &&
213 echo content >>file
214'
215
216# Write the patch file with a new line at the top and bottom
217test_expect_success 'setup patch' '
218 cat >patch <<-\EOF
219 index 180b47c..b6f2c08 100644
220 --- a/file
221 +++ b/file
222 @@ -1,2 +1,4 @@
223 +firstline
224 baseline
225 content
226 +lastline
227 EOF
228'
229
230# Expected output, similar to the patch but w/ diff at the top
231test_expect_success 'setup expected' '
232 cat >expected <<-\EOF
233 diff --git a/file b/file
234 index b6f2c08..61b9053 100755
235 --- a/file
236 +++ b/file
237 @@ -1,2 +1,4 @@
238 +firstline
239 baseline
240 content
241 +lastline
242 EOF
243'
244
245# Test splitting the first patch, then adding both
246test_expect_success 'add first line works' '
247 git commit -am "clear local changes" &&
248 git apply patch &&
249 (echo s; echo y; echo y) | git add -p file &&
250 git diff --cached > diff &&
251 test_cmp expected diff
252'
253
254test_expect_success 'setup expected' '
255 cat >expected <<-\EOF
256 diff --git a/non-empty b/non-empty
257 deleted file mode 100644
258 index d95f3ad..0000000
259 --- a/non-empty
260 +++ /dev/null
261 @@ -1 +0,0 @@
262 -content
263 EOF
264'
265
266test_expect_success 'deleting a non-empty file' '
267 git reset --hard &&
268 echo content >non-empty &&
269 git add non-empty &&
270 git commit -m non-empty &&
271 rm non-empty &&
272 echo y | git add -p non-empty &&
273 git diff --cached >diff &&
274 test_cmp expected diff
275'
276
277test_expect_success 'setup expected' '
278 cat >expected <<-\EOF
279 diff --git a/empty b/empty
280 deleted file mode 100644
281 index e69de29..0000000
282 EOF
283'
284
285test_expect_success 'deleting an empty file' '
286 git reset --hard &&
287 > empty &&
288 git add empty &&
289 git commit -m empty &&
290 rm empty &&
291 echo y | git add -p empty &&
292 git diff --cached >diff &&
293 test_cmp expected diff
294'
295
296test_expect_success 'split hunk setup' '
297 git reset --hard &&
298 test_write_lines 10 20 30 40 50 60 >test &&
299 git add test &&
300 test_tick &&
301 git commit -m test &&
302
303 test_write_lines 10 15 20 21 22 23 24 30 40 50 60 >test
304'
305
306test_expect_success 'split hunk "add -p (edit)"' '
307 # Split, say Edit and do nothing. Then:
308 #
309 # 1. Broken version results in a patch that does not apply and
310 # only takes [y/n] (edit again) so the first q is discarded
311 # and then n attempts to discard the edit. Repeat q enough
312 # times to get out.
313 #
314 # 2. Correct version applies the (not)edited version, and asks
315 # about the next hunk, against which we say q and program
316 # exits.
317 printf "%s\n" s e q n q q |
318 EDITOR=: git add -p &&
319 git diff >actual &&
320 ! grep "^+15" actual
321'
322
323test_expect_failure 'split hunk "add -p (no, yes, edit)"' '
324 test_write_lines 5 10 20 21 30 31 40 50 60 >test &&
325 git reset &&
326 # test sequence is s(plit), n(o), y(es), e(dit)
327 # q n q q is there to make sure we exit at the end.
328 printf "%s\n" s n y e q n q q |
329 EDITOR=: git add -p 2>error &&
330 test_must_be_empty error &&
331 git diff >actual &&
332 ! grep "^+31" actual
333'
334
335test_expect_success 'patch mode ignores unmerged entries' '
336 git reset --hard &&
337 test_commit conflict &&
338 test_commit non-conflict &&
339 git checkout -b side &&
340 test_commit side conflict.t &&
341 git checkout master &&
342 test_commit master conflict.t &&
343 test_must_fail git merge side &&
344 echo changed >non-conflict.t &&
345 echo y | git add -p >output &&
346 ! grep a/conflict.t output &&
347 cat >expected <<-\EOF &&
348 * Unmerged path conflict.t
349 diff --git a/non-conflict.t b/non-conflict.t
350 index f766221..5ea2ed4 100644
351 --- a/non-conflict.t
352 +++ b/non-conflict.t
353 @@ -1 +1 @@
354 -non-conflict
355 +changed
356 EOF
357 git diff --cached >diff &&
358 test_cmp expected diff
359'
360
361test_expect_success TTY 'diffs can be colorized' '
362 git reset --hard &&
363
364 echo content >test &&
365 printf y | test_terminal git add -p >output 2>&1 &&
366
367 # We do not want to depend on the exact coloring scheme
368 # git uses for diffs, so just check that we saw some kind of color.
369 grep "$(printf "\\033")" output
370'
371
372test_expect_success 'patch-mode via -i prompts for files' '
373 git reset --hard &&
374
375 echo one >file &&
376 echo two >test &&
377 git add -i <<-\EOF &&
378 patch
379 test
380
381 y
382 quit
383 EOF
384
385 echo test >expect &&
386 git diff --cached --name-only >actual &&
387 test_cmp expect actual
388'
389
390test_expect_success 'add -p handles globs' '
391 git reset --hard &&
392
393 mkdir -p subdir &&
394 echo base >one.c &&
395 echo base >subdir/two.c &&
396 git add "*.c" &&
397 git commit -m base &&
398
399 echo change >one.c &&
400 echo change >subdir/two.c &&
401 git add -p "*.c" <<-\EOF &&
402 y
403 y
404 EOF
405
406 cat >expect <<-\EOF &&
407 one.c
408 subdir/two.c
409 EOF
410 git diff --cached --name-only >actual &&
411 test_cmp expect actual
412'
413
414test_expect_success 'add -p handles relative paths' '
415 git reset --hard &&
416
417 echo base >relpath.c &&
418 git add "*.c" &&
419 git commit -m relpath &&
420
421 echo change >relpath.c &&
422 mkdir -p subdir &&
423 git -C subdir add -p .. 2>error <<-\EOF &&
424 y
425 EOF
426
427 test_must_be_empty error &&
428
429 cat >expect <<-\EOF &&
430 relpath.c
431 EOF
432 git diff --cached --name-only >actual &&
433 test_cmp expect actual
434'
435
436test_expect_success 'add -p does not expand argument lists' '
437 git reset --hard &&
438
439 echo content >not-changed &&
440 git add not-changed &&
441 git commit -m "add not-changed file" &&
442
443 echo change >file &&
444 GIT_TRACE=$(pwd)/trace.out git add -p . <<-\EOF &&
445 y
446 EOF
447
448 # we know that "file" must be mentioned since we actually
449 # update it, but we want to be sure that our "." pathspec
450 # was not expanded into the argument list of any command.
451 # So look only for "not-changed".
452 ! grep not-changed trace.out
453'
454
455test_expect_success 'hunk-editing handles custom comment char' '
456 git reset --hard &&
457 echo change >>file &&
458 test_config core.commentChar "\$" &&
459 echo e | GIT_EDITOR=true git add -p &&
460 git diff --exit-code
461'
462
463test_expect_success 'add -p works even with color.ui=always' '
464 git reset --hard &&
465 echo change >>file &&
466 test_config color.ui always &&
467 echo y | git add -p &&
468 echo file >expect &&
469 git diff --cached --name-only >actual &&
470 test_cmp expect actual
471'
472
473test_done