
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>
70 lines
1.4 KiB
Bash
Executable File
70 lines
1.4 KiB
Bash
Executable File
#!/bin/sh
|
|
|
|
test_description='checkout must not overwrite an untracked objects'
|
|
|
|
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_when_finished "rm a/b" &&
|
|
test -h a/b
|
|
'
|
|
|
|
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_done
|