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