git/t/t2021-checkout-overwrite.sh

84 lines
1.8 KiB
Bash
Raw Normal View History

#!/bin/sh
test_description='checkout must not overwrite an untracked objects'
checkout: fix "branch info" memory leaks The "checkout" command is one of the main sources of leaks in the test suite, let's fix the common ones by not leaking from the "struct branch_info". Doing this is rather straightforward, albeit verbose, we need to xstrdup() constant strings going into the struct, and free() the ones we clobber as we go along. This also means that we can delete previous partial leak fixes in this area, i.e. the "path_to_free" accounting added by 96ec7b1e708 (Convert resolve_ref+xstrdup to new resolve_refdup function, 2011-12-13). There was some discussion about whether "we should retain the "const char *" here and cast at free() time, or have it be a "char *". Since this is not a public API with any sort of API boundary let's use "char *", as is already being done for the "refname" member of the same struct. The tests to mark as passing were found with: rm .prove; GIT_SKIP_TESTS=t0027 prove -j8 --state=save t[0-9]*.sh :: --immediate # apply & compile this change prove -j8 --state=failed :: --immediate I.e. the ones that were newly passing when the --state=failed command was run. I left out "t3040-subprojects-basic.sh" and "t4131-apply-fake-ancestor.sh" to to optimization-level related differences similar to the ones noted in[1], except that these would be something the current 'linux-leaks' job would run into. 1. https://lore.kernel.org/git/cover-v3-0.6-00000000000-20211022T175227Z-avarab@gmail.com/ Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2021-11-16 18:27:38 +00:00
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
mkdir -p a/b/c &&
>a/b/c/d &&
git add -A &&
git commit -m base &&
git tag start
'
test_expect_success 'create a commit where dir a/b changed to file' '
git checkout -b file &&
rm -rf a/b &&
>a/b &&
git add -A &&
git commit -m "dir to file"
'
test_expect_success 'checkout commit with dir must not remove untracked a/b' '
git rm --cached a/b &&
git commit -m "un-track the file" &&
test_must_fail git checkout start &&
test -f a/b
'
test_expect_success 'create a commit where dir a/b changed to symlink' '
rm -rf a/b && # cleanup if previous test failed
git checkout -f -b symlink start &&
rm -rf a/b &&
git add -A &&
test_ln_s_add foo a/b &&
git commit -m "dir to symlink"
'
test_expect_success 'checkout commit with dir must not remove untracked a/b' '
git rm --cached a/b &&
git commit -m "un-track the symlink" &&
test_must_fail git checkout start
'
test_expect_success SYMLINKS 'the symlink remained' '
test -h a/b
'
test_expect_success 'cleanup after previous symlink tests' '
rm a/b
'
checkout: don't follow symlinks when removing entries At 1d718a5108 ("do not overwrite untracked symlinks", 2011-02-20), symlink.c:check_leading_path() started returning different codes for FL_ENOENT and FL_SYMLINK. But one of its callers, unlink_entry(), was not adjusted for this change, so it started to follow symlinks on the leading path of to-be-removed entries. Fix that and add a regression test. Note that since 1d718a5108 check_leading_path() no longer differentiates the case where it found a symlink in the path's leading components from the cases where it found a regular file or failed to lstat() the component. So, a side effect of this current patch is that unlink_entry() now returns early in all of these three cases. And because we no longer try to unlink such paths, we also don't get the warning from remove_or_warn(). For the regular file and symlink cases, it's questionable whether the warning was useful in the first place: unlink_entry() removes tracked paths that should no longer be present in the state we are checking out to. If the path had its leading dir replaced by another file, it means that the basename already doesn't exist, so there is no need for a warning. Sure, we are leaving a regular file or symlink behind at the path's dirname, but this file is either untracked now (so again, no need to warn), or it will be replaced by a tracked file during the next phase of this checkout operation. As for failing to lstat() one of the leading components, the basename might still exist only we cannot unlink it (e.g. due to the lack of the required permissions). Since the user expect it to be removed (especially with checkout's --no-overlay option), add back the warning in this more relevant case. Signed-off-by: Matheus Tavares <matheus.bernardino@usp.br> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2021-03-18 18:43:47 +00:00
test_expect_success SYMLINKS 'checkout -f must not follow symlinks when removing entries' '
git checkout -f start &&
mkdir dir &&
>dir/f &&
git add dir/f &&
git commit -m "add dir/f" &&
mv dir untracked &&
ln -s untracked dir &&
git checkout -f HEAD~ &&
test_path_is_file untracked/f
'
test_expect_success 'checkout --overwrite-ignore should succeed if only ignored files in the way' '
git checkout -b df_conflict &&
test_commit contents some_dir &&
git checkout start &&
mkdir some_dir &&
echo autogenerated information >some_dir/ignore &&
echo ignore >.git/info/exclude &&
git checkout --overwrite-ignore df_conflict &&
test_path_is_file some_dir
'
test_done