blob: f6d8d7d03d7ca42b566c2b177ee57345e09b7107 [file] [log] [blame]
Elijah Newren8a0d52d2021-12-09 05:08:25 +00001#!/bin/sh
2
3test_description='Test handling of the current working directory becoming empty'
4
5. ./test-lib.sh
6
7test_expect_success setup '
8 test_commit init &&
9
10 git branch fd_conflict &&
11
12 mkdir -p foo/bar &&
13 test_commit foo/bar/baz &&
14
15 git revert HEAD &&
16 git tag reverted &&
17
18 git checkout fd_conflict &&
19 mkdir dirORfile &&
20 test_commit dirORfile/foo &&
21
22 git rm -r dirORfile &&
23 echo not-a-directory >dirORfile &&
24 git add dirORfile &&
25 git commit -m dirORfile &&
26
27 git switch -c df_conflict HEAD~1 &&
28 test_commit random_file &&
29
30 git switch -c undo_fd_conflict fd_conflict &&
31 git revert HEAD
32'
33
34test_incidental_dir_removal () {
Elijah Newren8a0d52d2021-12-09 05:08:25 +000035 test_when_finished "git reset --hard" &&
36
37 git checkout foo/bar/baz^{commit} &&
38 test_path_is_dir foo/bar &&
39
40 (
41 cd foo &&
42 "$@" &&
43
Elijah Newren324b1702021-12-09 05:08:35 +000044 # Make sure foo still exists, and commands needing it work
45 test-tool getcwd &&
46 git status --porcelain
Elijah Newren8a0d52d2021-12-09 05:08:25 +000047 ) &&
48 test_path_is_missing foo/bar/baz &&
49 test_path_is_missing foo/bar &&
50
Elijah Newren324b1702021-12-09 05:08:35 +000051 test_path_is_dir foo
Elijah Newren8a0d52d2021-12-09 05:08:25 +000052}
53
54test_required_dir_removal () {
Elijah Newren8a0d52d2021-12-09 05:08:25 +000055 git checkout df_conflict^{commit} &&
56 test_when_finished "git clean -fdx" &&
57
58 (
59 cd dirORfile &&
60
Elijah Newren324b1702021-12-09 05:08:35 +000061 # Ensure command refuses to run
62 test_must_fail "$@" 2>../error &&
63 grep "Refusing to remove.*current working directory" ../error &&
Elijah Newren8a0d52d2021-12-09 05:08:25 +000064
Elijah Newren324b1702021-12-09 05:08:35 +000065 # ...and that the index and working tree are left clean
66 git diff --exit-code HEAD &&
Elijah Newren8a0d52d2021-12-09 05:08:25 +000067
Elijah Newren324b1702021-12-09 05:08:35 +000068 # Ensure that getcwd and git status do not error out (which
69 # they might if the current working directory had been removed)
70 test-tool getcwd &&
71 git status --porcelain
Elijah Newren8a0d52d2021-12-09 05:08:25 +000072 ) &&
73
Elijah Newren324b1702021-12-09 05:08:35 +000074 test_path_is_dir dirORfile
Elijah Newren8a0d52d2021-12-09 05:08:25 +000075}
76
77test_expect_success 'checkout does not clean cwd incidentally' '
Elijah Newren324b1702021-12-09 05:08:35 +000078 test_incidental_dir_removal git checkout init
Elijah Newren8a0d52d2021-12-09 05:08:25 +000079'
80
81test_expect_success 'checkout fails if cwd needs to be removed' '
Elijah Newren324b1702021-12-09 05:08:35 +000082 test_required_dir_removal git checkout fd_conflict
Elijah Newren8a0d52d2021-12-09 05:08:25 +000083'
84
85test_expect_success 'reset --hard does not clean cwd incidentally' '
Elijah Newren324b1702021-12-09 05:08:35 +000086 test_incidental_dir_removal git reset --hard init
Elijah Newren8a0d52d2021-12-09 05:08:25 +000087'
88
89test_expect_success 'reset --hard fails if cwd needs to be removed' '
Elijah Newren324b1702021-12-09 05:08:35 +000090 test_required_dir_removal git reset --hard fd_conflict
Elijah Newren8a0d52d2021-12-09 05:08:25 +000091'
92
93test_expect_success 'merge does not clean cwd incidentally' '
Elijah Newren324b1702021-12-09 05:08:35 +000094 test_incidental_dir_removal git merge reverted
Elijah Newren8a0d52d2021-12-09 05:08:25 +000095'
96
97# This file uses some simple merges where
98# Base: 'dirORfile/' exists
99# Side1: random other file changed
100# Side2: 'dirORfile/' removed, 'dirORfile' added
101# this should resolve cleanly, but merge-recursive throws merge conflicts
102# because it's dumb. Add a special test for checking merge-recursive (and
103# merge-ort), then after this just hard require ort for all remaining tests.
104#
105test_expect_success 'merge fails if cwd needs to be removed; recursive friendly' '
106 git checkout foo/bar/baz &&
107 test_when_finished "git clean -fdx" &&
108
109 mkdir dirORfile &&
110 (
111 cd dirORfile &&
112
Elijah Newrenb817e542021-12-09 05:08:27 +0000113 test_must_fail git merge fd_conflict 2>../error
Elijah Newren8a0d52d2021-12-09 05:08:25 +0000114 ) &&
115
Elijah Newrenb817e542021-12-09 05:08:27 +0000116 test_path_is_dir dirORfile &&
117 grep "Refusing to remove the current working directory" error
Elijah Newren8a0d52d2021-12-09 05:08:25 +0000118'
119
120GIT_TEST_MERGE_ALGORITHM=ort
121
122test_expect_success 'merge fails if cwd needs to be removed' '
Elijah Newren324b1702021-12-09 05:08:35 +0000123 test_required_dir_removal git merge fd_conflict
Elijah Newren8a0d52d2021-12-09 05:08:25 +0000124'
125
126test_expect_success 'cherry-pick does not clean cwd incidentally' '
Elijah Newren324b1702021-12-09 05:08:35 +0000127 test_incidental_dir_removal git cherry-pick reverted
Elijah Newren8a0d52d2021-12-09 05:08:25 +0000128'
129
130test_expect_success 'cherry-pick fails if cwd needs to be removed' '
Elijah Newren324b1702021-12-09 05:08:35 +0000131 test_required_dir_removal git cherry-pick fd_conflict
Elijah Newren8a0d52d2021-12-09 05:08:25 +0000132'
133
134test_expect_success 'rebase does not clean cwd incidentally' '
Elijah Newren324b1702021-12-09 05:08:35 +0000135 test_incidental_dir_removal git rebase reverted
Elijah Newren8a0d52d2021-12-09 05:08:25 +0000136'
137
138test_expect_success 'rebase fails if cwd needs to be removed' '
Elijah Newren324b1702021-12-09 05:08:35 +0000139 test_required_dir_removal git rebase fd_conflict
Elijah Newren8a0d52d2021-12-09 05:08:25 +0000140'
141
142test_expect_success 'revert does not clean cwd incidentally' '
Elijah Newren324b1702021-12-09 05:08:35 +0000143 test_incidental_dir_removal git revert HEAD
Elijah Newren8a0d52d2021-12-09 05:08:25 +0000144'
145
146test_expect_success 'revert fails if cwd needs to be removed' '
Elijah Newren324b1702021-12-09 05:08:35 +0000147 test_required_dir_removal git revert undo_fd_conflict
Elijah Newren8a0d52d2021-12-09 05:08:25 +0000148'
149
150test_expect_success 'rm does not clean cwd incidentally' '
Elijah Newren324b1702021-12-09 05:08:35 +0000151 test_incidental_dir_removal git rm bar/baz.t
Elijah Newren8a0d52d2021-12-09 05:08:25 +0000152'
153
154test_expect_success 'apply does not remove cwd incidentally' '
155 git diff HEAD HEAD~1 >patch &&
Elijah Newren324b1702021-12-09 05:08:35 +0000156 test_incidental_dir_removal git apply ../patch
Elijah Newren8a0d52d2021-12-09 05:08:25 +0000157'
158
159test_incidental_untracked_dir_removal () {
Elijah Newren8a0d52d2021-12-09 05:08:25 +0000160 test_when_finished "git reset --hard" &&
161
162 git checkout foo/bar/baz^{commit} &&
163 mkdir -p untracked &&
164 mkdir empty
165 >untracked/random &&
166
167 (
168 cd untracked &&
169 "$@" &&
170
Elijah Newren324b1702021-12-09 05:08:35 +0000171 # Make sure untracked still exists, and commands needing it work
172 test-tool getcwd &&
173 git status --porcelain
Elijah Newren8a0d52d2021-12-09 05:08:25 +0000174 ) &&
175 test_path_is_missing empty &&
176 test_path_is_missing untracked/random &&
177
Elijah Newren324b1702021-12-09 05:08:35 +0000178 test_path_is_dir untracked
Elijah Newren8a0d52d2021-12-09 05:08:25 +0000179}
180
181test_expect_success 'clean does not remove cwd incidentally' '
Elijah Newren324b1702021-12-09 05:08:35 +0000182 test_incidental_untracked_dir_removal \
Elijah Newrenc65744e2021-12-09 05:08:30 +0000183 git -C .. clean -fd -e warnings . >warnings &&
184 grep "Refusing to remove current working directory" warnings
Elijah Newren8a0d52d2021-12-09 05:08:25 +0000185'
186
187test_expect_success 'stash does not remove cwd incidentally' '
Elijah Newren324b1702021-12-09 05:08:35 +0000188 test_incidental_untracked_dir_removal \
Elijah Newren8a0d52d2021-12-09 05:08:25 +0000189 git stash --include-untracked
190'
191
192test_expect_success '`rm -rf dir` only removes a subset of dir' '
193 test_when_finished "rm -rf a/" &&
194
195 mkdir -p a/b/c &&
196 >a/b/c/untracked &&
197 >a/b/c/tracked &&
198 git add a/b/c/tracked &&
199
200 (
201 cd a/b &&
202 git rm -rf ../b
203 ) &&
204
205 test_path_is_dir a/b &&
206 test_path_is_missing a/b/c/tracked &&
207 test_path_is_file a/b/c/untracked
208'
209
210test_expect_success '`rm -rf dir` even with only tracked files will remove something else' '
211 test_when_finished "rm -rf a/" &&
212
213 mkdir -p a/b/c &&
214 >a/b/c/tracked &&
215 git add a/b/c/tracked &&
216
217 (
218 cd a/b &&
219 git rm -rf ../b
220 ) &&
221
222 test_path_is_missing a/b/c/tracked &&
Elijah Newren63bbe8b2021-12-09 05:08:33 +0000223 test_path_is_missing a/b/c &&
224 test_path_is_dir a/b
Elijah Newren8a0d52d2021-12-09 05:08:25 +0000225'
226
227test_expect_success 'git version continues working from a deleted dir' '
228 mkdir tmp &&
229 (
230 cd tmp &&
231 rm -rf ../tmp &&
232 git version
233 )
234'
235
236test_submodule_removal () {
237 path_status=$1 &&
238 shift &&
239
240 test_status=
241 test "$path_status" = dir && test_status=test_must_fail
242
Elijah Newren8a0d52d2021-12-09 05:08:25 +0000243 test_when_finished "git reset --hard HEAD~1" &&
244 test_when_finished "rm -rf .git/modules/my_submodule" &&
245
246 git checkout foo/bar/baz &&
247
248 git init my_submodule &&
249 touch my_submodule/file &&
250 git -C my_submodule add file &&
251 git -C my_submodule commit -m "initial commit" &&
252 git submodule add ./my_submodule &&
253 git commit -m "Add the submodule" &&
254
255 (
256 cd my_submodule &&
257 $test_status "$@"
258 ) &&
259
260 test_path_is_${path_status} my_submodule
261}
262
263test_expect_success 'rm -r with -C leaves submodule if cwd inside' '
264 test_submodule_removal dir git -C .. rm -r my_submodule/
265'
266
267test_expect_success 'rm -r leaves submodule if cwd inside' '
268 test_submodule_removal dir \
269 git --git-dir=../.git --work-tree=.. rm -r ../my_submodule/
270'
271
272test_expect_success 'rm -rf removes submodule even if cwd inside' '
273 test_submodule_removal missing \
274 git --git-dir=../.git --work-tree=.. rm -rf ../my_submodule/
275'
276
277test_done