Sync with 2.39.4
* maint-2.39: (38 commits) Git 2.39.4 fsck: warn about symlink pointing inside a gitdir core.hooksPath: add some protection while cloning init.templateDir: consider this config setting protected clone: prevent hooks from running during a clone Add a helper function to compare file contents init: refactor the template directory discovery into its own function find_hook(): refactor the `STRIP_EXTENSION` logic clone: when symbolic links collide with directories, keep the latter entry: report more colliding paths t5510: verify that D/F confusion cannot lead to an RCE submodule: require the submodule path to contain directories only clone_submodule: avoid using `access()` on directories submodules: submodule paths must not contain symlinks clone: prevent clashing git dirs when cloning submodule in parallel t7423: add tests for symlinked submodule directories has_dir_name(): do not get confused by characters < '/' docs: document security issues around untrusted .git dirs upload-pack: disable lazy-fetching by default fetch/clone: detect dubious ownership of local repositories ...
This commit is contained in:
@ -495,6 +495,16 @@ int cmd__path_utils(int argc, const char **argv)
|
||||
return !!res;
|
||||
}
|
||||
|
||||
if (argc == 4 && !strcmp(argv[1], "do_files_match")) {
|
||||
int ret = do_files_match(argv[2], argv[3]);
|
||||
|
||||
if (ret)
|
||||
printf("equal\n");
|
||||
else
|
||||
printf("different\n");
|
||||
return !ret;
|
||||
}
|
||||
|
||||
fprintf(stderr, "%s: unknown function name: %s\n", argv[0],
|
||||
argv[1] ? argv[1] : "(there was none)");
|
||||
return 1;
|
||||
|
@ -1201,6 +1201,34 @@ test_expect_success 'very long name in the index handled sanely' '
|
||||
test $len = 4098
|
||||
'
|
||||
|
||||
# D/F conflict checking uses an optimization when adding to the end.
|
||||
# make sure it does not get confused by `a-` sorting _between_
|
||||
# `a` and `a/`.
|
||||
test_expect_success 'more update-index D/F conflicts' '
|
||||
# empty the index to make sure our entry is last
|
||||
git read-tree --empty &&
|
||||
cacheinfo=100644,$(test_oid empty_blob) &&
|
||||
git update-index --add --cacheinfo $cacheinfo,path5/a &&
|
||||
|
||||
test_must_fail git update-index --add --cacheinfo $cacheinfo,path5/a/file &&
|
||||
test_must_fail git update-index --add --cacheinfo $cacheinfo,path5/a/b/file &&
|
||||
test_must_fail git update-index --add --cacheinfo $cacheinfo,path5/a/b/c/file &&
|
||||
|
||||
# "a-" sorts between "a" and "a/"
|
||||
git update-index --add --cacheinfo $cacheinfo,path5/a- &&
|
||||
|
||||
test_must_fail git update-index --add --cacheinfo $cacheinfo,path5/a/file &&
|
||||
test_must_fail git update-index --add --cacheinfo $cacheinfo,path5/a/b/file &&
|
||||
test_must_fail git update-index --add --cacheinfo $cacheinfo,path5/a/b/c/file &&
|
||||
|
||||
cat >expected <<-\EOF &&
|
||||
path5/a
|
||||
path5/a-
|
||||
EOF
|
||||
git ls-files >actual &&
|
||||
test_cmp expected actual
|
||||
'
|
||||
|
||||
test_expect_success 'test_must_fail on a failing git command' '
|
||||
test_must_fail git notacommand
|
||||
'
|
||||
|
@ -80,4 +80,28 @@ test_expect_success 'safe.directory in included file' '
|
||||
git status
|
||||
'
|
||||
|
||||
test_expect_success 'local clone of unowned repo refused in unsafe directory' '
|
||||
test_when_finished "rm -rf source" &&
|
||||
git init source &&
|
||||
(
|
||||
sane_unset GIT_TEST_ASSUME_DIFFERENT_OWNER &&
|
||||
test_commit -C source initial
|
||||
) &&
|
||||
test_must_fail git clone --local source target &&
|
||||
test_path_is_missing target
|
||||
'
|
||||
|
||||
test_expect_success 'local clone of unowned repo accepted in safe directory' '
|
||||
test_when_finished "rm -rf source" &&
|
||||
git init source &&
|
||||
(
|
||||
sane_unset GIT_TEST_ASSUME_DIFFERENT_OWNER &&
|
||||
test_commit -C source initial
|
||||
) &&
|
||||
test_must_fail git clone --local source target &&
|
||||
git config --global --add safe.directory "$(pwd)/source/.git" &&
|
||||
git clone --local source target &&
|
||||
test_path_is_dir target
|
||||
'
|
||||
|
||||
test_done
|
||||
|
@ -560,4 +560,45 @@ test_expect_success !VALGRIND,RUNTIME_PREFIX,CAN_EXEC_IN_PWD '%(prefix)/ works'
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success 'do_files_match()' '
|
||||
test_seq 0 10 >0-10.txt &&
|
||||
test_seq -1 10 >-1-10.txt &&
|
||||
test_seq 1 10 >1-10.txt &&
|
||||
test_seq 1 9 >1-9.txt &&
|
||||
test_seq 0 8 >0-8.txt &&
|
||||
|
||||
test-tool path-utils do_files_match 0-10.txt 0-10.txt >out &&
|
||||
|
||||
assert_fails() {
|
||||
test_must_fail \
|
||||
test-tool path-utils do_files_match "$1" "$2" >out &&
|
||||
grep different out
|
||||
} &&
|
||||
|
||||
assert_fails 0-8.txt 1-9.txt &&
|
||||
assert_fails -1-10.txt 0-10.txt &&
|
||||
assert_fails 1-10.txt 1-9.txt &&
|
||||
assert_fails 1-10.txt .git &&
|
||||
assert_fails does-not-exist 1-10.txt &&
|
||||
|
||||
if test_have_prereq FILEMODE
|
||||
then
|
||||
cp 0-10.txt 0-10.x &&
|
||||
chmod a+x 0-10.x &&
|
||||
assert_fails 0-10.txt 0-10.x
|
||||
fi &&
|
||||
|
||||
if test_have_prereq SYMLINKS
|
||||
then
|
||||
ln -sf 0-10.txt symlink &&
|
||||
ln -s 0-10.txt another-symlink &&
|
||||
ln -s over-the-ocean yet-another-symlink &&
|
||||
ln -s "$PWD/0-10.txt" absolute-symlink &&
|
||||
assert_fails 0-10.txt symlink &&
|
||||
test-tool path-utils do_files_match symlink another-symlink &&
|
||||
assert_fails symlink yet-another-symlink &&
|
||||
assert_fails symlink absolute-symlink
|
||||
fi
|
||||
'
|
||||
|
||||
test_done
|
||||
|
78
t/t0411-clone-from-partial.sh
Executable file
78
t/t0411-clone-from-partial.sh
Executable file
@ -0,0 +1,78 @@
|
||||
#!/bin/sh
|
||||
|
||||
test_description='check that local clone does not fetch from promisor remotes'
|
||||
|
||||
. ./test-lib.sh
|
||||
|
||||
test_expect_success 'create evil repo' '
|
||||
git init tmp &&
|
||||
test_commit -C tmp a &&
|
||||
git -C tmp config uploadpack.allowfilter 1 &&
|
||||
git clone --filter=blob:none --no-local --no-checkout tmp evil &&
|
||||
rm -rf tmp &&
|
||||
|
||||
git -C evil config remote.origin.uploadpack \"\$TRASH_DIRECTORY/fake-upload-pack\" &&
|
||||
write_script fake-upload-pack <<-\EOF &&
|
||||
echo >&2 "fake-upload-pack running"
|
||||
>"$TRASH_DIRECTORY/script-executed"
|
||||
exit 1
|
||||
EOF
|
||||
export TRASH_DIRECTORY &&
|
||||
|
||||
# empty shallow file disables local clone optimization
|
||||
>evil/.git/shallow
|
||||
'
|
||||
|
||||
test_expect_success 'local clone must not fetch from promisor remote and execute script' '
|
||||
rm -f script-executed &&
|
||||
test_must_fail git clone \
|
||||
--upload-pack="GIT_TEST_ASSUME_DIFFERENT_OWNER=true git-upload-pack" \
|
||||
evil clone1 2>err &&
|
||||
grep "detected dubious ownership" err &&
|
||||
! grep "fake-upload-pack running" err &&
|
||||
test_path_is_missing script-executed
|
||||
'
|
||||
|
||||
test_expect_success 'clone from file://... must not fetch from promisor remote and execute script' '
|
||||
rm -f script-executed &&
|
||||
test_must_fail git clone \
|
||||
--upload-pack="GIT_TEST_ASSUME_DIFFERENT_OWNER=true git-upload-pack" \
|
||||
"file://$(pwd)/evil" clone2 2>err &&
|
||||
grep "detected dubious ownership" err &&
|
||||
! grep "fake-upload-pack running" err &&
|
||||
test_path_is_missing script-executed
|
||||
'
|
||||
|
||||
test_expect_success 'fetch from file://... must not fetch from promisor remote and execute script' '
|
||||
rm -f script-executed &&
|
||||
test_must_fail git fetch \
|
||||
--upload-pack="GIT_TEST_ASSUME_DIFFERENT_OWNER=true git-upload-pack" \
|
||||
"file://$(pwd)/evil" 2>err &&
|
||||
grep "detected dubious ownership" err &&
|
||||
! grep "fake-upload-pack running" err &&
|
||||
test_path_is_missing script-executed
|
||||
'
|
||||
|
||||
test_expect_success 'pack-objects should fetch from promisor remote and execute script' '
|
||||
rm -f script-executed &&
|
||||
echo "HEAD" | test_must_fail git -C evil pack-objects --revs --stdout >/dev/null 2>err &&
|
||||
grep "fake-upload-pack running" err &&
|
||||
test_path_is_file script-executed
|
||||
'
|
||||
|
||||
test_expect_success 'clone from promisor remote does not lazy-fetch by default' '
|
||||
rm -f script-executed &&
|
||||
test_must_fail git clone evil no-lazy 2>err &&
|
||||
grep "lazy fetching disabled" err &&
|
||||
test_path_is_missing script-executed
|
||||
'
|
||||
|
||||
test_expect_success 'promisor lazy-fetching can be re-enabled' '
|
||||
rm -f script-executed &&
|
||||
test_must_fail env GIT_NO_LAZY_FETCH=0 \
|
||||
git clone evil lazy-ok 2>err &&
|
||||
grep "fake-upload-pack running" err &&
|
||||
test_path_is_file script-executed
|
||||
'
|
||||
|
||||
test_done
|
@ -1023,4 +1023,41 @@ test_expect_success 'fsck error on gitattributes with excessive size' '
|
||||
test_cmp expected actual
|
||||
'
|
||||
|
||||
test_expect_success 'fsck warning on symlink target with excessive length' '
|
||||
symlink_target=$(printf "pattern %032769d" 1 | git hash-object -w --stdin) &&
|
||||
test_when_finished "remove_object $symlink_target" &&
|
||||
tree=$(printf "120000 blob %s\t%s\n" $symlink_target symlink | git mktree) &&
|
||||
test_when_finished "remove_object $tree" &&
|
||||
cat >expected <<-EOF &&
|
||||
warning in blob $symlink_target: symlinkTargetLength: symlink target too long
|
||||
EOF
|
||||
git fsck --no-dangling >actual 2>&1 &&
|
||||
test_cmp expected actual
|
||||
'
|
||||
|
||||
test_expect_success 'fsck warning on symlink target pointing inside git dir' '
|
||||
gitdir=$(printf ".git" | git hash-object -w --stdin) &&
|
||||
ntfs_gitdir=$(printf "GIT~1" | git hash-object -w --stdin) &&
|
||||
hfs_gitdir=$(printf ".${u200c}git" | git hash-object -w --stdin) &&
|
||||
inside_gitdir=$(printf "nested/.git/config" | git hash-object -w --stdin) &&
|
||||
benign_target=$(printf "legit/config" | git hash-object -w --stdin) &&
|
||||
tree=$(printf "120000 blob %s\t%s\n" \
|
||||
$benign_target benign_target \
|
||||
$gitdir gitdir \
|
||||
$hfs_gitdir hfs_gitdir \
|
||||
$inside_gitdir inside_gitdir \
|
||||
$ntfs_gitdir ntfs_gitdir |
|
||||
git mktree) &&
|
||||
for o in $gitdir $ntfs_gitdir $hfs_gitdir $inside_gitdir $benign_target $tree
|
||||
do
|
||||
test_when_finished "remove_object $o" || return 1
|
||||
done &&
|
||||
printf "warning in blob %s: symlinkPointsToGitDir: symlink target points to git dir\n" \
|
||||
$gitdir $hfs_gitdir $inside_gitdir $ntfs_gitdir |
|
||||
sort >expected &&
|
||||
git fsck --no-dangling >actual 2>&1 &&
|
||||
sort actual >actual.sorted &&
|
||||
test_cmp expected actual.sorted
|
||||
'
|
||||
|
||||
test_done
|
||||
|
@ -195,4 +195,19 @@ test_expect_success 'stdin to hooks' '
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success 'clone protections' '
|
||||
test_config core.hooksPath "$(pwd)/my-hooks" &&
|
||||
mkdir -p my-hooks &&
|
||||
write_script my-hooks/test-hook <<-\EOF &&
|
||||
echo Hook ran $1
|
||||
EOF
|
||||
|
||||
git hook run test-hook 2>err &&
|
||||
grep "Hook ran" err &&
|
||||
test_must_fail env GIT_CLONE_PROTECTION_ACTIVE=true \
|
||||
git hook run test-hook 2>err &&
|
||||
grep "active .core.hooksPath" err &&
|
||||
! grep "Hook ran" err
|
||||
'
|
||||
|
||||
test_done
|
||||
|
@ -1248,6 +1248,30 @@ EOF
|
||||
test_cmp fatal-expect fatal-actual
|
||||
'
|
||||
|
||||
test_expect_success SYMLINKS 'clone does not get confused by a D/F conflict' '
|
||||
git init df-conflict &&
|
||||
(
|
||||
cd df-conflict &&
|
||||
ln -s .git a &&
|
||||
git add a &&
|
||||
test_tick &&
|
||||
git commit -m symlink &&
|
||||
test_commit a- &&
|
||||
rm a &&
|
||||
mkdir -p a/hooks &&
|
||||
write_script a/hooks/post-checkout <<-EOF &&
|
||||
echo WHOOPSIE >&2
|
||||
echo whoopsie >"$TRASH_DIRECTORY"/whoops
|
||||
EOF
|
||||
git add a/hooks/post-checkout &&
|
||||
test_tick &&
|
||||
git commit -m post-checkout
|
||||
) &&
|
||||
git clone df-conflict clone 2>err &&
|
||||
! grep WHOOPS err &&
|
||||
test_path_is_missing whoops
|
||||
'
|
||||
|
||||
. "$TEST_DIRECTORY"/lib-httpd.sh
|
||||
start_httpd
|
||||
|
||||
|
@ -633,6 +633,21 @@ test_expect_success CASE_INSENSITIVE_FS 'colliding file detection' '
|
||||
test_i18ngrep "the following paths have collided" icasefs/warning
|
||||
'
|
||||
|
||||
test_expect_success CASE_INSENSITIVE_FS,SYMLINKS \
|
||||
'colliding symlink/directory keeps directory' '
|
||||
git init icasefs-colliding-symlink &&
|
||||
(
|
||||
cd icasefs-colliding-symlink &&
|
||||
a=$(printf a | git hash-object -w --stdin) &&
|
||||
printf "100644 %s 0\tA/dir/b\n120000 %s 0\ta\n" $a $a >idx &&
|
||||
git update-index --index-info <idx &&
|
||||
test_tick &&
|
||||
git commit -m initial
|
||||
) &&
|
||||
git clone icasefs-colliding-symlink icasefs-colliding-symlink-clone &&
|
||||
test_file_not_empty icasefs-colliding-symlink-clone/A/dir/b
|
||||
'
|
||||
|
||||
test_expect_success 'clone with GIT_DEFAULT_HASH' '
|
||||
(
|
||||
sane_unset GIT_DEFAULT_HASH &&
|
||||
@ -756,6 +771,57 @@ test_expect_success 'batch missing blob request does not inadvertently try to fe
|
||||
git clone --filter=blob:limit=0 "file://$(pwd)/server" client
|
||||
'
|
||||
|
||||
test_expect_success 'clone with init.templatedir runs hooks' '
|
||||
git init tmpl/hooks &&
|
||||
write_script tmpl/hooks/post-checkout <<-EOF &&
|
||||
echo HOOK-RUN >&2
|
||||
echo I was here >hook.run
|
||||
EOF
|
||||
git -C tmpl/hooks add . &&
|
||||
test_tick &&
|
||||
git -C tmpl/hooks commit -m post-checkout &&
|
||||
|
||||
test_when_finished "git config --global --unset init.templateDir || :" &&
|
||||
test_when_finished "git config --unset init.templateDir || :" &&
|
||||
(
|
||||
sane_unset GIT_TEMPLATE_DIR &&
|
||||
NO_SET_GIT_TEMPLATE_DIR=t &&
|
||||
export NO_SET_GIT_TEMPLATE_DIR &&
|
||||
|
||||
git -c core.hooksPath="$(pwd)/tmpl/hooks" \
|
||||
clone tmpl/hooks hook-run-hookspath 2>err &&
|
||||
! grep "active .* hook found" err &&
|
||||
test_path_is_file hook-run-hookspath/hook.run &&
|
||||
|
||||
git -c init.templateDir="$(pwd)/tmpl" \
|
||||
clone tmpl/hooks hook-run-config 2>err &&
|
||||
! grep "active .* hook found" err &&
|
||||
test_path_is_file hook-run-config/hook.run &&
|
||||
|
||||
git clone --template=tmpl tmpl/hooks hook-run-option 2>err &&
|
||||
! grep "active .* hook found" err &&
|
||||
test_path_is_file hook-run-option/hook.run &&
|
||||
|
||||
git config --global init.templateDir "$(pwd)/tmpl" &&
|
||||
git clone tmpl/hooks hook-run-global-config 2>err &&
|
||||
git config --global --unset init.templateDir &&
|
||||
! grep "active .* hook found" err &&
|
||||
test_path_is_file hook-run-global-config/hook.run &&
|
||||
|
||||
# clone ignores local `init.templateDir`; need to create
|
||||
# a new repository because we deleted `.git/` in the
|
||||
# `setup` test case above
|
||||
git init local-clone &&
|
||||
cd local-clone &&
|
||||
|
||||
git config init.templateDir "$(pwd)/../tmpl" &&
|
||||
git clone ../tmpl/hooks hook-run-local-config 2>err &&
|
||||
git config --unset init.templateDir &&
|
||||
! grep "active .* hook found" err &&
|
||||
test_path_is_missing hook-run-local-config/hook.run
|
||||
)
|
||||
'
|
||||
|
||||
. "$TEST_DIRECTORY"/lib-httpd.sh
|
||||
start_httpd
|
||||
|
||||
|
@ -1436,4 +1436,35 @@ test_expect_success 'recursive clone respects -q' '
|
||||
test_must_be_empty actual
|
||||
'
|
||||
|
||||
test_expect_success '`submodule init` and `init.templateDir`' '
|
||||
mkdir -p tmpl/hooks &&
|
||||
write_script tmpl/hooks/post-checkout <<-EOF &&
|
||||
echo HOOK-RUN >&2
|
||||
echo I was here >hook.run
|
||||
exit 1
|
||||
EOF
|
||||
|
||||
test_config init.templateDir "$(pwd)/tmpl" &&
|
||||
test_when_finished \
|
||||
"git config --global --unset init.templateDir || true" &&
|
||||
(
|
||||
sane_unset GIT_TEMPLATE_DIR &&
|
||||
NO_SET_GIT_TEMPLATE_DIR=t &&
|
||||
export NO_SET_GIT_TEMPLATE_DIR &&
|
||||
|
||||
git config --global init.templateDir "$(pwd)/tmpl" &&
|
||||
test_must_fail git submodule \
|
||||
add "$submodurl" sub-global 2>err &&
|
||||
git config --global --unset init.templateDir &&
|
||||
grep HOOK-RUN err &&
|
||||
test_path_is_file sub-global/hook.run &&
|
||||
|
||||
git config init.templateDir "$(pwd)/tmpl" &&
|
||||
git submodule add "$submodurl" sub-local 2>err &&
|
||||
git config --unset init.templateDir &&
|
||||
! grep HOOK-RUN err &&
|
||||
test_path_is_missing sub-local/hook.run
|
||||
)
|
||||
'
|
||||
|
||||
test_done
|
||||
|
@ -1179,4 +1179,52 @@ test_expect_success 'submodule update --recursive skip submodules with strategy=
|
||||
test_cmp expect.err actual.err
|
||||
'
|
||||
|
||||
test_expect_success CASE_INSENSITIVE_FS,SYMLINKS \
|
||||
'submodule paths must not follow symlinks' '
|
||||
|
||||
# This is only needed because we want to run this in a self-contained
|
||||
# test without having to spin up an HTTP server; However, it would not
|
||||
# be needed in a real-world scenario where the submodule is simply
|
||||
# hosted on a public site.
|
||||
test_config_global protocol.file.allow always &&
|
||||
|
||||
# Make sure that Git tries to use symlinks on Windows
|
||||
test_config_global core.symlinks true &&
|
||||
|
||||
tell_tale_path="$PWD/tell.tale" &&
|
||||
git init hook &&
|
||||
(
|
||||
cd hook &&
|
||||
mkdir -p y/hooks &&
|
||||
write_script y/hooks/post-checkout <<-EOF &&
|
||||
echo HOOK-RUN >&2
|
||||
echo hook-run >"$tell_tale_path"
|
||||
EOF
|
||||
git add y/hooks/post-checkout &&
|
||||
test_tick &&
|
||||
git commit -m post-checkout
|
||||
) &&
|
||||
|
||||
hook_repo_path="$(pwd)/hook" &&
|
||||
git init captain &&
|
||||
(
|
||||
cd captain &&
|
||||
git submodule add --name x/y "$hook_repo_path" A/modules/x &&
|
||||
test_tick &&
|
||||
git commit -m add-submodule &&
|
||||
|
||||
printf .git >dotgit.txt &&
|
||||
git hash-object -w --stdin <dotgit.txt >dot-git.hash &&
|
||||
printf "120000 %s 0\ta\n" "$(cat dot-git.hash)" >index.info &&
|
||||
git update-index --index-info <index.info &&
|
||||
test_tick &&
|
||||
git commit -m add-symlink
|
||||
) &&
|
||||
|
||||
test_path_is_missing "$tell_tale_path" &&
|
||||
git clone --recursive captain hooked 2>err &&
|
||||
! grep HOOK-RUN err &&
|
||||
test_path_is_missing "$tell_tale_path"
|
||||
'
|
||||
|
||||
test_done
|
||||
|
67
t/t7423-submodule-symlinks.sh
Executable file
67
t/t7423-submodule-symlinks.sh
Executable file
@ -0,0 +1,67 @@
|
||||
#!/bin/sh
|
||||
|
||||
test_description='check that submodule operations do not follow symlinks'
|
||||
|
||||
. ./test-lib.sh
|
||||
|
||||
test_expect_success 'prepare' '
|
||||
git config --global protocol.file.allow always &&
|
||||
test_commit initial &&
|
||||
git init upstream &&
|
||||
test_commit -C upstream upstream submodule_file &&
|
||||
git submodule add ./upstream a/sm &&
|
||||
test_tick &&
|
||||
git commit -m submodule
|
||||
'
|
||||
|
||||
test_expect_success SYMLINKS 'git submodule update must not create submodule behind symlink' '
|
||||
rm -rf a b &&
|
||||
mkdir b &&
|
||||
ln -s b a &&
|
||||
test_path_is_missing b/sm &&
|
||||
test_must_fail git submodule update &&
|
||||
test_path_is_missing b/sm
|
||||
'
|
||||
|
||||
test_expect_success SYMLINKS,CASE_INSENSITIVE_FS 'git submodule update must not create submodule behind symlink on case insensitive fs' '
|
||||
rm -rf a b &&
|
||||
mkdir b &&
|
||||
ln -s b A &&
|
||||
test_must_fail git submodule update &&
|
||||
test_path_is_missing b/sm
|
||||
'
|
||||
|
||||
prepare_symlink_to_repo() {
|
||||
rm -rf a &&
|
||||
mkdir a &&
|
||||
git init a/target &&
|
||||
git -C a/target fetch ../../upstream &&
|
||||
ln -s target a/sm
|
||||
}
|
||||
|
||||
test_expect_success SYMLINKS 'git restore --recurse-submodules must not be confused by a symlink' '
|
||||
prepare_symlink_to_repo &&
|
||||
test_must_fail git restore --recurse-submodules a/sm &&
|
||||
test_path_is_missing a/sm/submodule_file &&
|
||||
test_path_is_dir a/target/.git &&
|
||||
test_path_is_missing a/target/submodule_file
|
||||
'
|
||||
|
||||
test_expect_success SYMLINKS 'git restore --recurse-submodules must not migrate git dir of symlinked repo' '
|
||||
prepare_symlink_to_repo &&
|
||||
rm -rf .git/modules &&
|
||||
test_must_fail git restore --recurse-submodules a/sm &&
|
||||
test_path_is_dir a/target/.git &&
|
||||
test_path_is_missing .git/modules/a/sm &&
|
||||
test_path_is_missing a/target/submodule_file
|
||||
'
|
||||
|
||||
test_expect_success SYMLINKS 'git checkout -f --recurse-submodules must not migrate git dir of symlinked repo when removing submodule' '
|
||||
prepare_symlink_to_repo &&
|
||||
rm -rf .git/modules &&
|
||||
test_must_fail git checkout -f --recurse-submodules initial &&
|
||||
test_path_is_dir a/target/.git &&
|
||||
test_path_is_missing .git/modules/a/sm
|
||||
'
|
||||
|
||||
test_done
|
@ -294,7 +294,7 @@ test_expect_success WINDOWS 'prevent git~1 squatting on Windows' '
|
||||
fi
|
||||
'
|
||||
|
||||
test_expect_success 'git dirs of sibling submodules must not be nested' '
|
||||
test_expect_success 'setup submodules with nested git dirs' '
|
||||
git init nested &&
|
||||
test_commit -C nested nested &&
|
||||
(
|
||||
@ -312,9 +312,39 @@ test_expect_success 'git dirs of sibling submodules must not be nested' '
|
||||
git add .gitmodules thing1 thing2 &&
|
||||
test_tick &&
|
||||
git commit -m nested
|
||||
) &&
|
||||
)
|
||||
'
|
||||
|
||||
test_expect_success 'git dirs of sibling submodules must not be nested' '
|
||||
test_must_fail git clone --recurse-submodules nested clone 2>err &&
|
||||
test_i18ngrep "is inside git dir" err
|
||||
'
|
||||
|
||||
test_expect_success 'submodule git dir nesting detection must work with parallel cloning' '
|
||||
test_must_fail git clone --recurse-submodules --jobs=2 nested clone_parallel 2>err &&
|
||||
cat err &&
|
||||
grep -E "(already exists|is inside git dir|not a git repository)" err &&
|
||||
{
|
||||
test_path_is_missing .git/modules/hippo/HEAD ||
|
||||
test_path_is_missing .git/modules/hippo/hooks/HEAD
|
||||
}
|
||||
'
|
||||
|
||||
test_expect_success 'checkout -f --recurse-submodules must not use a nested gitdir' '
|
||||
git clone nested nested_checkout &&
|
||||
(
|
||||
cd nested_checkout &&
|
||||
git submodule init &&
|
||||
git submodule update thing1 &&
|
||||
mkdir -p .git/modules/hippo/hooks/refs &&
|
||||
mkdir -p .git/modules/hippo/hooks/objects/info &&
|
||||
echo "../../../../objects" >.git/modules/hippo/hooks/objects/info/alternates &&
|
||||
echo "ref: refs/heads/master" >.git/modules/hippo/hooks/HEAD
|
||||
) &&
|
||||
test_must_fail git -C nested_checkout checkout -f --recurse-submodules HEAD 2>err &&
|
||||
cat err &&
|
||||
grep "is inside git dir" err &&
|
||||
test_path_is_missing nested_checkout/thing2/.git
|
||||
'
|
||||
|
||||
test_done
|
||||
|
@ -334,6 +334,7 @@ nr_san_dir_leaks_ () {
|
||||
find "$TEST_RESULTS_SAN_DIR" \
|
||||
-type f \
|
||||
-name "$TEST_RESULTS_SAN_FILE_PFX.*" 2>/dev/null |
|
||||
xargs grep -lv "Unable to get registers from thread" |
|
||||
wc -l
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user