symlinks: do not include startup_info->original_cwd in dir removal
[git/debian.git] / t / t2501-cwd-empty.sh
blobe4502d24d57f7726d5dc75fbb30f6e190c7fb41e
1 #!/bin/sh
3 test_description='Test handling of the current working directory becoming empty'
5 . ./test-lib.sh
7 test_expect_success setup '
8 test_commit init &&
10 git branch fd_conflict &&
12 mkdir -p foo/bar &&
13 test_commit foo/bar/baz &&
15 git revert HEAD &&
16 git tag reverted &&
18 git checkout fd_conflict &&
19 mkdir dirORfile &&
20 test_commit dirORfile/foo &&
22 git rm -r dirORfile &&
23 echo not-a-directory >dirORfile &&
24 git add dirORfile &&
25 git commit -m dirORfile &&
27 git switch -c df_conflict HEAD~1 &&
28 test_commit random_file &&
30 git switch -c undo_fd_conflict fd_conflict &&
31 git revert HEAD
34 test_incidental_dir_removal () {
35 works=$1 &&
36 shift &&
38 test_when_finished "git reset --hard" &&
40 git checkout foo/bar/baz^{commit} &&
41 test_path_is_dir foo/bar &&
44 cd foo &&
45 "$@" &&
47 # Although we want pwd & git status to pass, test for existing
48 # rather than desired behavior.
49 if test "$works" = "success"
50 then
51 test-tool getcwd &&
52 git status --porcelain
53 else
54 ! test-tool getcwd &&
55 test_might_fail git status --porcelain
57 ) &&
58 test_path_is_missing foo/bar/baz &&
59 test_path_is_missing foo/bar &&
61 # Although we want dir to be present, test for existing rather
62 # than desired behavior.
63 if test "$works" = "success"
64 then
65 test_path_is_dir foo
66 else
67 test_path_is_missing foo
71 test_required_dir_removal () {
72 works=$1 &&
73 shift &&
75 git checkout df_conflict^{commit} &&
76 test_when_finished "git clean -fdx" &&
79 cd dirORfile &&
81 # We'd like for the command to fail (much as it would if there
82 # was an untracked file there), and for the index and worktree
83 # to be left clean with pwd and git status working afterwards.
84 # But test for existing rather than desired behavior.
85 if test "$works" = "success"
86 then
87 test_must_fail "$@" 2>../error &&
88 grep "Refusing to remove.*current working directory" ../error &&
90 git diff --exit-code HEAD &&
92 test-tool getcwd &&
93 git status --porcelain
94 else
95 "$@" &&
96 ! test-tool getcwd &&
97 test_might_fail git status --porcelain
99 ) &&
101 # Although we want dirORfile to be present, test for existing rather
102 # than desired behavior.
103 if test "$works" = "success"
104 then
105 test_path_is_dir dirORfile
106 else
107 test_path_is_file dirORfile
111 test_expect_success 'checkout does not clean cwd incidentally' '
112 test_incidental_dir_removal success git checkout init
115 test_expect_success 'checkout fails if cwd needs to be removed' '
116 test_required_dir_removal success git checkout fd_conflict
119 test_expect_success 'reset --hard does not clean cwd incidentally' '
120 test_incidental_dir_removal success git reset --hard init
123 test_expect_success 'reset --hard fails if cwd needs to be removed' '
124 test_required_dir_removal success git reset --hard fd_conflict
127 test_expect_success 'merge does not clean cwd incidentally' '
128 test_incidental_dir_removal success git merge reverted
131 # This file uses some simple merges where
132 # Base: 'dirORfile/' exists
133 # Side1: random other file changed
134 # Side2: 'dirORfile/' removed, 'dirORfile' added
135 # this should resolve cleanly, but merge-recursive throws merge conflicts
136 # because it's dumb. Add a special test for checking merge-recursive (and
137 # merge-ort), then after this just hard require ort for all remaining tests.
139 test_expect_success 'merge fails if cwd needs to be removed; recursive friendly' '
140 git checkout foo/bar/baz &&
141 test_when_finished "git clean -fdx" &&
143 mkdir dirORfile &&
145 cd dirORfile &&
147 test_must_fail git merge fd_conflict 2>../error
148 ) &&
150 test_path_is_dir dirORfile &&
151 grep "Refusing to remove the current working directory" error
154 GIT_TEST_MERGE_ALGORITHM=ort
156 test_expect_success 'merge fails if cwd needs to be removed' '
157 test_required_dir_removal success git merge fd_conflict
160 test_expect_success 'cherry-pick does not clean cwd incidentally' '
161 test_incidental_dir_removal success git cherry-pick reverted
164 test_expect_success 'cherry-pick fails if cwd needs to be removed' '
165 test_required_dir_removal success git cherry-pick fd_conflict
168 test_expect_success 'rebase does not clean cwd incidentally' '
169 test_incidental_dir_removal failure git rebase reverted
172 test_expect_success 'rebase fails if cwd needs to be removed' '
173 test_required_dir_removal failure git rebase fd_conflict
176 test_expect_success 'revert does not clean cwd incidentally' '
177 test_incidental_dir_removal success git revert HEAD
180 test_expect_success 'revert fails if cwd needs to be removed' '
181 test_required_dir_removal success git revert undo_fd_conflict
184 test_expect_success 'rm does not clean cwd incidentally' '
185 test_incidental_dir_removal failure git rm bar/baz.t
188 test_expect_success 'apply does not remove cwd incidentally' '
189 git diff HEAD HEAD~1 >patch &&
190 test_incidental_dir_removal failure git apply ../patch
193 test_incidental_untracked_dir_removal () {
194 works=$1 &&
195 shift &&
197 test_when_finished "git reset --hard" &&
199 git checkout foo/bar/baz^{commit} &&
200 mkdir -p untracked &&
201 mkdir empty
202 >untracked/random &&
205 cd untracked &&
206 "$@" &&
208 # Although we want pwd & git status to pass, test for existing
209 # rather than desired behavior.
210 if test "$works" = "success"
211 then
212 test-tool getcwd &&
213 git status --porcelain
214 else
215 ! test-tool getcwd &&
216 test_might_fail git status --porcelain
218 ) &&
219 test_path_is_missing empty &&
220 test_path_is_missing untracked/random &&
222 # Although we want dir to be present, test for existing rather
223 # than desired behavior.
224 if test "$works" = "success"
225 then
226 test_path_is_dir untracked
227 else
228 test_path_is_missing untracked
232 test_expect_success 'clean does not remove cwd incidentally' '
233 test_incidental_untracked_dir_removal failure \
234 git -C .. clean -fd -e warnings . >warnings
237 test_expect_success 'stash does not remove cwd incidentally' '
238 test_incidental_untracked_dir_removal failure \
239 git stash --include-untracked
242 test_expect_success '`rm -rf dir` only removes a subset of dir' '
243 test_when_finished "rm -rf a/" &&
245 mkdir -p a/b/c &&
246 >a/b/c/untracked &&
247 >a/b/c/tracked &&
248 git add a/b/c/tracked &&
251 cd a/b &&
252 git rm -rf ../b
253 ) &&
255 test_path_is_dir a/b &&
256 test_path_is_missing a/b/c/tracked &&
257 test_path_is_file a/b/c/untracked
260 test_expect_success '`rm -rf dir` even with only tracked files will remove something else' '
261 test_when_finished "rm -rf a/" &&
263 mkdir -p a/b/c &&
264 >a/b/c/tracked &&
265 git add a/b/c/tracked &&
268 cd a/b &&
269 git rm -rf ../b
270 ) &&
272 test_path_is_missing a/b/c/tracked &&
273 ## We would prefer if a/b was still present, though empty, since it
274 ## was the current working directory
275 #test_path_is_dir a/b
276 ## But the current behavior is that it not only deletes the directory
277 ## a/b as requested, but also goes and deletes a
278 test_path_is_missing a
281 test_expect_success 'git version continues working from a deleted dir' '
282 mkdir tmp &&
284 cd tmp &&
285 rm -rf ../tmp &&
286 git version
290 test_submodule_removal () {
291 path_status=$1 &&
292 shift &&
294 test_status=
295 test "$path_status" = dir && test_status=test_must_fail
297 # Actually, while path_status=dir && test_status=test_must_fail
298 # reflect our desired behavior, current behavior is:
299 path_status=missing
300 test_status=
302 test_when_finished "git reset --hard HEAD~1" &&
303 test_when_finished "rm -rf .git/modules/my_submodule" &&
305 git checkout foo/bar/baz &&
307 git init my_submodule &&
308 touch my_submodule/file &&
309 git -C my_submodule add file &&
310 git -C my_submodule commit -m "initial commit" &&
311 git submodule add ./my_submodule &&
312 git commit -m "Add the submodule" &&
315 cd my_submodule &&
316 $test_status "$@"
317 ) &&
319 test_path_is_${path_status} my_submodule
322 test_expect_success 'rm -r with -C leaves submodule if cwd inside' '
323 test_submodule_removal dir git -C .. rm -r my_submodule/
326 test_expect_success 'rm -r leaves submodule if cwd inside' '
327 test_submodule_removal dir \
328 git --git-dir=../.git --work-tree=.. rm -r ../my_submodule/
331 test_expect_success 'rm -rf removes submodule even if cwd inside' '
332 test_submodule_removal missing \
333 git --git-dir=../.git --work-tree=.. rm -rf ../my_submodule/
336 test_done