git/t/t2017-checkout-orphan.sh
Ævar Arnfjörð Bjarmason 9081a421a6 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 96ec7b1e70 (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-18 14:32:26 -08:00

130 lines
3.7 KiB
Bash
Executable file

#!/bin/sh
#
# Copyright (c) 2010 Erick Mattos
#
test_description='git checkout --orphan
Main Tests for --orphan functionality.'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
TEST_FILE=foo
test_expect_success 'Setup' '
echo "Initial" >"$TEST_FILE" &&
git add "$TEST_FILE" &&
git commit -m "First Commit" &&
test_tick &&
echo "State 1" >>"$TEST_FILE" &&
git add "$TEST_FILE" &&
test_tick &&
git commit -m "Second Commit"
'
test_expect_success '--orphan creates a new orphan branch from HEAD' '
git checkout --orphan alpha &&
test_must_fail git rev-parse --verify HEAD &&
test "refs/heads/alpha" = "$(git symbolic-ref HEAD)" &&
test_tick &&
git commit -m "Third Commit" &&
test_must_fail git rev-parse --verify HEAD^ &&
git diff-tree --quiet main alpha
'
test_expect_success '--orphan creates a new orphan branch from <start_point>' '
git checkout main &&
git checkout --orphan beta main^ &&
test_must_fail git rev-parse --verify HEAD &&
test "refs/heads/beta" = "$(git symbolic-ref HEAD)" &&
test_tick &&
git commit -m "Fourth Commit" &&
test_must_fail git rev-parse --verify HEAD^ &&
git diff-tree --quiet main^ beta
'
test_expect_success '--orphan must be rejected with -b' '
git checkout main &&
test_must_fail git checkout --orphan new -b newer &&
test refs/heads/main = "$(git symbolic-ref HEAD)"
'
test_expect_success '--orphan must be rejected with -t' '
git checkout main &&
test_must_fail git checkout --orphan new -t main &&
test refs/heads/main = "$(git symbolic-ref HEAD)"
'
test_expect_success '--orphan ignores branch.autosetupmerge' '
git checkout main &&
git config branch.autosetupmerge always &&
git checkout --orphan gamma &&
test -z "$(git config branch.gamma.merge)" &&
test refs/heads/gamma = "$(git symbolic-ref HEAD)" &&
test_must_fail git rev-parse --verify HEAD^
'
test_expect_success '--orphan makes reflog by default' '
git checkout main &&
git config --unset core.logAllRefUpdates &&
git checkout --orphan delta &&
test_must_fail git rev-parse --verify delta@{0} &&
git commit -m Delta &&
git rev-parse --verify delta@{0}
'
test_expect_success REFFILES '--orphan does not make reflog when core.logAllRefUpdates = false' '
git checkout main &&
git config core.logAllRefUpdates false &&
git checkout --orphan epsilon &&
test_must_fail git rev-parse --verify epsilon@{0} &&
git commit -m Epsilon &&
test_must_fail git rev-parse --verify epsilon@{0}
'
test_expect_success '--orphan with -l makes reflog when core.logAllRefUpdates = false' '
git checkout main &&
git checkout -l --orphan zeta &&
test_must_fail git rev-parse --verify zeta@{0} &&
git commit -m Zeta &&
git rev-parse --verify zeta@{0}
'
test_expect_success 'giving up --orphan not committed when -l and core.logAllRefUpdates = false deletes reflog' '
git checkout main &&
git checkout -l --orphan eta &&
test_must_fail git rev-parse --verify eta@{0} &&
git checkout main &&
test_must_fail git rev-parse --verify eta@{0}
'
test_expect_success '--orphan is rejected with an existing name' '
git checkout main &&
test_must_fail git checkout --orphan main &&
test refs/heads/main = "$(git symbolic-ref HEAD)"
'
test_expect_success '--orphan refuses to switch if a merge is needed' '
git checkout main &&
git reset --hard &&
echo local >>"$TEST_FILE" &&
cat "$TEST_FILE" >"$TEST_FILE.saved" &&
test_must_fail git checkout --orphan new main^ &&
test refs/heads/main = "$(git symbolic-ref HEAD)" &&
test_cmp "$TEST_FILE" "$TEST_FILE.saved" &&
git diff-index --quiet --cached HEAD &&
git reset --hard
'
test_expect_success 'cannot --detach on an unborn branch' '
git checkout main &&
git checkout --orphan new &&
test_must_fail git checkout --detach
'
test_done