summaryrefslogtreecommitdiff
path: root/t/t2501-cwd-empty.sh
blob: f6d8d7d03d7ca42b566c2b177ee57345e09b7107 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
#!/bin/sh

test_description='Test handling of the current working directory becoming empty'

. ./test-lib.sh

test_expect_success setup '
	test_commit init &&

	git branch fd_conflict &&

	mkdir -p foo/bar &&
	test_commit foo/bar/baz &&

	git revert HEAD &&
	git tag reverted &&

	git checkout fd_conflict &&
	mkdir dirORfile &&
	test_commit dirORfile/foo &&

	git rm -r dirORfile &&
	echo not-a-directory >dirORfile &&
	git add dirORfile &&
	git commit -m dirORfile &&

	git switch -c df_conflict HEAD~1 &&
	test_commit random_file &&

	git switch -c undo_fd_conflict fd_conflict &&
	git revert HEAD
'

test_incidental_dir_removal () {
	test_when_finished "git reset --hard" &&

	git checkout foo/bar/baz^{commit} &&
	test_path_is_dir foo/bar &&

	(
		cd foo &&
		"$@" &&

		# Make sure foo still exists, and commands needing it work
		test-tool getcwd &&
		git status --porcelain
	) &&
	test_path_is_missing foo/bar/baz &&
	test_path_is_missing foo/bar &&

	test_path_is_dir foo
}

test_required_dir_removal () {
	git checkout df_conflict^{commit} &&
	test_when_finished "git clean -fdx" &&

	(
		cd dirORfile &&

		# Ensure command refuses to run
		test_must_fail "$@" 2>../error &&
		grep "Refusing to remove.*current working directory" ../error &&

		# ...and that the index and working tree are left clean
		git diff --exit-code HEAD &&

		# Ensure that getcwd and git status do not error out (which
		# they might if the current working directory had been removed)
		test-tool getcwd &&
		git status --porcelain
	) &&

	test_path_is_dir dirORfile
}

test_expect_success 'checkout does not clean cwd incidentally' '
	test_incidental_dir_removal git checkout init
'

test_expect_success 'checkout fails if cwd needs to be removed' '
	test_required_dir_removal git checkout fd_conflict
'

test_expect_success 'reset --hard does not clean cwd incidentally' '
	test_incidental_dir_removal git reset --hard init
'

test_expect_success 'reset --hard fails if cwd needs to be removed' '
	test_required_dir_removal git reset --hard fd_conflict
'

test_expect_success 'merge does not clean cwd incidentally' '
	test_incidental_dir_removal git merge reverted
'

# This file uses some simple merges where
#   Base: 'dirORfile/' exists
#   Side1: random other file changed
#   Side2: 'dirORfile/' removed, 'dirORfile' added
# this should resolve cleanly, but merge-recursive throws merge conflicts
# because it's dumb.  Add a special test for checking merge-recursive (and
# merge-ort), then after this just hard require ort for all remaining tests.
#
test_expect_success 'merge fails if cwd needs to be removed; recursive friendly' '
	git checkout foo/bar/baz &&
	test_when_finished "git clean -fdx" &&

	mkdir dirORfile &&
	(
		cd dirORfile &&

		test_must_fail git merge fd_conflict 2>../error
	) &&

	test_path_is_dir dirORfile &&
	grep "Refusing to remove the current working directory" error
'

GIT_TEST_MERGE_ALGORITHM=ort

test_expect_success 'merge fails if cwd needs to be removed' '
	test_required_dir_removal git merge fd_conflict
'

test_expect_success 'cherry-pick does not clean cwd incidentally' '
	test_incidental_dir_removal git cherry-pick reverted
'

test_expect_success 'cherry-pick fails if cwd needs to be removed' '
	test_required_dir_removal git cherry-pick fd_conflict
'

test_expect_success 'rebase does not clean cwd incidentally' '
	test_incidental_dir_removal git rebase reverted
