blob: 2f6515b5f06b271692b40a5725861881c9212896 [file] [edit]
#!/bin/sh
test_description='test receive-report hook'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
. ./test-lib.sh
. "$TEST_DIRECTORY"/t5411/common-functions.sh
URL_PREFIX="\.\."
test_expect_success "setup workbench" '
git init workbench &&
create_commits_in workbench A B
'
test_expect_success "no report hook, push succeeds" '
test_when_finished "rm -rf upstream" &&
test_when_finished "git -C workbench remote remove origin" &&
git init --bare upstream &&
git -C workbench remote add origin ../upstream &&
git -C workbench push origin $A:refs/heads/main &&
git -C workbench push origin $B:refs/heads/main >out 2>&1 &&
make_user_friendly_and_stable_output <out >actual &&
cat >expect <<-\EOF &&
To ../upstream
<COMMIT-A>..<COMMIT-B> <COMMIT-B> -> main
EOF
test_cmp expect actual
'
test_expect_success "passthrough does not alter report" '
test_when_finished "rm -rf upstream" &&
test_when_finished "git -C workbench remote remove origin" &&
git init --bare upstream &&
test_hook -C upstream --setup receive-report <<-\EOF &&
cat
EOF
git -C workbench remote add origin ../upstream &&
git -C workbench push origin $A:refs/heads/main &&
git -C workbench push origin $B:refs/heads/main >out 2>&1 &&
make_user_friendly_and_stable_output <out >actual &&
cat >expect <<-\EOF &&
To ../upstream
<COMMIT-A>..<COMMIT-B> <COMMIT-B> -> main
EOF
test_cmp expect actual
'
test_expect_success "non-zero exit reports as hook failed" '
test_when_finished "rm -rf upstream" &&
test_when_finished "git -C workbench remote remove origin" &&
git init --bare upstream &&
git -C workbench remote add origin ../upstream &&
git -C workbench push origin $A:refs/heads/main &&
test_hook -C upstream --setup receive-report <<-\EOF &&
exit 1
EOF
test_must_fail git -C workbench push origin $B:refs/heads/main >out 2>&1 &&
make_user_friendly_and_stable_output <out >actual &&
cat >expect <<-\EOF &&
To ../upstream
! [remote rejected] <COMMIT-B> -> main (receive-report hook failed)
EOF
test_cmp expect actual
'
test_expect_success "hook is invoked and receives report on stdin" '
test_when_finished "rm -rf upstream" &&
test_when_finished "git -C workbench remote remove origin" &&
git init --bare upstream &&
test_hook -C upstream --setup receive-report <<-EOF &&
tee raw
EOF
git -C workbench remote add origin ../upstream &&
git -C workbench push origin $A:refs/heads/main &&
git -C workbench push origin $B:refs/heads/main >out 2>&1 &&
make_user_friendly_and_stable_output <out >actual &&
cat >expect <<-EOF &&
To ../upstream
<COMMIT-A>..<COMMIT-B> <COMMIT-B> -> main
EOF
test_cmp expect actual &&
test-tool pkt-line unpack <upstream/raw >actual-report &&
cat >expect-report <<-EOF &&
unpack ok
ok refs/heads/main
0000
EOF
test_cmp expect-report actual-report
'
test_expect_success "hook can modify the report sent to client" '
test_when_finished "rm -rf upstream" &&
test_when_finished "git -C workbench remote remove origin" &&
git init --bare upstream &&
git -C workbench remote add origin ../upstream &&
git -C workbench push origin $A:refs/heads/main &&
test_hook -C upstream --setup receive-report <<-\EOF &&
test-tool pkt-line unpack |
sed "s/^ok /ng /" |
test-tool pkt-line pack
EOF
test_must_fail git -C workbench push origin $B:refs/heads/main >out 2>&1 &&
make_user_friendly_and_stable_output <out >actual &&
cat >expect <<-\EOF &&
To ../upstream
! [remote rejected] <COMMIT-B> -> main (failed)
EOF
test_cmp expect actual
'
test_expect_success "hook can modify the unpack status" '
test_when_finished "rm -rf upstream" &&
test_when_finished "git -C workbench remote remove origin" &&
git init --bare upstream &&
git -C workbench remote add origin ../upstream &&
git -C workbench push origin $A:refs/heads/main &&
test_hook -C upstream --setup receive-report <<-\EOF &&
test-tool pkt-line unpack |
sed "s/^unpack ok$/unpack push failed due to server error/" |
test-tool pkt-line pack
EOF
test_must_fail git -C workbench push origin $B:refs/heads/main >out 2>&1 &&
test_grep "error: remote unpack failed: push failed due to server error" out &&
make_user_friendly_and_stable_output <out >actual &&
cat >expect <<-\EOF &&
To ../upstream
<COMMIT-A>..<COMMIT-B> <COMMIT-B> -> main
EOF
test_cmp expect actual
'
test_expect_success "hook can report a custom failure message" '
test_when_finished "rm -rf upstream" &&
test_when_finished "git -C workbench remote remove origin" &&
git init --bare upstream &&
git -C workbench remote add origin ../upstream &&
git -C workbench push origin $A:refs/heads/main &&
test_hook -C upstream --setup receive-report <<-\EOF &&
echo "push rejected: service X is down" >&2
test-tool pkt-line unpack |
sed "s/^ok \(.*\)/ng \1 service-x-is-down/" |
test-tool pkt-line pack |
tee raw
EOF
test_must_fail git -C workbench push origin $B:refs/heads/main >out 2>&1 &&
test_grep "push rejected: service X is down" out &&
test-tool pkt-line unpack <upstream/raw >actual-report &&
cat >expect-report <<-\EOF &&
unpack ok
ng refs/heads/main service-x-is-down
0000
EOF
test_cmp expect-report actual-report
'
test_expect_success "hook stderr with zero exit status code" '
test_when_finished "rm -rf upstream" &&
test_when_finished "git -C workbench remote remove origin" &&
git init --bare upstream &&
git -C workbench remote add origin ../upstream &&
git -C workbench push origin $A:refs/heads/main &&
test_hook -C upstream --setup receive-report <<-\EOF &&
echo "push rejected: service X is down" >&2
tee raw
EOF
git -C workbench push origin $B:refs/heads/main >out 2>&1 &&
test_grep "push rejected: service X is down" out &&
test-tool pkt-line unpack <upstream/raw >actual-report &&
cat >expect-report <<-\EOF &&
unpack ok
ok refs/heads/main
0000
EOF
test_cmp expect-report actual-report
'
test_expect_success "non-zero exit with pre-existing ng from proc-receive" '
test_when_finished "rm -rf upstream" &&
test_when_finished "git -C workbench remote remove origin" &&
git init --bare upstream &&
git -C upstream config receive.procReceiveRefs refs/for &&
git -C workbench remote add origin ../upstream &&
git -C workbench push origin $A:refs/heads/main &&
# Use a proc-receive hook to generate a dynamic error string.
# This is used to capture any leaks stemming from overriding the
# error message via the receive-report.
test_hook -C upstream --setup proc-receive <<-\EOF &&
test-tool proc-receive -r "ng refs/for/main/topic push-rejected-by-service-x"
EOF
test_hook -C upstream --setup receive-report <<-\EOF &&
tee raw
exit 1
EOF
test_must_fail git -C workbench push origin HEAD:refs/for/main/topic >out 2>&1 &&
test_grep "receive-report hook failed" out &&
test-tool pkt-line unpack <upstream/raw >actual-report &&
cat >expect-report <<-\EOF &&
unpack ok
ng refs/for/main/topic push-rejected-by-service-x
0000
EOF
test_cmp expect-report actual-report
'
test_expect_success "hook stderr is relayed to client via sideband" '
test_when_finished "rm -rf upstream" &&
test_when_finished "git -C workbench remote remove origin" &&
git init --bare upstream &&
git -C workbench remote add origin ../upstream &&
git -C workbench push origin $A:refs/heads/main &&
test_hook -C upstream --setup receive-report <<-\EOF &&
echo "hook-stderr-message" >&2
exit 1
EOF
test_must_fail git -C workbench push origin $B:refs/heads/main >out 2>&1 &&
test_grep "remote: hook-stderr-message" out
'
test_done