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
|
#!/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
'
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
|