Git fork
1#!/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 () {
35 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
44 # Make sure foo still exists, and commands needing it work
45 test-tool getcwd &&
46 git status --porcelain
47 ) &&
48 test_path_is_missing foo/bar/baz &&
49 test_path_is_missing foo/bar &&
50
51 test_path_is_dir foo
52}
53
54test_required_dir_removal () {
55 git checkout df_conflict^{commit} &&
56 test_when_finished "git clean -fdx" &&
57
58 (
59 cd dirORfile &&
60
61 # Ensure command refuses to run
62 test_must_fail "$@" 2>../error &&
63 grep "Refusing to remove.*current working directory" ../error &&
64
65 # ...and that the index and working tree are left clean
66 git diff --exit-code HEAD &&
67
68 # 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
72 ) &&
73
74 test_path_is_dir dirORfile
75}
76
77test_expect_success 'checkout does not clean cwd incidentally' '
78 test_incidental_dir_removal git checkout init
79'
80
81test_expect_success 'checkout fails if cwd needs to be removed' '
82 test_required_dir_removal git checkout fd_conflict
83'
84
85test_expect_success 'reset --hard does not clean cwd incidentally' '
86 test_incidental_dir_removal git reset --hard init
87'
88
89test_expect_success 'reset --hard fails if cwd needs to be removed' '
90 test_required_dir_removal git reset --hard fd_conflict
91'
92
93test_expect_success 'merge does not clean cwd incidentally' '
94 test_incidental_dir_removal git merge reverted
95'
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
113 test_must_fail git merge fd_conflict 2>../error
114 ) &&
115
116 test_path_is_dir dirORfile &&
117 grep "Refusing to remove the current working directory" error
118'
119
120test_expect_success 'merge fails if cwd needs to be removed' '
121 test_required_dir_removal git merge fd_conflict
122'
123
124test_expect_success 'cherry-pick does not clean cwd incidentally' '
125 test_incidental_dir_removal git cherry-pick reverted
126'
127
128test_expect_success 'cherry-pick fails if cwd needs to be removed' '
129 test_required_dir_removal git cherry-pick fd_conflict
130'
131
132test_expect_success 'rebase does not clean cwd incidentally' '
133 test_incidental_dir_removal git rebase reverted
134'
135
136test_expect_success 'rebase fails if cwd needs to be removed' '
137 test_required_dir_removal git rebase fd_conflict
138'
139
140test_expect_success 'revert does not clean cwd incidentally' '
141 test_incidental_dir_removal git revert HEAD
142'
143
144test_expect_success 'revert fails if cwd needs to be removed' '
145 test_required_dir_removal git revert undo_fd_conflict
146'
147
148test_expect_success 'rm does not clean cwd incidentally' '
149 test_incidental_dir_removal git rm bar/baz.t
150'
151
152test_expect_success 'apply does not remove cwd incidentally' '
153 git diff HEAD HEAD~1 >patch &&
154 test_incidental_dir_removal git apply ../patch
155'
156
157test_incidental_untracked_dir_removal () {
158 test_when_finished "git reset --hard" &&
159
160 git checkout foo/bar/baz^{commit} &&
161 mkdir -p untracked &&
162 mkdir empty
163 >untracked/random &&
164
165 (
166 cd untracked &&
167 "$@" &&
168
169 # Make sure untracked still exists, and commands needing it work
170 test-tool getcwd &&
171 git status --porcelain
172 ) &&
173 test_path_is_missing empty &&
174 test_path_is_missing untracked/random &&
175
176 test_path_is_dir untracked
177}
178
179test_expect_success 'clean does not remove cwd incidentally' '
180 test_incidental_untracked_dir_removal \
181 git -C .. clean -fd -e warnings . >warnings &&
182 grep "Refusing to remove current working directory" warnings
183'
184
185test_expect_success 'stash does not remove cwd incidentally' '
186 test_incidental_untracked_dir_removal \
187 git stash --include-untracked
188'
189
190test_expect_success '`rm -rf dir` only removes a subset of dir' '
191 test_when_finished "rm -rf a/" &&
192
193 mkdir -p a/b/c &&
194 >a/b/c/untracked &&
195 >a/b/c/tracked &&
196 git add a/b/c/tracked &&
197
198 (
199 cd a/b &&
200 git rm -rf ../b
201 ) &&
202
203 test_path_is_dir a/b &&
204 test_path_is_missing a/b/c/tracked &&
205 test_path_is_file a/b/c/untracked
206'
207
208test_expect_success '`rm -rf dir` even with only tracked files will remove something else' '
209 test_when_finished "rm -rf a/" &&
210
211 mkdir -p a/b/c &&
212 >a/b/c/tracked &&
213 git add a/b/c/tracked &&
214
215 (
216 cd a/b &&
217 git rm -rf ../b
218 ) &&
219
220 test_path_is_missing a/b/c/tracked &&
221 test_path_is_missing a/b/c &&
222 test_path_is_dir a/b
223'
224
225test_expect_success 'git version continues working from a deleted dir' '
226 mkdir tmp &&
227 (
228 cd tmp &&
229 rm -rf ../tmp &&
230 git version
231 )
232'
233
234test_submodule_removal () {
235 path_status=$1 &&
236 shift &&
237
238 test_status=
239 test "$path_status" = dir && test_status=test_must_fail
240
241 test_when_finished "git reset --hard HEAD~1" &&
242 test_when_finished "rm -rf .git/modules/my_submodule" &&
243
244 git checkout foo/bar/baz &&
245
246 git init my_submodule &&
247 touch my_submodule/file &&
248 git -C my_submodule add file &&
249 git -C my_submodule commit -m "initial commit" &&
250 git submodule add ./my_submodule &&
251 git commit -m "Add the submodule" &&
252
253 (
254 cd my_submodule &&
255 $test_status "$@"
256 ) &&
257
258 test_path_is_${path_status} my_submodule
259}
260
261test_expect_success 'rm -r with -C leaves submodule if cwd inside' '
262 test_submodule_removal dir git -C .. rm -r my_submodule/
263'
264
265test_expect_success 'rm -r leaves submodule if cwd inside' '
266 test_submodule_removal dir \
267 git --git-dir=../.git --work-tree=.. rm -r ../my_submodule/
268'
269
270test_expect_success 'rm -rf removes submodule even if cwd inside' '
271 test_submodule_removal missing \
272 git --git-dir=../.git --work-tree=.. rm -rf ../my_submodule/
273'
274
275test_done