
The test case "fetch porcelain output" checks output of the fetch command. The error output must be empty with the follow assertion: test_must_be_empty stderr But this assertion fails if using atomic fetch. Refactor this test case to use different fetch options by splitting it into three test cases. 1. "setup for fetch porcelain output". 2. "fetch porcelain output": for non-atomic fetch. 3. "fetch porcelain output (atomic)": for atomic fetch. Add new command "test_commit ..." in the first test case, so that if we run these test cases individually (--run=4-6), "git rev-parse HEAD~" command will work properly. Run the above test cases, we can find that one test case has a known breakage, as shown below: ok 4 - setup for fetch porcelain output ok 5 - fetch porcelain output # TODO known breakage vanished not ok 6 - fetch porcelain output (atomic) # TODO known breakage The failed test case has an error message with only the error prompt but no message body, as follows: 'stderr' is not empty, it contains: error: In a later commit, we will fix this issue. Helped-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Jiang Xin <zhiyou.jx@alibaba-inc.com> Acked-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
305 lines
9.1 KiB
Bash
Executable File
305 lines
9.1 KiB
Bash
Executable File
#!/bin/sh
|
|
|
|
test_description='git fetch output format'
|
|
|
|
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
|
|
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
|
|
|
|
. ./test-lib.sh
|
|
|
|
test_expect_success 'fetch with invalid output format configuration' '
|
|
test_when_finished "rm -rf clone" &&
|
|
git clone . clone &&
|
|
|
|
test_must_fail git -C clone -c fetch.output fetch origin 2>actual.err &&
|
|
cat >expect <<-EOF &&
|
|
error: missing value for ${SQ}fetch.output${SQ}
|
|
fatal: unable to parse ${SQ}fetch.output${SQ} from command-line config
|
|
EOF
|
|
test_cmp expect actual.err &&
|
|
|
|
test_must_fail git -C clone -c fetch.output= fetch origin 2>actual.err &&
|
|
cat >expect <<-EOF &&
|
|
fatal: invalid value for ${SQ}fetch.output${SQ}: ${SQ}${SQ}
|
|
EOF
|
|
test_cmp expect actual.err &&
|
|
|
|
test_must_fail git -C clone -c fetch.output=garbage fetch origin 2>actual.err &&
|
|
cat >expect <<-EOF &&
|
|
fatal: invalid value for ${SQ}fetch.output${SQ}: ${SQ}garbage${SQ}
|
|
EOF
|
|
test_cmp expect actual.err
|
|
'
|
|
|
|
test_expect_success 'fetch aligned output' '
|
|
git clone . full-output &&
|
|
test_commit looooooooooooong-tag &&
|
|
(
|
|
cd full-output &&
|
|
git -c fetch.output=full fetch origin >actual 2>&1 &&
|
|
grep -e "->" actual | cut -c 22- >../actual
|
|
) &&
|
|
cat >expect <<-\EOF &&
|
|
main -> origin/main
|
|
looooooooooooong-tag -> looooooooooooong-tag
|
|
EOF
|
|
test_cmp expect actual
|
|
'
|
|
|
|
test_expect_success 'fetch compact output' '
|
|
git clone . compact &&
|
|
test_commit extraaa &&
|
|
(
|
|
cd compact &&
|
|
git -c fetch.output=compact fetch origin >actual 2>&1 &&
|
|
grep -e "->" actual | cut -c 22- >../actual
|
|
) &&
|
|
cat >expect <<-\EOF &&
|
|
main -> origin/*
|
|
extraaa -> *
|
|
EOF
|
|
test_cmp expect actual
|
|
'
|
|
|
|
test_expect_success 'setup for fetch porcelain output' '
|
|
# Set up a bunch of references that we can use to demonstrate different
|
|
# kinds of flag symbols in the output format.
|
|
test_commit commit-for-porcelain-output &&
|
|
MAIN_OLD=$(git rev-parse HEAD) &&
|
|
git branch "fast-forward" &&
|
|
git branch "deleted-branch" &&
|
|
git checkout -b force-updated &&
|
|
test_commit --no-tag force-update-old &&
|
|
FORCE_UPDATED_OLD=$(git rev-parse HEAD) &&
|
|
git checkout main &&
|
|
|
|
# Backup to preseed.git
|
|
git clone --mirror . preseed.git &&
|
|
|
|
# Continue changing our local references.
|
|
git branch new-branch &&
|
|
git branch -d deleted-branch &&
|
|
git checkout fast-forward &&
|
|
test_commit --no-tag fast-forward-new &&
|
|
FAST_FORWARD_NEW=$(git rev-parse HEAD) &&
|
|
git checkout force-updated &&
|
|
git reset --hard HEAD~ &&
|
|
test_commit --no-tag force-update-new &&
|
|
FORCE_UPDATED_NEW=$(git rev-parse HEAD)
|
|
'
|
|
|
|
for opt in "" "--atomic"
|
|
do
|
|
test_expect_failure "fetch porcelain output ${opt:+(atomic)}" '
|
|
test_when_finished "rm -rf porcelain" &&
|
|
|
|
# Clone and pre-seed the repositories. We fetch references into two
|
|
# namespaces so that we can test that rejected and force-updated
|
|
# references are reported properly.
|
|
refspecs="refs/heads/*:refs/unforced/* +refs/heads/*:refs/forced/*" &&
|
|
git clone preseed.git porcelain &&
|
|
git -C porcelain fetch origin $opt $refspecs &&
|
|
|
|
cat >expect <<-EOF &&
|
|
- $MAIN_OLD $ZERO_OID refs/forced/deleted-branch
|
|
- $MAIN_OLD $ZERO_OID refs/unforced/deleted-branch
|
|
$MAIN_OLD $FAST_FORWARD_NEW refs/unforced/fast-forward
|
|
! $FORCE_UPDATED_OLD $FORCE_UPDATED_NEW refs/unforced/force-updated
|
|
* $ZERO_OID $MAIN_OLD refs/unforced/new-branch
|
|
$MAIN_OLD $FAST_FORWARD_NEW refs/forced/fast-forward
|
|
+ $FORCE_UPDATED_OLD $FORCE_UPDATED_NEW refs/forced/force-updated
|
|
* $ZERO_OID $MAIN_OLD refs/forced/new-branch
|
|
$MAIN_OLD $FAST_FORWARD_NEW refs/remotes/origin/fast-forward
|
|
+ $FORCE_UPDATED_OLD $FORCE_UPDATED_NEW refs/remotes/origin/force-updated
|
|
* $ZERO_OID $MAIN_OLD refs/remotes/origin/new-branch
|
|
EOF
|
|
|
|
# Change the URL of the repository to fetch different references.
|
|
git -C porcelain remote set-url origin .. &&
|
|
|
|
# Execute a dry-run fetch first. We do this to assert that the dry-run
|
|
# and non-dry-run fetches produces the same output. Execution of the
|
|
# fetch is expected to fail as we have a rejected reference update.
|
|
test_must_fail git -C porcelain fetch $opt \
|
|
--porcelain --dry-run --prune origin $refspecs >actual &&
|
|
test_cmp expect actual &&
|
|
|
|
# And now we perform a non-dry-run fetch.
|
|
test_must_fail git -C porcelain fetch $opt \
|
|
--porcelain --prune origin $refspecs >actual 2>stderr &&
|
|
test_cmp expect actual &&
|
|
test_must_be_empty stderr
|
|
'
|
|
done
|
|
|
|
test_expect_success 'fetch porcelain with multiple remotes' '
|
|
test_when_finished "rm -rf porcelain" &&
|
|
|
|
git switch --create multiple-remotes &&
|
|
git clone . porcelain &&
|
|
git -C porcelain remote add second-remote "$PWD" &&
|
|
git -C porcelain fetch second-remote &&
|
|
|
|
test_commit --no-tag multi-commit &&
|
|
old_commit=$(git rev-parse HEAD~) &&
|
|
new_commit=$(git rev-parse HEAD) &&
|
|
|
|
cat >expect <<-EOF &&
|
|
$old_commit $new_commit refs/remotes/origin/multiple-remotes
|
|
$old_commit $new_commit refs/remotes/second-remote/multiple-remotes
|
|
EOF
|
|
|
|
git -C porcelain fetch --porcelain --all >actual 2>stderr &&
|
|
test_cmp expect actual &&
|
|
test_must_be_empty stderr
|
|
'
|
|
|
|
test_expect_success 'fetch porcelain refuses to work with submodules' '
|
|
test_when_finished "rm -rf porcelain" &&
|
|
|
|
cat >expect <<-EOF &&
|
|
fatal: options ${SQ}--porcelain${SQ} and ${SQ}--recurse-submodules${SQ} cannot be used together
|
|
EOF
|
|
|
|
git init porcelain &&
|
|
test_must_fail git -C porcelain fetch --porcelain --recurse-submodules=yes 2>stderr &&
|
|
test_cmp expect stderr &&
|
|
|
|
test_must_fail git -C porcelain fetch --porcelain --recurse-submodules=on-demand 2>stderr &&
|
|
test_cmp expect stderr
|
|
'
|
|
|
|
test_expect_success 'fetch porcelain overrides fetch.output config' '
|
|
test_when_finished "rm -rf porcelain" &&
|
|
|
|
git switch --create config-override &&
|
|
git clone . porcelain &&
|
|
test_commit new-commit &&
|
|
old_commit=$(git rev-parse HEAD~) &&
|
|
new_commit=$(git rev-parse HEAD) &&
|
|
|
|
cat >expect <<-EOF &&
|
|
$old_commit $new_commit refs/remotes/origin/config-override
|
|
* $ZERO_OID $new_commit refs/tags/new-commit
|
|
EOF
|
|
|
|
git -C porcelain -c fetch.output=compact fetch --porcelain >stdout 2>stderr &&
|
|
test_must_be_empty stderr &&
|
|
test_cmp expect stdout
|
|
'
|
|
|
|
test_expect_success 'fetch --no-porcelain overrides previous --porcelain' '
|
|
test_when_finished "rm -rf no-porcelain" &&
|
|
|
|
git switch --create no-porcelain &&
|
|
git clone . no-porcelain &&
|
|
test_commit --no-tag no-porcelain &&
|
|
old_commit=$(git rev-parse --short HEAD~) &&
|
|
new_commit=$(git rev-parse --short HEAD) &&
|
|
|
|
cat >expect <<-EOF &&
|
|
From $(test-tool path-utils real_path .)/.
|
|
$old_commit..$new_commit no-porcelain -> origin/no-porcelain
|
|
EOF
|
|
|
|
git -C no-porcelain fetch --porcelain --no-porcelain >stdout 2>stderr &&
|
|
test_cmp expect stderr &&
|
|
test_must_be_empty stdout
|
|
'
|
|
|
|
test_expect_success 'fetch output with HEAD' '
|
|
test_when_finished "rm -rf head" &&
|
|
git clone . head &&
|
|
|
|
git -C head fetch --dry-run origin HEAD >actual.out 2>actual.err &&
|
|
cat >expect <<-EOF &&
|
|
From $(test-tool path-utils real_path .)/.
|
|
* branch HEAD -> FETCH_HEAD
|
|
EOF
|
|
test_must_be_empty actual.out &&
|
|
test_cmp expect actual.err &&
|
|
|
|
git -C head fetch origin HEAD >actual.out 2>actual.err &&
|
|
test_must_be_empty actual.out &&
|
|
test_cmp expect actual.err &&
|
|
|
|
git -C head fetch --dry-run origin HEAD:foo >actual.out 2>actual.err &&
|
|
cat >expect <<-EOF &&
|
|
From $(test-tool path-utils real_path .)/.
|
|
* [new ref] HEAD -> foo
|
|
EOF
|
|
test_must_be_empty actual.out &&
|
|
test_cmp expect actual.err &&
|
|
|
|
git -C head fetch origin HEAD:foo >actual.out 2>actual.err &&
|
|
test_must_be_empty actual.out &&
|
|
test_cmp expect actual.err
|
|
'
|
|
|
|
test_expect_success 'fetch porcelain output with HEAD' '
|
|
test_when_finished "rm -rf head" &&
|
|
git clone . head &&
|
|
COMMIT_ID=$(git rev-parse HEAD) &&
|
|
|
|
git -C head fetch --porcelain --dry-run origin HEAD >actual &&
|
|
cat >expect <<-EOF &&
|
|
* $ZERO_OID $COMMIT_ID FETCH_HEAD
|
|
EOF
|
|
test_cmp expect actual &&
|
|
|
|
git -C head fetch --porcelain origin HEAD >actual &&
|
|
test_cmp expect actual &&
|
|
|
|
git -C head fetch --porcelain --dry-run origin HEAD:foo >actual &&
|
|
cat >expect <<-EOF &&
|
|
* $ZERO_OID $COMMIT_ID refs/heads/foo
|
|
EOF
|
|
test_cmp expect actual &&
|
|
|
|
git -C head fetch --porcelain origin HEAD:foo >actual &&
|
|
test_cmp expect actual
|
|
'
|
|
|
|
test_expect_success 'fetch output with object ID' '
|
|
test_when_finished "rm -rf object-id" &&
|
|
git clone . object-id &&
|
|
commit=$(git rev-parse HEAD) &&
|
|
|
|
git -C object-id fetch --dry-run origin $commit:object-id >actual.out 2>actual.err &&
|
|
cat >expect <<-EOF &&
|
|
From $(test-tool path-utils real_path .)/.
|
|
* [new ref] $commit -> object-id
|
|
EOF
|
|
test_must_be_empty actual.out &&
|
|
test_cmp expect actual.err &&
|
|
|
|
git -C object-id fetch origin $commit:object-id >actual.out 2>actual.err &&
|
|
test_must_be_empty actual.out &&
|
|
test_cmp expect actual.err
|
|
'
|
|
|
|
test_expect_success '--no-show-forced-updates' '
|
|
mkdir forced-updates &&
|
|
(
|
|
cd forced-updates &&
|
|
git init &&
|
|
test_commit 1 &&
|
|
test_commit 2
|
|
) &&
|
|
git clone forced-updates forced-update-clone &&
|
|
git clone forced-updates no-forced-update-clone &&
|
|
git -C forced-updates reset --hard HEAD~1 &&
|
|
(
|
|
cd forced-update-clone &&
|
|
git fetch --show-forced-updates origin 2>output &&
|
|
test_i18ngrep "(forced update)" output
|
|
) &&
|
|
(
|
|
cd no-forced-update-clone &&
|
|
git fetch --no-show-forced-updates origin 2>output &&
|
|
test_i18ngrep ! "(forced update)" output
|
|
)
|
|
'
|
|
|
|
test_done
|