'

test_expect_success 'rebase fails if cwd needs to be removed' '
	test_required_dir_removal git rebase fd_conflict
'

test_expect_success 'revert does not clean cwd incidentally' '
	test_incidental_dir_removal git revert HEAD
'

test_expect_success 'revert fails if cwd needs to be removed' '
	test_required_dir_removal git revert undo_fd_conflict
'

test_expect_success 'rm does not clean cwd incidentally' '
	test_incidental_dir_removal git rm bar/baz.t
'

test_expect_success 'apply does not remove cwd incidentally' '
	git diff HEAD HEAD~1 >patch &&
	test_incidental_dir_removal git apply ../patch
'

test_incidental_untracked_dir_removal () {
	test_when_finished "git reset --hard" &&

	git checkout foo/bar/baz^{commit} &&
	mkdir -p untracked &&
	mkdir empty
	>untracked/random &&

	(
		cd untracked &&
		"$@" &&

		# Make sure untracked still exists, and commands needing it work
		test-tool getcwd &&
		git status --porcelain
	) &&
	test_path_is_missing empty &&
	test_path_is_missing untracked/random &&

	test_path_is_dir untracked
}

test_expect_success 'clean does not remove cwd incidentally' '
	test_incidental_untracked_dir_removal \
		git -C .. clean -fd -e warnings . >warnings &&
	grep "Refusing to remove current working directory" warnings
'

test_expect_success 'stash does not remove cwd incidentally' '
	test_incidental_untracked_dir_removal \
		git stash --include-untracked
'

test_expect_success '`rm -rf dir` only removes a subset of dir' '
	test_when_finished "rm -rf a/" &&

	mkdir -p a/b/c &&
	>a/b/c/untracked &&
	>a/b/c/tracked &&
	git add a/b/c/tracked &&

	(
		cd a/b &&
		git rm -rf ../b
	) &&

	test_path_is_dir a/b &&
	test_path_is_missing a/b/c/tracked &&
	test_path_is_file a/b/c/untracked
'

test_expect_success '`rm -rf dir` even with only tracked files will remove something else' '
	test_when_finished "rm -rf a/" &&

	mkdir -p a/b/c &&
	>a/b/c/tracked &&
	git add a/b/c/tracked &&

	(
		cd a/b &&
		git rm -rf ../b
	) &&

	test_path_is_missing a/b/c/tracked &&
	test_path_is_missing a/b/c &&
	test_path_is_dir a/b
'

test_expect_success 'git version continues working from a deleted dir' '
	mkdir tmp &&
	(
		cd tmp &&
		rm -rf ../tmp &&
		git version
	)
'

test_submodule_removal () {
	path_status=$1 &&
	shift &&

	test_status=
	test "$path_status" = dir && test_status=test_must_fail

	test_when_finished "git reset --hard HEAD~1" &&
	test_when_finished "rm -rf .git/modules/my_submodule" &&

	git checkout foo/bar/baz &&

	git init my_submodule &&
	touch my_submodule/file &&
	git -C my_submodule add file &&
	git -C my_submodule commit -m "initial commit" &&
	git submodule add ./my_submodule &&
	git commit -m "Add the submodule" &&

	(
		cd my_submodule &&
		$test_status "$@"
	) &&

	test_path_is_${path_status} my_submodule
}

test_expect_success 'rm -r with -C leaves submodule if cwd inside' '
	test_submodule_removal dir git -C .. rm -r my_submodule/
'

test_expect_success 'rm -r leaves submodule if cwd inside' '
	test_submodule_removal dir \
		git --git-dir=../.git --work-tree=.. rm -r ../my_submodule/
'

test_expect_success 'rm -rf removes submodule even if cwd inside' '
	test_submodule_removal missing \
		git --git-dir=../.git --work-tree=.. rm -rf ../my_submodule/
'

test_done