You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
343 lines
8.2 KiB
343 lines
8.2 KiB
![]()
3 years ago
|
#!/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 () {
|
||
|
works=$1 &&
|
||
|
shift &&
|
||
|
|
||
|
test_when_finished "git reset --hard" &&
|
||
|
|
||
|
git checkout foo/bar/baz^{commit} &&
|
||
|
test_path_is_dir foo/bar &&
|
||
|
|
||
|
(
|
||
|
cd foo &&
|
||
|
"$@" &&
|
||
|
|
||
|
# Although we want pwd & git status to pass, test for existing
|
||
|
# rather than desired behavior.
|
||
|
if test "$works" = "success"
|
||
|
then
|
||
|
test-tool getcwd &&
|
||
|
git status --porcelain
|
||
|
else
|
||
|
! test-tool getcwd &&
|
||
|
test_might_fail git status --porcelain
|
||
|
fi
|
||
|
) &&
|
||
|
test_path_is_missing foo/bar/baz &&
|
||
|
test_path_is_missing foo/bar &&
|
||
|
|
||
|
# Although we want dir to be present, test for existing rather
|
||
|
# than desired behavior.
|
||
|
if test "$works" = "success"
|
||
|
then
|
||
|
test_path_is_dir foo
|
||
|
else
|
||
|
test_path_is_missing foo
|
||
|
fi
|
||
|
}
|
||
|
|
||
|
test_required_dir_removal () {
|
||
|
works=$1 &&
|
||
|
shift &&
|
||
|
|
||
|
git checkout df_conflict^{commit} &&
|
||
|
test_when_finished "git clean -fdx" &&
|
||
|
|
||
|
(
|
||
|
cd dirORfile &&
|
||
|
|
||
|
# We'd like for the command to fail (much as it would if there
|
||
|
# was an untracked file there), and for the index and worktree
|
||
|
# to be left clean with pwd and git status working afterwards.
|
||
|
# But test for existing rather than desired behavior.
|
||
|
if test "$works" = "success"
|
||
|
then
|
||
|
test_must_fail "$@" 2>../error &&
|
||
|
grep "Refusing to remove.*current working directory" ../error &&
|
||
|
|
||
|
git diff --exit-code HEAD &&
|
||
|
|
||
|
test-tool getcwd &&
|
||
|
git status --porcelain
|
||
|
else
|
||
|
"$@" &&
|
||
|
! test-tool getcwd &&
|
||
|
test_might_fail git status --porcelain
|
||
|
fi
|
||
|
) &&
|
||
|
|
||
|
# Although we want dirORfile to be present, test for existing rather
|
||
|
# than desired behavior.
|
||
|
if test "$works" = "success"
|
||
|
then
|
||
|
test_path_is_dir dirORfile
|
||
|
else
|
||
|
test_path_is_file dirORfile
|
||
|
fi
|
||
|
}
|
||
|
|
||
|
test_expect_success 'checkout does not clean cwd incidentally' '
|
||
|
test_incidental_dir_removal failure git checkout init
|
||
|
'
|
||
|
|
||
|
test_expect_success 'checkout fails if cwd needs to be removed' '
|
||
|
test_required_dir_removal failure git checkout fd_conflict
|
||
|
'
|
||
|
|
||
|
test_expect_success 'reset --hard does not clean cwd incidentally' '
|
||
|
test_incidental_dir_removal failure git reset --hard init
|
||
|
'
|
||
|
|
||
|
test_expect_success 'reset --hard fails if cwd needs to be removed' '
|
||
|
test_required_dir_removal failure git reset --hard fd_conflict
|
||
|
'
|
||
|
|
||
|
test_expect_success 'merge does not clean cwd incidentally' '
|
||
|
test_incidental_dir_removal failure 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 &&
|
||
|
|
||
|
# We would rather this failed, but we test for existing
|
||
|
# rather than desired behavior
|
||
|
git merge fd_conflict 2>../error
|
||
|
) &&
|
||
|
|
||
|
## Here is the behavior we would rather have:
|
||
|
#test_path_is_dir dirORfile &&
|
||
|
#grep "Refusing to remove the current working directory" error
|
||
|
## But instead we test for existing behavior
|
||
|
test_path_is_file dirORfile &&
|
||
|
test_must_be_empty error
|
||
|
'
|
||
|
|
||
|
GIT_TEST_MERGE_ALGORITHM=ort
|
||
|
|
||
|
test_expect_success 'merge fails if cwd needs to be removed' '
|
||
|
test_required_dir_removal failure git merge fd_conflict
|
||
|
'
|
||
|
|
||
|
test_expect_success 'cherry-pick does not clean cwd incidentally' '
|
||
|
test_incidental_dir_removal failure git cherry-pick reverted
|
||
|
'
|
||
|
|
||
|
test_expect_success 'cherry-pick fails if cwd needs to be removed' '
|
||
|
test_required_dir_removal failure git cherry-pick fd_conflict
|
||
|
'
|
||
|
|
||
|
test_expect_success 'rebase does not clean cwd incidentally' '
|
||
|
test_incidental_dir_removal failure git rebase reverted
|
||
|
'
|
||
|
|
||
|
test_expect_success 'rebase fails if cwd needs to be removed' '
|
||
|
test_required_dir_removal failure git rebase fd_conflict
|
||
|
'
|
||
|
|
||
|
test_expect_success 'revert does not clean cwd incidentally' '
|
||
|
test_incidental_dir_removal failure git revert HEAD
|
||
|
'
|
||
|
|
||
|
test_expect_success 'revert fails if cwd needs to be removed' '
|
||
|
test_required_dir_removal failure git revert undo_fd_conflict
|
||
|
'
|
||
|
|
||
|
test_expect_success 'rm does not clean cwd incidentally' '
|
||
|
test_incidental_dir_removal failure git rm bar/baz.t
|
||
|
'
|
||
|
|
||
|
test_expect_success 'apply does not remove cwd incidentally' '
|
||
|
git diff HEAD HEAD~1 >patch &&
|
||
|
test_incidental_dir_removal failure git apply ../patch
|
||
|
'
|
||
|
|
||
|
test_incidental_untracked_dir_removal () {
|
||
|
works=$1 &&
|
||
|
shift &&
|
||
|
|
||
|
test_when_finished "git reset --hard" &&
|
||
|
|
||
|
git checkout foo/bar/baz^{commit} &&
|
||
|
mkdir -p untracked &&
|
||
|
mkdir empty
|
||
|
>untracked/random &&
|
||
|
|
||
|
(
|
||
|
cd untracked &&
|
||
|
"$@" &&
|
||
|
|
||
|
# Although we want pwd & git status to pass, test for existing
|
||
|
# rather than desired behavior.
|
||
|
if test "$works" = "success"
|
||
|
then
|
||
|
test-tool getcwd &&
|
||
|
git status --porcelain
|
||
|
else
|
||
|
! test-tool getcwd &&
|
||
|
test_might_fail git status --porcelain
|
||
|
fi
|
||
|
) &&
|
||
|
test_path_is_missing empty &&
|
||
|
test_path_is_missing untracked/random &&
|
||
|
|
||
|
# Although we want dir to be present, test for existing rather
|
||
|
# than desired behavior.
|
||
|
if test "$works" = "success"
|
||
|
then
|
||
|
test_path_is_dir untracked
|
||
|
else
|
||
|
test_path_is_missing untracked
|
||
|
fi
|
||
|
}
|
||
|
|
||
|
test_expect_success 'clean does not remove cwd incidentally' '
|
||
|
test_incidental_untracked_dir_removal failure \
|
||
|
git -C .. clean -fd -e warnings . >warnings
|
||
|
'
|
||
|
|
||
|
test_expect_success 'stash does not remove cwd incidentally' '
|
||
|
test_incidental_untracked_dir_removal failure \
|
||
|
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 &&
|
||
|
## We would prefer if a/b was still present, though empty, since it
|
||
|
## was the current working directory
|
||
|
#test_path_is_dir a/b
|
||
|
## But the current behavior is that it not only deletes the directory
|
||
|
## a/b as requested, but also goes and deletes a
|
||
|
test_path_is_missing a
|
||
|
'
|
||
|
|
||
|
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
|
||
|
|
||
|
# Actually, while path_status=dir && test_status=test_must_fail
|
||
|
# reflect our desired behavior, current behavior is:
|
||
|
path_status=missing
|
||
|
test_status=
|
||
|
|
||
|
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
|