Merge branch 'js/update-index-ignore-removal-for-skip-worktree'
[git] / t / t3600-rm.sh
1 #!/bin/sh
2 #
3 # Copyright (c) 2006 Carl D. Worth
4 #
5
6 test_description='Test of the various options to git rm.'
7
8 . ./test-lib.sh
9
10 # Setup some files to be removed, some with funny characters
11 test_expect_success 'Initialize test directory' '
12         touch -- foo bar baz "space embedded" -q &&
13         git add -- foo bar baz "space embedded" -q &&
14         git commit -m "add normal files"
15 '
16
17 if test_have_prereq !FUNNYNAMES
18 then
19         say 'Your filesystem does not allow tabs in filenames.'
20 fi
21
22 test_expect_success FUNNYNAMES 'add files with funny names' '
23         touch -- "tab   embedded" "newline${LF}embedded" &&
24         git add -- "tab embedded" "newline${LF}embedded" &&
25         git commit -m "add files with tabs and newlines"
26 '
27
28 test_expect_success 'Pre-check that foo exists and is in index before git rm foo' '
29         test_path_is_file foo &&
30         git ls-files --error-unmatch foo
31 '
32
33 test_expect_success 'Test that git rm foo succeeds' '
34         git rm --cached foo
35 '
36
37 test_expect_success 'Test that git rm --cached foo succeeds if the index matches the file' '
38         echo content >foo &&
39         git add foo &&
40         git rm --cached foo
41 '
42
43 test_expect_success 'Test that git rm --cached foo succeeds if the index matches the file' '
44         echo content >foo &&
45         git add foo &&
46         git commit -m foo &&
47         echo "other content" >foo &&
48         git rm --cached foo
49 '
50
51 test_expect_success 'Test that git rm --cached foo fails if the index matches neither the file nor HEAD' '
52         echo content >foo &&
53         git add foo &&
54         git commit -m foo --allow-empty &&
55         echo "other content" >foo &&
56         git add foo &&
57         echo "yet another content" >foo &&
58         test_must_fail git rm --cached foo
59 '
60
61 test_expect_success 'Test that git rm --cached -f foo works in case where --cached only did not' '
62         echo content >foo &&
63         git add foo &&
64         git commit -m foo --allow-empty &&
65         echo "other content" >foo &&
66         git add foo &&
67         echo "yet another content" >foo &&
68         git rm --cached -f foo
69 '
70
71 test_expect_success 'Post-check that foo exists but is not in index after git rm foo' '
72         test_path_is_file foo &&
73         test_must_fail git ls-files --error-unmatch foo
74 '
75
76 test_expect_success 'Pre-check that bar exists and is in index before "git rm bar"' '
77         test_path_is_file bar &&
78         git ls-files --error-unmatch bar
79 '
80
81 test_expect_success 'Test that "git rm bar" succeeds' '
82         git rm bar
83 '
84
85 test_expect_success 'Post-check that bar does not exist and is not in index after "git rm -f bar"' '
86         test_path_is_missing bar &&
87         test_must_fail git ls-files --error-unmatch bar
88 '
89
90 test_expect_success 'Test that "git rm -- -q" succeeds (remove a file that looks like an option)' '
91         git rm -- -q
92 '
93
94 test_expect_success FUNNYNAMES 'Test that "git rm -f" succeeds with embedded space, tab, or newline characters.' '
95         git rm -f "space embedded" "tab embedded" "newline${LF}embedded"
96 '
97
98 test_expect_success SANITY 'Test that "git rm -f" fails if its rm fails' '
99         test_when_finished "chmod 775 ." &&
100         chmod a-w . &&
101         test_must_fail git rm -f baz
102 '
103
104 test_expect_success 'When the rm in "git rm -f" fails, it should not remove the file from the index' '
105         git ls-files --error-unmatch baz
106 '
107
108 test_expect_success 'Remove nonexistent file with --ignore-unmatch' '
109         git rm --ignore-unmatch nonexistent
110 '
111
112 test_expect_success '"rm" command printed' '
113         echo frotz >test-file &&
114         git add test-file &&
115         git commit -m "add file for rm test" &&
116         git rm test-file >rm-output &&
117         test $(grep "^rm " rm-output | wc -l) = 1 &&
118         rm -f test-file rm-output &&
119         git commit -m "remove file from rm test"
120 '
121
122 test_expect_success '"rm" command suppressed with --quiet' '
123         echo frotz >test-file &&
124         git add test-file &&
125         git commit -m "add file for rm --quiet test" &&
126         git rm --quiet test-file >rm-output &&
127         test_must_be_empty rm-output &&
128         rm -f test-file rm-output &&
129         git commit -m "remove file from rm --quiet test"
130 '
131
132 # Now, failure cases.
133 test_expect_success 'Re-add foo and baz' '
134         git add foo baz &&
135         git ls-files --error-unmatch foo baz
136 '
137
138 test_expect_success 'Modify foo -- rm should refuse' '
139         echo >>foo &&
140         test_must_fail git rm foo baz &&
141         test_path_is_file foo &&
142         test_path_is_file baz &&
143         git ls-files --error-unmatch foo baz
144 '
145
146 test_expect_success 'Modified foo -- rm -f should work' '
147         git rm -f foo baz &&
148         test_path_is_missing foo &&
149         test_path_is_missing baz &&
150         test_must_fail git ls-files --error-unmatch foo &&
151         test_must_fail git ls-files --error-unmatch bar
152 '
153
154 test_expect_success 'Re-add foo and baz for HEAD tests' '
155         echo frotz >foo &&
156         git checkout HEAD -- baz &&
157         git add foo baz &&
158         git ls-files --error-unmatch foo baz
159 '
160
161 test_expect_success 'foo is different in index from HEAD -- rm should refuse' '
162         test_must_fail git rm foo baz &&
163         test_path_is_file foo &&
164         test_path_is_file baz &&
165         git ls-files --error-unmatch foo baz
166 '
167
168 test_expect_success 'but with -f it should work.' '
169         git rm -f foo baz &&
170         test_path_is_missing foo &&
171         test_path_is_missing baz &&
172         test_must_fail git ls-files --error-unmatch foo &&
173         test_must_fail git ls-files --error-unmatch baz
174 '
175
176 test_expect_success 'refuse to remove cached empty file with modifications' '
177         >empty &&
178         git add empty &&
179         echo content >empty &&
180         test_must_fail git rm --cached empty
181 '
182
183 test_expect_success 'remove intent-to-add file without --force' '
184         echo content >intent-to-add &&
185         git add -N intent-to-add &&
186         git rm --cached intent-to-add
187 '
188
189 test_expect_success 'Recursive test setup' '
190         mkdir -p frotz &&
191         echo qfwfq >frotz/nitfol &&
192         git add frotz &&
193         git commit -m "subdir test"
194 '
195
196 test_expect_success 'Recursive without -r fails' '
197         test_must_fail git rm frotz &&
198         test_path_is_dir frotz &&
199         test_path_is_file frotz/nitfol
200 '
201
202 test_expect_success 'Recursive with -r but dirty' '
203         echo qfwfq >>frotz/nitfol &&
204         test_must_fail git rm -r frotz &&
205         test_path_is_dir frotz &&
206         test_path_is_file frotz/nitfol
207 '
208
209 test_expect_success 'Recursive with -r -f' '
210         git rm -f -r frotz &&
211         test_path_is_missing frotz/nitfol &&
212         test_path_is_missing frotz
213 '
214
215 test_expect_success 'Remove nonexistent file returns nonzero exit status' '
216         test_must_fail git rm nonexistent
217 '
218
219 test_expect_success 'Call "rm" from outside the work tree' '
220         mkdir repo &&
221         (
222                 cd repo &&
223                 git init &&
224                 echo something >somefile &&
225                 git add somefile &&
226                 git commit -m "add a file" &&
227                 (
228                         cd .. &&
229                         git --git-dir=repo/.git --work-tree=repo rm somefile
230                 ) &&
231                 test_must_fail git ls-files --error-unmatch somefile
232         )
233 '
234
235 test_expect_success 'refresh index before checking if it is up-to-date' '
236         git reset --hard &&
237         test-tool chmtime -86400 frotz/nitfol &&
238         git rm frotz/nitfol &&
239         test_path_is_missing frotz/nitfol
240 '
241
242 test_expect_success 'choking "git rm" should not let it die with cruft' '
243         test_oid_init &&
244         git reset -q --hard &&
245         test_when_finished "rm -f .git/index.lock && git reset -q --hard" &&
246         i=0 &&
247         hash=$(test_oid deadbeef) &&
248         while test $i -lt 12000
249         do
250                 echo "100644 $hash 0    some-file-$i"
251                 i=$(( $i + 1 ))
252         done | git update-index --index-info &&
253         git rm -n "some-file-*" | : &&
254         test_path_is_missing .git/index.lock
255 '
256
257 test_expect_success 'Resolving by removal is not a warning-worthy event' '
258         git reset -q --hard &&
259         test_when_finished "rm -f .git/index.lock msg && git reset -q --hard" &&
260         blob=$(echo blob | git hash-object -w --stdin) &&
261         for stage in 1 2 3
262         do
263                 echo "100644 $blob $stage       blob"
264         done | git update-index --index-info &&
265         git rm blob >msg 2>&1 &&
266         test_i18ngrep ! "needs merge" msg &&
267         test_must_fail git ls-files -s --error-unmatch blob
268 '
269
270 test_expect_success 'rm removes subdirectories recursively' '
271         mkdir -p dir/subdir/subsubdir &&
272         echo content >dir/subdir/subsubdir/file &&
273         git add dir/subdir/subsubdir/file &&
274         git rm -f dir/subdir/subsubdir/file &&
275         test_path_is_missing dir
276 '
277
278 cat >expect <<EOF
279 M  .gitmodules
280 D  submod
281 EOF
282
283 cat >expect.modified <<EOF
284  M submod
285 EOF
286
287 cat >expect.modified_inside <<EOF
288  m submod
289 EOF
290
291 cat >expect.modified_untracked <<EOF
292  ? submod
293 EOF
294
295 cat >expect.cached <<EOF
296 D  submod
297 EOF
298
299 cat >expect.both_deleted<<EOF
300 D  .gitmodules
301 D  submod
302 EOF
303
304 test_expect_success 'rm removes empty submodules from work tree' '
305         mkdir submod &&
306         git update-index --add --cacheinfo 160000 $(git rev-parse HEAD) submod &&
307         git config -f .gitmodules submodule.sub.url ./. &&
308         git config -f .gitmodules submodule.sub.path submod &&
309         git submodule init &&
310         git add .gitmodules &&
311         git commit -m "add submodule" &&
312         git rm submod &&
313         test_path_is_missing submod &&
314         git status -s -uno --ignore-submodules=none >actual &&
315         test_cmp expect actual &&
316         test_must_fail git config -f .gitmodules submodule.sub.url &&
317         test_must_fail git config -f .gitmodules submodule.sub.path
318 '
319
320 test_expect_success 'rm removes removed submodule from index and .gitmodules' '
321         git reset --hard &&
322         git submodule update &&
323         rm -rf submod &&
324         git rm submod &&
325         git status -s -uno --ignore-submodules=none >actual &&
326         test_cmp expect actual &&
327         test_must_fail git config -f .gitmodules submodule.sub.url &&
328         test_must_fail git config -f .gitmodules submodule.sub.path
329 '
330
331 test_expect_success 'rm removes work tree of unmodified submodules' '
332         git reset --hard &&
333         git submodule update &&
334         git rm submod &&
335         test_path_is_missing submod &&
336         git status -s -uno --ignore-submodules=none >actual &&
337         test_cmp expect actual &&
338         test_must_fail git config -f .gitmodules submodule.sub.url &&
339         test_must_fail git config -f .gitmodules submodule.sub.path
340 '
341
342 test_expect_success 'rm removes a submodule with a trailing /' '
343         git reset --hard &&
344         git submodule update &&
345         git rm submod/ &&
346         test_path_is_missing submod &&
347         git status -s -uno --ignore-submodules=none >actual &&
348         test_cmp expect actual
349 '
350
351 test_expect_success 'rm fails when given a file with a trailing /' '
352         test_must_fail git rm empty/
353 '
354
355 test_expect_success 'rm succeeds when given a directory with a trailing /' '
356         git rm -r frotz/
357 '
358
359 test_expect_success 'rm of a populated submodule with different HEAD fails unless forced' '
360         git reset --hard &&
361         git submodule update &&
362         git -C submod checkout HEAD^ &&
363         test_must_fail git rm submod &&
364         test_path_is_dir submod &&
365         test_path_is_file submod/.git &&
366         git status -s -uno --ignore-submodules=none >actual &&
367         test_cmp expect.modified actual &&
368         git rm -f submod &&
369         test_path_is_missing submod &&
370         git status -s -uno --ignore-submodules=none >actual &&
371         test_cmp expect actual &&
372         test_must_fail git config -f .gitmodules submodule.sub.url &&
373         test_must_fail git config -f .gitmodules submodule.sub.path
374 '
375
376 test_expect_success 'rm --cached leaves work tree of populated submodules and .gitmodules alone' '
377         git reset --hard &&
378         git submodule update &&
379         git rm --cached submod &&
380         test_path_is_dir submod &&
381         test_path_is_file submod/.git &&
382         git status -s -uno >actual &&
383         test_cmp expect.cached actual &&
384         git config -f .gitmodules submodule.sub.url &&
385         git config -f .gitmodules submodule.sub.path
386 '
387
388 test_expect_success 'rm --dry-run does not touch the submodule or .gitmodules' '
389         git reset --hard &&
390         git submodule update &&
391         git rm -n submod &&
392         test_path_is_file submod/.git &&
393         git diff-index --exit-code HEAD
394 '
395
396 test_expect_success 'rm does not complain when no .gitmodules file is found' '
397         git reset --hard &&
398         git submodule update &&
399         git rm .gitmodules &&
400         git rm submod >actual 2>actual.err &&
401         test_must_be_empty actual.err &&
402         test_path_is_missing submod &&
403         test_path_is_missing submod/.git &&
404         git status -s -uno >actual &&
405         test_cmp expect.both_deleted actual
406 '
407
408 test_expect_success 'rm will error out on a modified .gitmodules file unless staged' '
409         git reset --hard &&
410         git submodule update &&
411         git config -f .gitmodules foo.bar true &&
412         test_must_fail git rm submod >actual 2>actual.err &&
413         test_file_not_empty actual.err &&
414         test_path_is_dir submod &&
415         test_path_is_file submod/.git &&
416         git diff-files --quiet -- submod &&
417         git add .gitmodules &&
418         git rm submod >actual 2>actual.err &&
419         test_must_be_empty actual.err &&
420         test_path_is_missing submod &&
421         test_path_is_missing submod/.git &&
422         git status -s -uno >actual &&
423         test_cmp expect actual
424 '
425
426 test_expect_success 'rm issues a warning when section is not found in .gitmodules' '
427         git reset --hard &&
428         git submodule update &&
429         git config -f .gitmodules --remove-section submodule.sub &&
430         git add .gitmodules &&
431         echo "warning: Could not find section in .gitmodules where path=submod" >expect.err &&
432         git rm submod >actual 2>actual.err &&
433         test_i18ncmp expect.err actual.err &&
434         test_path_is_missing submod &&
435         test_path_is_missing submod/.git &&
436         git status -s -uno >actual &&
437         test_cmp expect actual
438 '
439
440 test_expect_success 'rm of a populated submodule with modifications fails unless forced' '
441         git reset --hard &&
442         git submodule update &&
443         echo X >submod/empty &&
444         test_must_fail git rm submod &&
445         test_path_is_dir submod &&
446         test_path_is_file submod/.git &&
447         git status -s -uno --ignore-submodules=none >actual &&
448         test_cmp expect.modified_inside actual &&
449         git rm -f submod &&
450         test_path_is_missing submod &&
451         git status -s -uno --ignore-submodules=none >actual &&
452         test_cmp expect actual
453 '
454
455 test_expect_success 'rm of a populated submodule with untracked files fails unless forced' '
456         git reset --hard &&
457         git submodule update &&
458         echo X >submod/untracked &&
459         test_must_fail git rm submod &&
460         test_path_is_dir submod &&
461         test_path_is_file submod/.git &&
462         git status -s -uno --ignore-submodules=none >actual &&
463         test_cmp expect.modified_untracked actual &&
464         git rm -f submod &&
465         test_path_is_missing submod &&
466         git status -s -uno --ignore-submodules=none >actual &&
467         test_cmp expect actual
468 '
469
470 test_expect_success 'setup submodule conflict' '
471         git reset --hard &&
472         git submodule update &&
473         git checkout -b branch1 &&
474         echo 1 >nitfol &&
475         git add nitfol &&
476         git commit -m "added nitfol 1" &&
477         git checkout -b branch2 master &&
478         echo 2 >nitfol &&
479         git add nitfol &&
480         git commit -m "added nitfol 2" &&
481         git checkout -b conflict1 master &&
482         git -C submod fetch &&
483         git -C submod checkout branch1 &&
484         git add submod &&
485         git commit -m "submod 1" &&
486         git checkout -b conflict2 master &&
487         git -C submod checkout branch2 &&
488         git add submod &&
489         git commit -m "submod 2"
490 '
491
492 cat >expect.conflict <<EOF
493 UU submod
494 EOF
495
496 test_expect_success 'rm removes work tree of unmodified conflicted submodule' '
497         git checkout conflict1 &&
498         git reset --hard &&
499         git submodule update &&
500         test_must_fail git merge conflict2 &&
501         git rm submod &&
502         test_path_is_missing submod &&
503         git status -s -uno --ignore-submodules=none >actual &&
504         test_cmp expect actual
505 '
506
507 test_expect_success 'rm of a conflicted populated submodule with different HEAD fails unless forced' '
508         git checkout conflict1 &&
509         git reset --hard &&
510         git submodule update &&
511         git -C submod checkout HEAD^ &&
512         test_must_fail git merge conflict2 &&
513         test_must_fail git rm submod &&
514         test_path_is_dir submod &&
515         test_path_is_file submod/.git &&
516         git status -s -uno --ignore-submodules=none >actual &&
517         test_cmp expect.conflict actual &&
518         git rm -f submod &&
519         test_path_is_missing submod &&
520         git status -s -uno --ignore-submodules=none >actual &&
521         test_cmp expect actual &&
522         test_must_fail git config -f .gitmodules submodule.sub.url &&
523         test_must_fail git config -f .gitmodules submodule.sub.path
524 '
525
526 test_expect_success 'rm of a conflicted populated submodule with modifications fails unless forced' '
527         git checkout conflict1 &&
528         git reset --hard &&
529         git submodule update &&
530         echo X >submod/empty &&
531         test_must_fail git merge conflict2 &&
532         test_must_fail git rm submod &&
533         test_path_is_dir submod &&
534         test_path_is_file submod/.git &&
535         git status -s -uno --ignore-submodules=none >actual &&
536         test_cmp expect.conflict actual &&
537         git rm -f submod &&
538         test_path_is_missing submod &&
539         git status -s -uno --ignore-submodules=none >actual &&
540         test_cmp expect actual &&
541         test_must_fail git config -f .gitmodules submodule.sub.url &&
542         test_must_fail git config -f .gitmodules submodule.sub.path
543 '
544
545 test_expect_success 'rm of a conflicted populated submodule with untracked files fails unless forced' '
546         git checkout conflict1 &&
547         git reset --hard &&
548         git submodule update &&
549         echo X >submod/untracked &&
550         test_must_fail git merge conflict2 &&
551         test_must_fail git rm submod &&
552         test_path_is_dir submod &&
553         test_path_is_file submod/.git &&
554         git status -s -uno --ignore-submodules=none >actual &&
555         test_cmp expect.conflict actual &&
556         git rm -f submod &&
557         test_path_is_missing submod &&
558         git status -s -uno --ignore-submodules=none >actual &&
559         test_cmp expect actual
560 '
561
562 test_expect_success 'rm of a conflicted populated submodule with a .git directory fails even when forced' '
563         git checkout conflict1 &&
564         git reset --hard &&
565         git submodule update &&
566         (
567                 cd submod &&
568                 rm .git &&
569                 cp -R ../.git/modules/sub .git &&
570                 GIT_WORK_TREE=. git config --unset core.worktree
571         ) &&
572         test_must_fail git merge conflict2 &&
573         test_must_fail git rm submod &&
574         test_path_is_dir submod &&
575         test_path_is_dir submod/.git &&
576         git status -s -uno --ignore-submodules=none >actual &&
577         test_cmp expect.conflict actual &&
578         test_must_fail git rm -f submod &&
579         test_path_is_dir submod &&
580         test_path_is_dir submod/.git &&
581         git status -s -uno --ignore-submodules=none >actual &&
582         test_cmp expect.conflict actual &&
583         git merge --abort &&
584         rm -rf submod
585 '
586
587 test_expect_success 'rm of a conflicted unpopulated submodule succeeds' '
588         git checkout conflict1 &&
589         git reset --hard &&
590         test_must_fail git merge conflict2 &&
591         git rm submod &&
592         test_path_is_missing submod &&
593         git status -s -uno --ignore-submodules=none >actual &&
594         test_cmp expect actual
595 '
596
597 test_expect_success 'rm of a populated submodule with a .git directory migrates git dir' '
598         git checkout -f master &&
599         git reset --hard &&
600         git submodule update &&
601         (
602                 cd submod &&
603                 rm .git &&
604                 cp -R ../.git/modules/sub .git &&
605                 GIT_WORK_TREE=. git config --unset core.worktree &&
606                 rm -r ../.git/modules/sub
607         ) &&
608         git rm submod 2>output.err &&
609         test_path_is_missing submod &&
610         test_path_is_missing submod/.git &&
611         git status -s -uno --ignore-submodules=none >actual &&
612         test_file_not_empty actual &&
613         test_i18ngrep Migrating output.err
614 '
615
616 cat >expect.deepmodified <<EOF
617  M submod/subsubmod
618 EOF
619
620 test_expect_success 'setup subsubmodule' '
621         git reset --hard &&
622         git submodule update &&
623         (
624                 cd submod &&
625                 git update-index --add --cacheinfo 160000 $(git rev-parse HEAD) subsubmod &&
626                 git config -f .gitmodules submodule.sub.url ../. &&
627                 git config -f .gitmodules submodule.sub.path subsubmod &&
628                 git submodule init &&
629                 git add .gitmodules &&
630                 git commit -m "add subsubmodule" &&
631                 git submodule update subsubmod
632         ) &&
633         git commit -a -m "added deep submodule"
634 '
635
636 test_expect_success 'rm recursively removes work tree of unmodified submodules' '
637         git rm submod &&
638         test_path_is_missing submod &&
639         git status -s -uno --ignore-submodules=none >actual &&
640         test_cmp expect actual
641 '
642
643 test_expect_success 'rm of a populated nested submodule with different nested HEAD fails unless forced' '
644         git reset --hard &&
645         git submodule update --recursive &&
646         git -C submod/subsubmod checkout HEAD^ &&
647         test_must_fail git rm submod &&
648         test_path_is_dir submod &&
649         test_path_is_file submod/.git &&
650         git status -s -uno --ignore-submodules=none >actual &&
651         test_cmp expect.modified_inside actual &&
652         git rm -f submod &&
653         test_path_is_missing submod &&
654         git status -s -uno --ignore-submodules=none >actual &&
655         test_cmp expect actual
656 '
657
658 test_expect_success 'rm of a populated nested submodule with nested modifications fails unless forced' '
659         git reset --hard &&
660         git submodule update --recursive &&
661         echo X >submod/subsubmod/empty &&
662         test_must_fail git rm submod &&
663         test_path_is_dir submod &&
664         test_path_is_file submod/.git &&
665         git status -s -uno --ignore-submodules=none >actual &&
666         test_cmp expect.modified_inside actual &&
667         git rm -f submod &&
668         test_path_is_missing submod &&
669         git status -s -uno --ignore-submodules=none >actual &&
670         test_cmp expect actual
671 '
672
673 test_expect_success 'rm of a populated nested submodule with nested untracked files fails unless forced' '
674         git reset --hard &&
675         git submodule update --recursive &&
676         echo X >submod/subsubmod/untracked &&
677         test_must_fail git rm submod &&
678         test_path_is_dir submod &&
679         test_path_is_file submod/.git &&
680         git status -s -uno --ignore-submodules=none >actual &&
681         test_cmp expect.modified_untracked actual &&
682         git rm -f submod &&
683         test_path_is_missing submod &&
684         git status -s -uno --ignore-submodules=none >actual &&
685         test_cmp expect actual
686 '
687
688 test_expect_success "rm absorbs submodule's nested .git directory" '
689         git reset --hard &&
690         git submodule update --recursive &&
691         (
692                 cd submod/subsubmod &&
693                 rm .git &&
694                 mv ../../.git/modules/sub/modules/sub .git &&
695                 GIT_WORK_TREE=. git config --unset core.worktree
696         ) &&
697         git rm submod 2>output.err &&
698         test_path_is_missing submod &&
699         test_path_is_missing submod/subsubmod/.git &&
700         git status -s -uno --ignore-submodules=none >actual &&
701         test_file_not_empty actual &&
702         test_i18ngrep Migrating output.err
703 '
704
705 test_expect_success 'checking out a commit after submodule removal needs manual updates' '
706         git commit -m "submodule removal" submod .gitmodules &&
707         git checkout HEAD^ &&
708         git submodule update &&
709         git checkout -q HEAD^ &&
710         git checkout -q master 2>actual &&
711         test_i18ngrep "^warning: unable to rmdir '\''submod'\'':" actual &&
712         git status -s submod >actual &&
713         echo "?? submod/" >expected &&
714         test_cmp expected actual &&
715         rm -rf submod &&
716         git status -s -uno --ignore-submodules=none >actual &&
717         test_must_be_empty actual
718 '
719
720 test_expect_success 'rm of d/f when d has become a non-directory' '
721         rm -rf d &&
722         mkdir d &&
723         >d/f &&
724         git add d &&
725         rm -rf d &&
726         >d &&
727         git rm d/f &&
728         test_must_fail git rev-parse --verify :d/f &&
729         test_path_is_file d
730 '
731
732 test_expect_success SYMLINKS 'rm of d/f when d has become a dangling symlink' '
733         rm -rf d &&
734         mkdir d &&
735         >d/f &&
736         git add d &&
737         rm -rf d &&
738         ln -s nonexistent d &&
739         git rm d/f &&
740         test_must_fail git rev-parse --verify :d/f &&
741         test -h d &&
742         test_path_is_missing d
743 '
744
745 test_expect_success 'rm of file when it has become a directory' '
746         rm -rf d &&
747         >d &&
748         git add d &&
749         rm -f d &&
750         mkdir d &&
751         >d/f &&
752         test_must_fail git rm d &&
753         git rev-parse --verify :d &&
754         test_path_is_file d/f
755 '
756
757 test_expect_success SYMLINKS 'rm across a symlinked leading path (no index)' '
758         rm -rf d e &&
759         mkdir e &&
760         echo content >e/f &&
761         ln -s e d &&
762         git add -A e d &&
763         git commit -m "symlink d to e, e/f exists" &&
764         test_must_fail git rm d/f &&
765         git rev-parse --verify :d &&
766         git rev-parse --verify :e/f &&
767         test -h d &&
768         test_path_is_file e/f
769 '
770
771 test_expect_failure SYMLINKS 'rm across a symlinked leading path (w/ index)' '
772         rm -rf d e &&
773         mkdir d &&
774         echo content >d/f &&
775         git add -A e d &&
776         git commit -m "d/f exists" &&
777         mv d e &&
778         ln -s e d &&
779         test_must_fail git rm d/f &&
780         git rev-parse --verify :d/f &&
781         test -h d &&
782         test_path_is_file e/f
783 '
784
785 test_expect_success 'setup for testing rm messages' '
786         >bar.txt &&
787         >foo.txt &&
788         git add bar.txt foo.txt
789 '
790
791 test_expect_success 'rm files with different staged content' '
792         cat >expect <<-\EOF &&
793         error: the following files have staged content different from both the
794         file and the HEAD:
795             bar.txt
796             foo.txt
797         (use -f to force removal)
798         EOF
799         echo content1 >foo.txt &&
800         echo content1 >bar.txt &&
801         test_must_fail git rm foo.txt bar.txt 2>actual &&
802         test_i18ncmp expect actual
803 '
804
805 test_expect_success 'rm files with different staged content without hints' '
806         cat >expect <<-\EOF &&
807         error: the following files have staged content different from both the
808         file and the HEAD:
809             bar.txt
810             foo.txt
811         EOF
812         echo content2 >foo.txt &&
813         echo content2 >bar.txt &&
814         test_must_fail git -c advice.rmhints=false rm foo.txt bar.txt 2>actual &&
815         test_i18ncmp expect actual
816 '
817
818 test_expect_success 'rm file with local modification' '
819         cat >expect <<-\EOF &&
820         error: the following file has local modifications:
821             foo.txt
822         (use --cached to keep the file, or -f to force removal)
823         EOF
824         git commit -m "testing rm 3" &&
825         echo content3 >foo.txt &&
826         test_must_fail git rm foo.txt 2>actual &&
827         test_i18ncmp expect actual
828 '
829
830 test_expect_success 'rm file with local modification without hints' '
831         cat >expect <<-\EOF &&
832         error: the following file has local modifications:
833             bar.txt
834         EOF
835         echo content4 >bar.txt &&
836         test_must_fail git -c advice.rmhints=false rm bar.txt 2>actual &&
837         test_i18ncmp expect actual
838 '
839
840 test_expect_success 'rm file with changes in the index' '
841         cat >expect <<-\EOF &&
842         error: the following file has changes staged in the index:
843             foo.txt
844         (use --cached to keep the file, or -f to force removal)
845         EOF
846         git reset --hard &&
847         echo content5 >foo.txt &&
848         git add foo.txt &&
849         test_must_fail git rm foo.txt 2>actual &&
850         test_i18ncmp expect actual
851 '
852
853 test_expect_success 'rm file with changes in the index without hints' '
854         cat >expect <<-\EOF &&
855         error: the following file has changes staged in the index:
856             foo.txt
857         EOF
858         test_must_fail git -c advice.rmhints=false rm foo.txt 2>actual &&
859         test_i18ncmp expect actual
860 '
861
862 test_expect_success 'rm files with two different errors' '
863         cat >expect <<-\EOF &&
864         error: the following file has staged content different from both the
865         file and the HEAD:
866             foo1.txt
867         (use -f to force removal)
868         error: the following file has changes staged in the index:
869             bar1.txt
870         (use --cached to keep the file, or -f to force removal)
871         EOF
872         echo content >foo1.txt &&
873         git add foo1.txt &&
874         echo content6 >foo1.txt &&
875         echo content6 >bar1.txt &&
876         git add bar1.txt &&
877         test_must_fail git rm bar1.txt foo1.txt 2>actual &&
878         test_i18ncmp expect actual
879 '
880
881 test_expect_success 'rm empty string should fail' '
882         test_must_fail git rm -rf ""
883 '
884
885 test_done