From patchwork Sat Apr 18 16:03:27 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiang Xin X-Patchwork-Id: 11496629 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 89C23912 for ; Sat, 18 Apr 2020 16:03:53 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 5E63C2223D for ; Sat, 18 Apr 2020 16:03:53 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="eBkhW5ug" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726814AbgDRQDw (ORCPT ); Sat, 18 Apr 2020 12:03:52 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45406 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1726471AbgDRQDu (ORCPT ); Sat, 18 Apr 2020 12:03:50 -0400 Received: from mail-pl1-x643.google.com (mail-pl1-x643.google.com [IPv6:2607:f8b0:4864:20::643]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DCBAAC061A0F for ; Sat, 18 Apr 2020 09:03:49 -0700 (PDT) Received: by mail-pl1-x643.google.com with SMTP id t16so2197307plo.7 for ; Sat, 18 Apr 2020 09:03:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=/Cp0ccPfHDzAg8p8LnLNq9iGeLDeMxDzqQ8ORc3Rx9Y=; b=eBkhW5ug2BLbHxLxBTctoL3eoAsSjiSCVA5a8cpKuhNBup7TrojbcQ1GQ5IA13eRt/ xNYLa6LN+eq/+g9rOs3BUSo6rv0Vu8Y55VI3El6odq0KPVpAPbhsjSCaXtOyj/HuaY0M proOfOGRA5LOpx1CGH2eIgX9UFTlQQTbNK+ps52wEEi8/NMyrWTkF3Gcwqg7inaX2Xv8 9lNb1fsXQ3pqBDt4JiRLEs2nG5z6jpl9gzW5o0VR7IZP2Kr9M4gkoncHuDU9bCmiCZUT IKgxF5r3e1DAdBah4OMZlpEfueizn72odY3+PXdL+zc/4XVyLo/7aw7yfVtZ18btOuiK kS7Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=/Cp0ccPfHDzAg8p8LnLNq9iGeLDeMxDzqQ8ORc3Rx9Y=; b=HNY1eZV1jQH8N7ju8FiC2aI2ufAMkgN43/bqROFQwRO+zFcGInLxxtwNpS63v2rCRO Kaza4QJqznLX6bZ08nhHtqyqxaX9s5oLn9hIifIc71YuINUgpNFxsH+wzORjdYmnr2hw 6A4tV5Mpk/dJsY8RAB6b+D2EAqKRPVxZ3F9b+2U4WcXXggzUeDWQZen/okIHNf6lv2ez KsJsMFTy6zZd4ttDhOhX/1vw9jkNXW25Qzdc/VyKzkl0HitkdS5347wYv6IrA8VqL+7M yH0Av9Bs/9FEakof1PMnNhAxoIM7iBI28W0xTFng+LIwQJ5WHYHLifzRSU29kO5q/lKz rvTg== X-Gm-Message-State: AGi0PuYhbXbnfvXzLNYZh1hmG3WEqXpA0y8DiNbWeEU/aZprUHamh02q Hx2Ombr1q9RTo/SfMn+Q1MJBcHt4 X-Google-Smtp-Source: APiQypII7jJz/65h+9i1KVxzQ4Aoc1puGQCZqTBhzJ9H7FvkmObNLxdoN59J5XuWDRsC2LOibmphgw== X-Received: by 2002:a17:90a:de0e:: with SMTP id m14mr11115780pjv.54.1587225829115; Sat, 18 Apr 2020 09:03:49 -0700 (PDT) Received: from tigtog.localdomain.localdomain ([144.34.163.219]) by smtp.gmail.com with ESMTPSA id i187sm22461649pfg.33.2020.04.18.09.03.48 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Sat, 18 Apr 2020 09:03:48 -0700 (PDT) From: Jiang Xin To: Junio C Hamano , Git List Cc: Jiang Xin Subject: [PATCH v13 1/8] transport: not report a non-head push as a branch Date: Sat, 18 Apr 2020 12:03:27 -0400 Message-Id: <20200418160334.15631-2-worldhello.net@gmail.com> X-Mailer: git-send-email 2.26.0.rc0 In-Reply-To: <20200414123257.27449-1-worldhello.net@gmail.com> References: <20200414123257.27449-1-worldhello.net@gmail.com> MIME-Version: 1.0 Sender: git-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Jiang Xin When pushing a new reference (not a head or tag), report it as a new reference instead of a new branch. Signed-off-by: Jiang Xin --- t/t5411-proc-receive-hook.sh | 105 ++++++++++++++++++ t/t5411/common-functions.sh | 56 ++++++++++ t/t5411/test-0000-standard-git-push.sh | 84 ++++++++++++++ .../test-0001-standard-git-push--porcelain.sh | 87 +++++++++++++++ t/t5411/test-0002-pre-receive-declined.sh | 33 ++++++ ...st-0003-pre-receive-declined--porcelain.sh | 34 ++++++ t/t5516-fetch-push.sh | 2 +- transport.c | 9 +- 8 files changed, 406 insertions(+), 4 deletions(-) create mode 100755 t/t5411-proc-receive-hook.sh create mode 100644 t/t5411/common-functions.sh create mode 100644 t/t5411/test-0000-standard-git-push.sh create mode 100644 t/t5411/test-0001-standard-git-push--porcelain.sh create mode 100644 t/t5411/test-0002-pre-receive-declined.sh create mode 100644 t/t5411/test-0003-pre-receive-declined--porcelain.sh diff --git a/t/t5411-proc-receive-hook.sh b/t/t5411-proc-receive-hook.sh new file mode 100755 index 0000000000..33d4e019ae --- /dev/null +++ b/t/t5411-proc-receive-hook.sh @@ -0,0 +1,105 @@ +#!/bin/sh +# +# Copyright (c) 2020 Jiang Xin +# + +test_description='Test proc-receive hook' + +. ./test-lib.sh + +. "$TEST_DIRECTORY"/t5411/common-functions.sh + +setup_upstream_and_workbench () { + # Refs of upstream : master(A) + # Refs of workbench: master(A) tags/v123 + test_expect_success "setup upstream and workbench" ' + rm -rf upstream.git && + rm -rf workbench && + git init --bare upstream.git && + git init workbench && + create_commits_in workbench A B && + ( + cd workbench && + # Try to make a stable fixed width for abbreviated commit ID, + # this fixed-width oid will be replaced with "". + git config core.abbrev 7 && + git remote add origin ../upstream.git && + git update-ref refs/heads/master $A && + git tag -m "v123" v123 $A && + git push origin $A:refs/heads/master + ) && + TAG=$(git -C workbench rev-parse v123) && + + # setup pre-receive hook + write_script upstream.git/hooks/pre-receive <<-\EOF && + exec >&2 + echo "# pre-receive hook" + while read old new ref + do + echo "pre-receive< $old $new $ref" + done + EOF + + # setup post-receive hook + write_script upstream.git/hooks/post-receive <<-\EOF && + exec >&2 + echo "# post-receive hook" + while read old new ref + do + echo "post-receive< $old $new $ref" + done + EOF + + upstream=upstream.git + ' +} + +run_proc_receive_hook_test() { + case $1 in + http) + PROTOCOL="HTTP protocol" + URL_PREFIX="http://.*" + ;; + file | local) + PROTOCOL="builtin protocol" + URL_PREFIX="\.\." + ;; + esac + + # Include test cases for both file and HTTP protocol + for t in "$TEST_DIRECTORY"/t5411/test-*.sh + do + . "$t" + done +} + +# Initialize the upstream repository and local workbench. +setup_upstream_and_workbench + +# Run test cases for 'proc-receive' hook on local file protocol. +run_proc_receive_hook_test local + +ROOT_PATH="$PWD" +. "$TEST_DIRECTORY"/lib-gpg.sh +. "$TEST_DIRECTORY"/lib-httpd.sh +. "$TEST_DIRECTORY"/lib-terminal.sh +start_httpd + +# Re-initialize the upstream repository and local workbench. +setup_upstream_and_workbench + +# Refs of upstream : master(A) +# Refs of workbench: master(A) tags/v123 +test_expect_success "setup for HTTP protocol" ' + git -C upstream.git config http.receivepack true && + upstream="$HTTPD_DOCUMENT_ROOT_PATH/upstream.git" && + mv upstream.git "$upstream" && + git -C workbench remote set-url origin $HTTPD_URL/smart/upstream.git +' + +setup_askpass_helper + +# Run test cases for 'proc-receive' hook on HTTP protocol. +run_proc_receive_hook_test http + +test_done diff --git a/t/t5411/common-functions.sh b/t/t5411/common-functions.sh new file mode 100644 index 0000000000..6580bebd8e --- /dev/null +++ b/t/t5411/common-functions.sh @@ -0,0 +1,56 @@ +# Create commits in and assign each commit's oid to shell variables +# given in the arguments (A, B, and C). E.g.: +# +# create_commits_in A B C +# +# NOTE: Never calling this function from a subshell since variable +# assignments will disappear when subshell exits. +create_commits_in () { + repo="$1" && + if ! parent=$(git -C "$repo" rev-parse HEAD^{} --) + then + parent= + fi && + T=$(git -C "$repo" write-tree) && + shift && + while test $# -gt 0 + do + name=$1 && + test_tick && + if test -z "$parent" + then + oid=$(echo $name | git -C "$repo" commit-tree $T) + else + oid=$(echo $name | git -C "$repo" commit-tree -p $parent $T) + fi && + eval $name=$oid && + parent=$oid && + shift || + return 1 + done && + git -C "$repo" update-ref refs/heads/master $oid +} + +# Format the output of git-push, git-show-ref and other commands to make a +# user-friendly and stable text. We can easily prepare the expect text +# without having to worry about future changes of the commit ID and spaces +# of the output. Single quotes are replaced with double quotes, because +# it is boring to prepare unquoted single quotes in expect text. We also +# remove some locale error messages, which break test if we turn on +# `GIT_TEST_GETTEXT_POISON=true` in order to test unintentional translations +# on plumbing commands. +make_user_friendly_and_stable_output () { + sed \ + -e "s/ *\$//" \ + -e "s/ */ /g" \ + -e "s/'/\"/g" \ + -e "s/ / /g" \ + -e "s/$A//g" \ + -e "s/$B//g" \ + -e "s/$TAG//g" \ + -e "s/$ZERO_OID//g" \ + -e "s/$(echo $A | cut -c1-7)[0-9a-f]*//g" \ + -e "s/$(echo $B | cut -c1-7)[0-9a-f]*//g" \ + -e "s#To $URL_PREFIX/upstream.git#To #" \ + -e "/^error: / d" +} diff --git a/t/t5411/test-0000-standard-git-push.sh b/t/t5411/test-0000-standard-git-push.sh new file mode 100644 index 0000000000..2ee35d17b1 --- /dev/null +++ b/t/t5411/test-0000-standard-git-push.sh @@ -0,0 +1,84 @@ +# Refs of upstream : master(A) +# Refs of workbench: master(A) tags/v123 +# git-push : master(B) next(A) +test_expect_success "non-force git-push ($PROTOCOL)" ' + git -C workbench push origin \ + $B:refs/heads/master \ + HEAD:refs/heads/next \ + >out 2>&1 && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + remote: # pre-receive hook + remote: pre-receive< refs/heads/master + remote: pre-receive< refs/heads/next + remote: # post-receive hook + remote: post-receive< refs/heads/master + remote: post-receive< refs/heads/next + To + .. -> master + * [new branch] HEAD -> next + EOF + test_cmp expect actual && + git -C "$upstream" show-ref >out && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + refs/heads/master + refs/heads/next + EOF + test_cmp expect actual +' + +# Refs of upstream : master(B) next(A) +# Refs of workbench: master(A) tags/v123 +# git-push -f : master(A) NULL tags/v123 refs/review/master/topic(A) a/b/c(A) +test_expect_success "force git-push ($PROTOCOL)" ' + git -C workbench push -f origin \ + refs/tags/v123 \ + :refs/heads/next \ + HEAD:refs/heads/master \ + HEAD:refs/review/master/topic \ + HEAD:refs/heads/a/b/c \ + >out 2>&1 && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + remote: # pre-receive hook + remote: pre-receive< refs/heads/master + remote: pre-receive< refs/heads/next + remote: pre-receive< refs/tags/v123 + remote: pre-receive< refs/review/master/topic + remote: pre-receive< refs/heads/a/b/c + remote: # post-receive hook + remote: post-receive< refs/heads/master + remote: post-receive< refs/heads/next + remote: post-receive< refs/tags/v123 + remote: post-receive< refs/review/master/topic + remote: post-receive< refs/heads/a/b/c + To + + ... HEAD -> master (forced update) + - [deleted] next + * [new tag] v123 -> v123 + * [new reference] HEAD -> refs/review/master/topic + * [new branch] HEAD -> a/b/c + EOF + test_cmp expect actual && + git -C "$upstream" show-ref >out && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + refs/heads/a/b/c + refs/heads/master + refs/review/master/topic + refs/tags/v123 + EOF + test_cmp expect actual +' + +# Refs of upstream : master(A) tags/v123 refs/review/master/topic(A) a/b/c(A) +# Refs of workbench: master(A) tags/v123 +test_expect_success "cleanup ($PROTOCOL)" ' + ( + cd "$upstream" && + git update-ref -d refs/review/master/topic && + git update-ref -d refs/tags/v123 && + git update-ref -d refs/heads/a/b/c + ) +' diff --git a/t/t5411/test-0001-standard-git-push--porcelain.sh b/t/t5411/test-0001-standard-git-push--porcelain.sh new file mode 100644 index 0000000000..6b7ad15543 --- /dev/null +++ b/t/t5411/test-0001-standard-git-push--porcelain.sh @@ -0,0 +1,87 @@ +# Refs of upstream : master(A) +# Refs of workbench: master(A) tags/v123 +# git-push : master(B) next(A) +test_expect_success "non-force git-push (--porcelain, $PROTOCOL)" ' + git -C workbench push --porcelain origin \ + $B:refs/heads/master \ + HEAD:refs/heads/next \ + >out 2>&1 && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + remote: # pre-receive hook + remote: pre-receive< refs/heads/master + remote: pre-receive< refs/heads/next + remote: # post-receive hook + remote: post-receive< refs/heads/master + remote: post-receive< refs/heads/next + To + :refs/heads/master .. + * HEAD:refs/heads/next [new branch] + Done + EOF + test_cmp expect actual && + git -C "$upstream" show-ref >out && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + refs/heads/master + refs/heads/next + EOF + test_cmp expect actual +' + +# Refs of upstream : master(B) next(A) +# Refs of workbench: master(A) tags/v123 +# git-push -f : master(A) NULL tags/v123 refs/review/master/topic(A) a/b/c(A) +test_expect_success "force git-push (--porcelain, $PROTOCOL)" ' + git -C workbench push --porcelain -f origin \ + refs/tags/v123 \ + :refs/heads/next \ + HEAD:refs/heads/master \ + HEAD:refs/review/master/topic \ + HEAD:refs/heads/a/b/c \ + >out 2>&1 && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + remote: # pre-receive hook + remote: pre-receive< refs/heads/master + remote: pre-receive< refs/heads/next + remote: pre-receive< refs/tags/v123 + remote: pre-receive< refs/review/master/topic + remote: pre-receive< refs/heads/a/b/c + remote: # post-receive hook + remote: post-receive< refs/heads/master + remote: post-receive< refs/heads/next + remote: post-receive< refs/tags/v123 + remote: post-receive< refs/review/master/topic + remote: post-receive< refs/heads/a/b/c + To + + HEAD:refs/heads/master ... (forced update) + - :refs/heads/next [deleted] + * refs/tags/v123:refs/tags/v123 [new tag] + * HEAD:refs/review/master/topic [new reference] + * HEAD:refs/heads/a/b/c [new branch] + Done + EOF + test_cmp expect actual && + git -C "$upstream" show-ref >out && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + refs/heads/a/b/c + refs/heads/master + refs/review/master/topic + refs/tags/v123 + EOF + test_cmp expect actual +' + +# Refs of upstream : master(A) tags/v123 refs/review/master/topic(A) a/b/c(A) +# Refs of workbench: master(A) tags/v123 +test_expect_success "cleanup ($PROTOCOL)" ' + ( + cd "$upstream" && + git update-ref -d refs/review/master/topic && + git update-ref -d refs/tags/v123 && + git update-ref -d refs/heads/a/b/c + ) +' + diff --git a/t/t5411/test-0002-pre-receive-declined.sh b/t/t5411/test-0002-pre-receive-declined.sh new file mode 100644 index 0000000000..71203fbfd5 --- /dev/null +++ b/t/t5411/test-0002-pre-receive-declined.sh @@ -0,0 +1,33 @@ +test_expect_success "setup pre-receive hook (declined, $PROTOCOL)" ' + mv "$upstream/hooks/pre-receive" "$upstream/hooks/pre-receive.ok" && + write_script "$upstream/hooks/pre-receive" <<-EOF + exit 1 + EOF +' + +# Refs of upstream : master(A) +# Refs of workbench: master(A) tags/v123 +# git-push : master(B) next(A) +test_expect_success "git-push is declined ($PROTOCOL)" ' + test_must_fail git -C workbench push origin \ + $B:refs/heads/master \ + HEAD:refs/heads/next \ + >out 2>&1 && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + To + ! [remote rejected] -> master (pre-receive hook declined) + ! [remote rejected] HEAD -> next (pre-receive hook declined) + EOF + test_cmp expect actual && + git -C "$upstream" show-ref >out && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + refs/heads/master + EOF + test_cmp expect actual +' + +test_expect_success "cleanup ($PROTOCOL)" ' + mv "$upstream/hooks/pre-receive.ok" "$upstream/hooks/pre-receive" +' diff --git a/t/t5411/test-0003-pre-receive-declined--porcelain.sh b/t/t5411/test-0003-pre-receive-declined--porcelain.sh new file mode 100644 index 0000000000..0bf4e44657 --- /dev/null +++ b/t/t5411/test-0003-pre-receive-declined--porcelain.sh @@ -0,0 +1,34 @@ +test_expect_success "setup pre-receive hook (declined, $PROTOCOL)" ' + mv "$upstream/hooks/pre-receive" "$upstream/hooks/pre-receive.ok" && + write_script "$upstream/hooks/pre-receive" <<-EOF + exit 1 + EOF +' + +# Refs of upstream : master(A) +# Refs of workbench: master(A) tags/v123 +# git-push : master(B) next(A) +test_expect_success "git-push is declined (--porcelain, $PROTOCOL)" ' + test_must_fail git -C workbench push --porcelain origin \ + $B:refs/heads/master \ + HEAD:refs/heads/next \ + >out 2>&1 && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + To + ! :refs/heads/master [remote rejected] (pre-receive hook declined) + ! HEAD:refs/heads/next [remote rejected] (pre-receive hook declined) + Done + EOF + test_cmp expect actual && + git -C "$upstream" show-ref >out && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + refs/heads/master + EOF + test_cmp expect actual +' + +test_expect_success "cleanup ($PROTOCOL)" ' + mv "$upstream/hooks/pre-receive.ok" "$upstream/hooks/pre-receive" +' diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh index 9c6218f568..77938db77f 100755 --- a/t/t5516-fetch-push.sh +++ b/t/t5516-fetch-push.sh @@ -1039,7 +1039,7 @@ test_force_fetch_tag "annotated tag" "-f -a -m'tag message'" test_expect_success 'push --porcelain' ' mk_empty testrepo && echo >.git/foo "To testrepo" && - echo >>.git/foo "* refs/heads/master:refs/remotes/origin/master [new branch]" && + echo >>.git/foo "* refs/heads/master:refs/remotes/origin/master [new reference]" && echo >>.git/foo "Done" && git push >.git/bar --porcelain testrepo refs/heads/master:refs/remotes/origin/master && ( diff --git a/transport.c b/transport.c index a07e39564c..73defc4a5a 100644 --- a/transport.c +++ b/transport.c @@ -500,9 +500,12 @@ static void print_ok_ref_status(struct ref *ref, int porcelain, int summary_widt porcelain, summary_width); else if (is_null_oid(&ref->old_oid)) print_ref_status('*', - (starts_with(ref->name, "refs/tags/") ? "[new tag]" : - "[new branch]"), - ref, ref->peer_ref, NULL, porcelain, summary_width); + (starts_with(ref->name, "refs/tags/") + ? "[new tag]" + : (starts_with(ref->name, "refs/heads/") + ? "[new branch]" + : "[new reference]")), + ref, ref->peer_ref, NULL, porcelain, summary_width); else { struct strbuf quickref = STRBUF_INIT; char type; From patchwork Sat Apr 18 16:03:28 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiang Xin X-Patchwork-Id: 11496633 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 78634912 for ; Sat, 18 Apr 2020 16:03:58 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 5F9DD2223D for ; Sat, 18 Apr 2020 16:03:58 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="UszcH9Zp" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1725879AbgDRQD5 (ORCPT ); Sat, 18 Apr 2020 12:03:57 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45408 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1726581AbgDRQDv (ORCPT ); Sat, 18 Apr 2020 12:03:51 -0400 Received: from mail-pf1-x442.google.com (mail-pf1-x442.google.com [IPv6:2607:f8b0:4864:20::442]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 45F9BC061A10 for ; Sat, 18 Apr 2020 09:03:50 -0700 (PDT) Received: by mail-pf1-x442.google.com with SMTP id d1so2687383pfh.1 for ; Sat, 18 Apr 2020 09:03:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=UPo3QpRJR2XiWos3b8MvTn8o0c2HhyHfcUhONqkjpZY=; b=UszcH9Zp/LMa8oyQlesStklPlWp2STHXzseR9U2vzpdWamvDXoXD8T+EXWcULRheIW Yo8FFUr+7POdZVHQfV7wMv7mBq5kRvA+iBC0yxyLA0+Vb55pPcwYlstevBMztuKhaEUp WvR/prGB1SgHdQgiDeWjwE1I+Ug67ywFPMfHmGUVnhBXq2rEHl1jEHEBBP1IJ/CSThpg kay8xqTosApzZgthy3o1JtwRKYb+8QC6Euz0mFl8bzbcVfwbEFBDqoZQPAZHc+ZtdyNS NChnsYCDq07g7wbjJl1JSKr4ktieq+vgK0gqk428YB7U6ztScTBmZmTZufUcfKMKwhsq vVmw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=UPo3QpRJR2XiWos3b8MvTn8o0c2HhyHfcUhONqkjpZY=; b=sqauKuG2KGxj8MDOBGkuvtmHzD0mApE7xNLudfsf81kaVeeoBkDMH1HFOGV+3chENK 6/iGNOu3a+dFhn8sFE4gKVa2GEFsBXKxPbwnuf+bciMeezQdUO4VQjsrM4SsKmLkpFjC GqnMaYXIMxJVEbA/4d2TUazeAoYU8dD0GD6nNfUQOpjnTSIa0bCQppBPHzGVF8y4ZS9P L57mC8i2A40iuYW3AdgzJjXDO8+5e0ArRDPYH6OEEiUfs35f9UB7Mfeu8EFRYNTbcqKG tgUIExaFxFmiJXp4mFjJbG2sZQXdY6adHWTohkYBX9L8rIsbE7ztJdv0d+T/iqLMDvOQ USTQ== X-Gm-Message-State: AGi0Puase9ibN1+RVp6xsMvMpOjV1kGuRmjBnrbsDIdXTqmPCJZ5Nqg3 WStbaQAAy6RPqK9HSuvn3RE= X-Google-Smtp-Source: APiQypKXacIyvssO2k9CPPSlCOoj+cc2BO+PsksnMN5sV8h8NHN3QU32ChFqCxOhLSE56yCeiYazIA== X-Received: by 2002:a63:7159:: with SMTP id b25mr8175205pgn.72.1587225829900; Sat, 18 Apr 2020 09:03:49 -0700 (PDT) Received: from tigtog.localdomain.localdomain ([144.34.163.219]) by smtp.gmail.com with ESMTPSA id i187sm22461649pfg.33.2020.04.18.09.03.49 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Sat, 18 Apr 2020 09:03:49 -0700 (PDT) From: Jiang Xin To: Junio C Hamano , Git List Cc: Jiang Xin Subject: [PATCH v13 2/8] connect: export parse_feature_value() Date: Sat, 18 Apr 2020 12:03:28 -0400 Message-Id: <20200418160334.15631-3-worldhello.net@gmail.com> X-Mailer: git-send-email 2.26.0.rc0 In-Reply-To: <20200414123257.27449-1-worldhello.net@gmail.com> References: <20200414123257.27449-1-worldhello.net@gmail.com> MIME-Version: 1.0 Sender: git-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Jiang Xin Export `parse_feature_value()` to parse extended status of report for "proc-receive" and "receive-pack". Signed-off-by: Jiang Xin --- connect.c | 3 +-- connect.h | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/connect.c b/connect.c index b6451ab5e8..08e0616726 100644 --- a/connect.c +++ b/connect.c @@ -18,7 +18,6 @@ static char *server_capabilities_v1; static struct argv_array server_capabilities_v2 = ARGV_ARRAY_INIT; -static const char *parse_feature_value(const char *, const char *, int *); static int check_ref(const char *name, unsigned int flags) { @@ -447,7 +446,7 @@ struct ref **get_remote_refs(int fd_out, struct packet_reader *reader, return list; } -static const char *parse_feature_value(const char *feature_list, const char *feature, int *lenp) +const char *parse_feature_value(const char *feature_list, const char *feature, int *lenp) { int len; diff --git a/connect.h b/connect.h index 5f2382e018..17b3252cbc 100644 --- a/connect.h +++ b/connect.h @@ -12,6 +12,7 @@ int finish_connect(struct child_process *conn); int git_connection_is_socket(struct child_process *conn); int server_supports(const char *feature); int parse_feature_request(const char *features, const char *feature); +const char *parse_feature_value(const char *feature_list, const char *feature, int *len_ret); const char *server_feature_value(const char *feature, int *len_ret); int url_is_local_not_ssh(const char *url); From patchwork Sat Apr 18 16:03:29 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiang Xin X-Patchwork-Id: 11496645 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 691CE112C for ; Sat, 18 Apr 2020 16:04:07 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 2CC5021D93 for ; Sat, 18 Apr 2020 16:04:07 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="DJf30fSc" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727833AbgDRQEF (ORCPT ); Sat, 18 Apr 2020 12:04:05 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45422 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1726907AbgDRQDy (ORCPT ); Sat, 18 Apr 2020 12:03:54 -0400 Received: from mail-pf1-x443.google.com (mail-pf1-x443.google.com [IPv6:2607:f8b0:4864:20::443]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 47F1CC061A0F for ; Sat, 18 Apr 2020 09:03:54 -0700 (PDT) Received: by mail-pf1-x443.google.com with SMTP id d1so2687458pfh.1 for ; Sat, 18 Apr 2020 09:03:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=FkN3azort0vMzqBc2oKYFKfI73U1BHF84Jk99SFKhyE=; b=DJf30fScyj8KS13timX7ls05LHG0O1MAj35Vn+93U56fYS1UHtFa5TR/ymmO4urRTH 08ls4ayUy/9/tr9TdepMwl+8yDSVf8iPbmfZ2umLjOPdrWwyAR1MCqPUoxZS7H0nudVx TCh9ILpzB7p0ls/9mT3TAk5RT4V+z5syGtkE9GddN21wMJFG+bf7aAigekcaJiuwJPcX Mc6ZQiTrH6YcB0LReksJws3Lhd+Zj9ToBGnNHUAJig/1FmKC2MJmlNn8Q2wPxAoFaruz gvy7ldqYsHnbFMq5ta01Z+XVdIdrMZcd/t7OBu36vKgO+ND3ig5K2lm+ymtHQMTv76ze SETQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=FkN3azort0vMzqBc2oKYFKfI73U1BHF84Jk99SFKhyE=; b=jMYfJbLxrxpoe8doKj52OZekURiqh0+0H/vGzAtp5T2OjSYL4086dUZQ8W1oUXgxmi aohCYhTntJpVXcGKs/mBuxV26Q2ZSLDRVJE48KfotrAOZKEZBI79OcHFruX8q728GAun snK/bboSWqVp+Zd+B1pOyDQq6Oj/GGSGIEyYzv+fnw1Qwtn0z5HTW2fLs4G72CT4qQpB iDo6ViaW2jc6XaJLqWzNUbe8SA5k6VIPYfgdODqNyc6HLGKgI7xMjHEEgTQHku2pAns0 2sSFj0rICjfni7FXm3MUsvFHB+BFCTHcdaRi5hanXBd1PxPBmW+qXH/VzBXtE6G4CM1f bEFA== X-Gm-Message-State: AGi0PuZGEbsY8Eh4V0/gNPUSlHZB1amP/LvgjbOkALWcLCAk3oagtmYO 7Ik0Qn7goJ0HoVrlRYmp0wY= X-Google-Smtp-Source: APiQypIeuJik0AhKbhmYkGDb7G5oTHYvgg5bXONz/JYhrgqlHp4NqIjpqk5QpCYO3GdZ+AVXW+tAdg== X-Received: by 2002:a62:d119:: with SMTP id z25mr7443463pfg.153.1587225831950; Sat, 18 Apr 2020 09:03:51 -0700 (PDT) Received: from tigtog.localdomain.localdomain ([144.34.163.219]) by smtp.gmail.com with ESMTPSA id i187sm22461649pfg.33.2020.04.18.09.03.50 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Sat, 18 Apr 2020 09:03:51 -0700 (PDT) From: Jiang Xin To: Junio C Hamano , Git List Cc: Jiang Xin Subject: [PATCH v13 3/8] receive-pack: add new proc-receive hook Date: Sat, 18 Apr 2020 12:03:29 -0400 Message-Id: <20200418160334.15631-4-worldhello.net@gmail.com> X-Mailer: git-send-email 2.26.0.rc0 In-Reply-To: <20200414123257.27449-1-worldhello.net@gmail.com> References: <20200414123257.27449-1-worldhello.net@gmail.com> MIME-Version: 1.0 Sender: git-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Jiang Xin Git calls an internal `execute_commands` function to handle commands sent from client to `git-receive-pack`. Regardless of what references the user pushes, git creates or updates the corresponding references if the user has write-permission. A contributor who has no write-permission, cannot push to the repository directly. So, the contributor has to write commits to an alternate location, and sends pull request by emails or by other ways. We call this workflow as a distributed workflow. It would be more convenient to work in a centralized workflow like what Gerrit provided for some cases. For example, a read-only user who cannot push to a branch directly can run the following `git push` command to push commits to a pseudo reference (has a prefix "refs/for/", not "refs/heads/") to create a code review. git push origin \ HEAD:refs/for// The `` in the above example can be as simple as "master", or a more complicated branch name like "foo/bar". The `` in the above example command can be the local branch name of the client side, such as "my/topic". We cannot implement a centralized workflow elegantly by using "pre-receive" + "post-receive", because Git will call the internal function "execute_commands" to create references (even the special pseudo reference) between these two hooks. Even though we can delete the temporarily created pseudo reference via the "post-receive" hook, having a temporary reference is not safe for concurrent pushes. So, add a filter and a new handler to support this kind of workflow. The filter will check the prefix of the reference name, and if the command has a special reference name, the filter will turn a specific field (`run_proc_receive`) on for the command. Commands with this filed turned on will be executed by a new handler (an hook named "proc-receive") instead of the internal `execute_commands` function. We can use this "proc-receive" command to create pull requests or send emails for code review. Suggested by Junio, this "proc-receive" hook reads the commands, push-options (optional), and send result using a protocol in pkt-line format. In the following example, The letter "S" stands for "receive-pack" and letter "H" stands for the hook. # Version and features negotiation. S: PKT-LINE(version=1\0push-options atomic...) S: flush-pkt H: PKT-LINE(version=1\0push-options...) H: flush-pkt # Send commands from server to the hook. S: PKT-LINE( ) S: ... ... S: flush-pkt # Send push-options only if the 'push-options' feature is enabled. S: PKT-LINE(push-option) S: ... ... S: flush-pkt # Receive result from the hook. # OK, run this command successfully. H: PKT-LINE(ok ) # NO, I reject it. H: PKT-LINE(ng ) # Fall through, let 'receive-pack' to execute it. H: PKT-LINE(ft ) # OK, but has an alternate reference. The alternate reference name # is given in the third parameter, and other status can be given in # key-value pairs. H: PKT-LINE(alt old-oid= new-oid= forced-update) H: ... ... H: flush-pkt After receiving a command, the hook will execute the command, and may create/update different reference. For example, a command for a pseudo reference "refs/for/master/topic" may create/update different reference such as "refs/pull/123/head". The alternate reference name and other status are given in key-value pairs as extended status of the report line. The list of commands returned from "proc-receive" will replace the relevant commands that are sent from user to "receive-pack", and "receive-pack" will continue to run the "execute_commands" function and other routines. Finally, the result of the execution of these commands will be reported to end user. The reporting function from "receive-pack" to "send-pack" is extended using a backward compatible way by adding key-value pairs after an null character, like: # OK, run this command successfully with optional extended-status. ok \0ref=refs/pull/123/head old-oid=... # NO, I reject it. ng Parsing the extended status of the report lines for "send-pack" is not implemented in this commit, so we can make a compatible test on old version of a Git client. Suggested-by: Junio C Hamano Signed-off-by: Jiang Xin --- Makefile | 1 + builtin/receive-pack.c | 356 +++++++++++++++++- t/helper/test-proc-receive.c | 175 +++++++++ t/helper/test-tool.c | 1 + t/helper/test-tool.h | 1 + t/t5411/test-0011-no-hook-error.sh | 64 ++++ t/t5411/test-0012-no-hook-error--porcelain.sh | 66 ++++ t/t5411/test-0013-bad-protocol.sh | 225 +++++++++++ t/t5411/test-0014-bad-protocol--porcelain.sh | 160 ++++++++ t/t5411/test-0020-report-ng.sh | 67 ++++ t/t5411/test-0021-report-ng--porcelain.sh | 69 ++++ t/t5411/test-0022-report-unexpect-ref.sh | 45 +++ ...est-0023-report-unexpect-ref--porcelain.sh | 46 +++ t/t5411/test-0024-report-unknown-ref.sh | 34 ++ ...test-0025-report-unknown-ref--porcelain.sh | 35 ++ t/t5411/test-0026-push-options.sh | 79 ++++ t/t5411/test-0027-push-options--porcelain.sh | 82 ++++ t/t5411/test-0030-report-ok.sh | 35 ++ t/t5411/test-0031-report-ok--porcelain.sh | 36 ++ t/t5411/test-0032-report-alt.sh | 229 +++++++++++ t/t5411/test-0033-report-alt--porcelain.sh | 236 ++++++++++++ t/t5411/test-0034-report-ft.sh | 42 +++ t/t5411/test-0035-report-ft--porcelain.sh | 43 +++ .../test-0036-report-multi-alt-for-one-ref.sh | 155 ++++++++ ...report-multi-alt-for-one-ref--porcelain.sh | 159 ++++++++ t/t5411/test-0038-report-mixed-refs.sh | 74 ++++ .../test-0039-report-mixed-refs--porcelain.sh | 75 ++++ 27 files changed, 2581 insertions(+), 9 deletions(-) create mode 100644 t/helper/test-proc-receive.c create mode 100644 t/t5411/test-0011-no-hook-error.sh create mode 100644 t/t5411/test-0012-no-hook-error--porcelain.sh create mode 100644 t/t5411/test-0013-bad-protocol.sh create mode 100644 t/t5411/test-0014-bad-protocol--porcelain.sh create mode 100644 t/t5411/test-0020-report-ng.sh create mode 100644 t/t5411/test-0021-report-ng--porcelain.sh create mode 100644 t/t5411/test-0022-report-unexpect-ref.sh create mode 100644 t/t5411/test-0023-report-unexpect-ref--porcelain.sh create mode 100644 t/t5411/test-0024-report-unknown-ref.sh create mode 100644 t/t5411/test-0025-report-unknown-ref--porcelain.sh create mode 100644 t/t5411/test-0026-push-options.sh create mode 100644 t/t5411/test-0027-push-options--porcelain.sh create mode 100644 t/t5411/test-0030-report-ok.sh create mode 100644 t/t5411/test-0031-report-ok--porcelain.sh create mode 100644 t/t5411/test-0032-report-alt.sh create mode 100644 t/t5411/test-0033-report-alt--porcelain.sh create mode 100644 t/t5411/test-0034-report-ft.sh create mode 100644 t/t5411/test-0035-report-ft--porcelain.sh create mode 100644 t/t5411/test-0036-report-multi-alt-for-one-ref.sh create mode 100644 t/t5411/test-0037-report-multi-alt-for-one-ref--porcelain.sh create mode 100644 t/t5411/test-0038-report-mixed-refs.sh create mode 100644 t/t5411/test-0039-report-mixed-refs--porcelain.sh diff --git a/Makefile b/Makefile index ef1ff2228f..1c52c280ce 100644 --- a/Makefile +++ b/Makefile @@ -725,6 +725,7 @@ TEST_BUILTINS_OBJS += test-parse-pathspec-file.o TEST_BUILTINS_OBJS += test-path-utils.o TEST_BUILTINS_OBJS += test-pkt-line.o TEST_BUILTINS_OBJS += test-prio-queue.o +TEST_BUILTINS_OBJS += test-proc-receive.o TEST_BUILTINS_OBJS += test-progress.o TEST_BUILTINS_OBJS += test-reach.o TEST_BUILTINS_OBJS += test-read-cache.o diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c index 2cc18bbffd..0081bf1415 100644 --- a/builtin/receive-pack.c +++ b/builtin/receive-pack.c @@ -308,11 +308,15 @@ static void write_head_info(void) packet_flush(1); } +#define RUN_PROC_RECEIVE_SCHEDULED 1 +#define RUN_PROC_RECEIVE_RETURNED 2 struct command { struct command *next; const char *error_string; + const char *extended_status; unsigned int skip_update:1, - did_not_exist:1; + did_not_exist:1, + run_proc_receive:2; int index; struct object_id old_oid; struct object_id new_oid; @@ -817,6 +821,307 @@ static int run_update_hook(struct command *cmd) return finish_command(&proc); } +static struct command *find_command_by_refname(const struct command *list, + const char *refname) +{ + for (; list; list = list->next) + if (!strcmp(list->ref_name, refname)) + return (struct command *)list; + return NULL; +} + +static int read_proc_receive_report(struct packet_reader *reader, + struct command *commands, + struct strbuf *errmsg) +{ + struct command *cmd; + struct command *hint = NULL; + struct strbuf extended_status = STRBUF_INIT; + int code = 0; + + for (;;) { + struct object_id old_oid, new_oid; + const char *status; + char *refname; + char *remains = NULL; + + if (packet_reader_read(reader) != PACKET_READ_NORMAL) + break; + status = reader->line; + refname = strchr(status, ' '); + if (refname) { + *refname++ = '\0'; + remains = strchr(refname, ' '); + if (remains) + *remains++ = '\0'; + } + if (!refname || strlen(refname) == 0) { + strbuf_addf(errmsg, "proc-receive expected ' ...', got '%s'\n", + reader->line); + code = -1; + continue; + } + + /* first try searching at our hint, falling back to all refs */ + if (hint) + hint = find_command_by_refname(hint, refname); + if (!hint) + hint = find_command_by_refname(commands, refname); + if (!hint) { + strbuf_addf(errmsg, "proc-receive reported status on unknown ref: %s\n", + refname); + continue; + } + if (!hint->run_proc_receive) { + strbuf_addf(errmsg, "proc-receive reported status on unexpected ref: %s\n", + refname); + continue; + } + if (!strcmp(status, "ng")) { + if (remains) + hint->error_string = xstrdup(remains); + else + hint->error_string = "failed"; + code = -1; + } else if (!strcmp("ft", status)) { + /* Reset "run_proc_receive" field, and continue to run in "receive-pack" */ + hint->run_proc_receive = 0; + } else if (!strcmp("alt", status)) { + char *alt_ref = NULL; + char *p1, *p2; + + if (!remains) { + strbuf_addf(errmsg, "proc-receive expected 'alt ...', got 'alt %s'\n", + refname); + continue; + } + p1 = strchr(remains, '='); + p2 = strchr(remains, ' '); + if (!p1) { + /* + * "alt ", or + * "alt forced-update" + */ + alt_ref = remains; + remains = p2; + if (remains) + *remains++ = '\0'; + } else if (!p2) { + /* "alt old-oid=" */ + alt_ref = NULL; + } else if (p1 > p2) { + /* "alt old-oid=" */ + alt_ref = remains; + remains = p2; + if (remains) + *remains++ = '\0'; + } else { + /* "alt old-oid= new-oid=" */ + alt_ref = NULL; + } + + if (hint->extended_status) + strbuf_addstr(&extended_status, hint->extended_status); + + /* + * Already received an "ok " response, add an + * additional "ref=" field. + */ + if (extended_status.len == 0 && + hint->run_proc_receive & RUN_PROC_RECEIVE_RETURNED) + strbuf_addf(&extended_status, "ref=%s", refname); + + if (alt_ref) + strbuf_addf(&extended_status, "%sref=%s", + extended_status.len > 0 ? " ": "", + alt_ref); + else if (extended_status.len > 0) + /* + * Start new extended status for refname, if it + * is not the first report for this reference. + */ + strbuf_addf(&extended_status, " ref=%s", refname); + + if (remains) { + const char *val; + int len; + + val = parse_feature_value(remains, "old-oid", &len); + if (val && len > 0) + if (!parse_oid_hex(val, &old_oid, &val)) + strbuf_addf(&extended_status, "%sold-oid=%s", + extended_status.len > 0 ? " ": "", + oid_to_hex(&old_oid)); + + val = parse_feature_value(remains, "new-oid", &len); + if (val && len > 0) + if (!parse_oid_hex(val, &new_oid, &val)) + strbuf_addf(&extended_status, "%snew-oid=%s", + extended_status.len > 0 ? " ": "", + oid_to_hex(&new_oid)); + + if (parse_feature_request(remains, "forced-update")) + strbuf_addf(&extended_status, "%sforced-update", + extended_status.len > 0 ? " ": ""); + } + + if (extended_status.len > 0) { + free((void *)hint->extended_status); + hint->extended_status = strbuf_detach(&extended_status, NULL); + } + } else if (strcmp("ok", status)) { + strbuf_addf(errmsg, "proc-receive reported bad status '%s' on ref '%s'\n", + status, refname); + code = -1; + /* Skip marking it as RUN_PROC_RECEIVE_RETURNED */ + continue; + } + + if (hint->run_proc_receive) + hint->run_proc_receive |= RUN_PROC_RECEIVE_RETURNED; + } + + for (cmd = commands; cmd; cmd = cmd->next) + if (cmd->run_proc_receive && !cmd->error_string && + !(cmd->run_proc_receive & RUN_PROC_RECEIVE_RETURNED)) { + cmd->error_string = "proc-receive failed to report status"; + code = -1; + } + + return code; +} + +static int run_proc_receive_hook(struct command *commands, + const struct string_list *push_options) +{ + struct child_process proc = CHILD_PROCESS_INIT; + struct async muxer; + struct command *cmd; + const char *argv[2]; + struct packet_reader reader; + struct strbuf cap = STRBUF_INIT; + struct strbuf errmsg = STRBUF_INIT; + int pr_use_push_options = 0; + int version = 0; + int code; + + argv[0] = find_hook("proc-receive"); + if (!argv[0]) { + rp_error("cannot find hook 'proc-receive'"); + return -1; + } + argv[1] = NULL; + + proc.argv = argv; + proc.in = -1; + proc.out = -1; + proc.trace2_hook_name = "proc-receive"; + + if (use_sideband) { + memset(&muxer, 0, sizeof(muxer)); + muxer.proc = copy_to_sideband; + muxer.in = -1; + code = start_async(&muxer); + if (code) + return code; + proc.err = muxer.in; + } else { + proc.err = 0; + } + + code = start_command(&proc); + if (code) { + if (use_sideband) + finish_async(&muxer); + return code; + } + + sigchain_push(SIGPIPE, SIG_IGN); + + /* Version negotiaton */ + packet_reader_init(&reader, proc.out, NULL, 0, + PACKET_READ_CHOMP_NEWLINE | + PACKET_READ_GENTLE_ON_EOF); + if (use_atomic) + strbuf_addstr(&cap, " atomic"); + if (use_push_options) + strbuf_addstr(&cap, " push-options"); + if (cap.len) { + packet_write_fmt(proc.in, "version=1%c%s\n", '\0', cap.buf + 1); + strbuf_release(&cap); + } else { + packet_write_fmt(proc.in, "version=1\n"); + } + packet_flush(proc.in); + + for (;;) { + int linelen; + + if (packet_reader_read(&reader) != PACKET_READ_NORMAL) + break; + + if (reader.pktlen > 8 && starts_with(reader.line, "version=")) { + version = atoi(reader.line + 8); + linelen = strlen(reader.line); + if (linelen < reader.pktlen) { + const char *feature_list = reader.line + linelen + 1; + if (parse_feature_request(feature_list, "push-options")) + pr_use_push_options = 1; + } + } + } + + if (version != 1) { + strbuf_addf(&errmsg, "proc-receive version '%d' is not supported", + version); + code = -1; + goto cleanup; + } + + /* Send commands */ + for (cmd = commands; cmd; cmd = cmd->next) { + if (!cmd->run_proc_receive || cmd->skip_update || cmd->error_string) + continue; + packet_write_fmt(proc.in, "%s %s %s", + oid_to_hex(&cmd->old_oid), + oid_to_hex(&cmd->new_oid), + cmd->ref_name); + } + packet_flush(proc.in); + + /* Send push options */ + if (pr_use_push_options) { + struct string_list_item *item; + + for_each_string_list_item(item, push_options) + packet_write_fmt(proc.in, "%s", item->string); + packet_flush(proc.in); + } + + /* Read result from proc-receive */ + code = read_proc_receive_report(&reader, commands, &errmsg); + +cleanup: + close(proc.in); + close(proc.out); + if (use_sideband) + finish_async(&muxer); + if (finish_command(&proc)) + code = -1; + if (errmsg.len >0) { + char *p = errmsg.buf; + + p += errmsg.len - 1; + if (*p == '\n') + *p = '\0'; + rp_error("%s", errmsg.buf); + strbuf_release(&errmsg); + } + sigchain_pop(SIGPIPE); + + return code; +} + static char *refuse_unconfigured_deny_msg = N_("By default, updating the current branch in a non-bare repository\n" "is denied, because it will make the index and work tree inconsistent\n" @@ -1392,7 +1697,7 @@ static void execute_commands_non_atomic(struct command *commands, struct strbuf err = STRBUF_INIT; for (cmd = commands; cmd; cmd = cmd->next) { - if (!should_process_cmd(cmd)) + if (!should_process_cmd(cmd) || cmd->run_proc_receive) continue; transaction = ref_transaction_begin(&err); @@ -1432,7 +1737,7 @@ static void execute_commands_atomic(struct command *commands, } for (cmd = commands; cmd; cmd = cmd->next) { - if (!should_process_cmd(cmd)) + if (!should_process_cmd(cmd) || cmd->run_proc_receive) continue; cmd->error_string = update(cmd, si); @@ -1468,6 +1773,7 @@ static void execute_commands(struct command *commands, struct iterate_data data; struct async muxer; int err_fd = 0; + int run_proc_receive = 0; if (unpacker_error) { for (cmd = commands; cmd; cmd = cmd->next) @@ -1497,6 +1803,21 @@ static void execute_commands(struct command *commands, reject_updates_to_hidden(commands); + /* + * Try to find commands that have special prefix in their reference names, + * and mark them to run an external "proc-receive" hook later. + */ + for (cmd = commands; cmd; cmd = cmd->next) { + if (!should_process_cmd(cmd)) + continue; + + /* TODO: replace the fixed prefix by looking up git config variables. */ + if (!strncmp(cmd->ref_name, "refs/for/", 9)) { + cmd->run_proc_receive = RUN_PROC_RECEIVE_SCHEDULED; + run_proc_receive = 1; + } + } + if (run_receive_hook(commands, "pre-receive", 0, push_options)) { for (cmd = commands; cmd; cmd = cmd->next) { if (!cmd->error_string) @@ -1523,6 +1844,12 @@ static void execute_commands(struct command *commands, free(head_name_to_free); head_name = head_name_to_free = resolve_refdup("HEAD", 0, NULL, NULL); + if (run_proc_receive && + run_proc_receive_hook(commands, push_options)) + for (cmd = commands; cmd; cmd = cmd->next) + if (!cmd->error_string && (cmd->run_proc_receive || use_atomic)) + cmd->error_string = "fail to run proc-receive hook"; + if (use_atomic) execute_commands_atomic(commands, si); else @@ -1899,12 +2226,23 @@ static void report(struct command *commands, const char *unpack_status) packet_buf_write(&buf, "unpack %s\n", unpack_status ? unpack_status : "ok"); for (cmd = commands; cmd; cmd = cmd->next) { - if (!cmd->error_string) - packet_buf_write(&buf, "ok %s\n", - cmd->ref_name); - else - packet_buf_write(&buf, "ng %s %s\n", - cmd->ref_name, cmd->error_string); + if (!cmd->error_string) { + if (cmd->extended_status) + packet_buf_write(&buf, "ok %s%c%s\n", + cmd->ref_name, '\0', + cmd->extended_status); + else + packet_buf_write(&buf, "ok %s\n", + cmd->ref_name); + } else { + if (cmd->extended_status) + packet_buf_write(&buf, "ng %s %s%c%s\n", + cmd->ref_name, cmd->error_string, + '\0', cmd->extended_status); + else + packet_buf_write(&buf, "ng %s %s\n", + cmd->ref_name, cmd->error_string); + } } packet_buf_flush(&buf); diff --git a/t/helper/test-proc-receive.c b/t/helper/test-proc-receive.c new file mode 100644 index 0000000000..6ace1863b0 --- /dev/null +++ b/t/helper/test-proc-receive.c @@ -0,0 +1,175 @@ +#include "cache.h" +#include "connect.h" +#include "parse-options.h" +#include "pkt-line.h" +#include "sigchain.h" +#include "string-list.h" +#include "test-tool.h" + +static const char *proc_receive_usage[] = { + "test-tool proc-receive [...]", + NULL +}; + +static int die_version = 0; +static int die_readline = 0; +static int no_push_options = 0; +static int use_atomic = 0; +static int use_push_options = 0; +static int verbose = 0; +static int version = 1; +static struct string_list returns = STRING_LIST_INIT_NODUP; + +struct command { + struct command *next; + const char *error_string; + unsigned int skip_update:1, + did_not_exist:1; + int index; + struct object_id old_oid; + struct object_id new_oid; + char ref_name[FLEX_ARRAY]; /* more */ +}; + +static void proc_receive_verison(struct packet_reader *reader) { + int server_version = 0; + + for (;;) { + int linelen; + + if (packet_reader_read(reader) != PACKET_READ_NORMAL) + break; + + if (reader->pktlen > 8 && starts_with(reader->line, "version=")) { + server_version = atoi(reader->line+8); + linelen = strlen(reader->line); + if (linelen < reader->pktlen) { + const char *feature_list = reader->line + linelen + 1; + if (parse_feature_request(feature_list, "atomic")) + use_atomic= 1; + if (parse_feature_request(feature_list, "push-options")) + use_push_options = 1; + } + } + } + + if (server_version != 1 || die_version) + die("bad protocol version: %d", server_version); + + packet_write_fmt(1, "version=%d%c%s\n", + version, '\0', + use_push_options && !no_push_options ? "push-options": ""); + packet_flush(1); +} + +static void proc_receive_read_commands(struct packet_reader *reader, + struct command **commands) +{ + struct command **tail = commands; + + for (;;) { + struct object_id old_oid, new_oid; + struct command *cmd; + const char *refname; + const char *p; + + if (packet_reader_read(reader) != PACKET_READ_NORMAL) + break; + + if (parse_oid_hex(reader->line, &old_oid, &p) || + *p++ != ' ' || + parse_oid_hex(p, &new_oid, &p) || + *p++ != ' ' || + die_readline) + die("protocol error: expected 'old new ref', got '%s'", + reader->line); + refname = p; + FLEX_ALLOC_STR(cmd, ref_name, refname); + oidcpy(&cmd->old_oid, &old_oid); + oidcpy(&cmd->new_oid, &new_oid); + + *tail = cmd; + tail = &cmd->next; + } +} + +static void proc_receive_read_push_options(struct packet_reader *reader, + struct string_list *options) +{ + + if (no_push_options || !use_push_options) + return; + + while (1) { + if (packet_reader_read(reader) != PACKET_READ_NORMAL) + break; + + string_list_append(options, reader->line); + } +} + +int cmd__proc_receive(int argc, const char **argv) +{ + struct packet_reader reader; + struct command *commands = NULL; + struct string_list push_options = STRING_LIST_INIT_DUP; + struct string_list_item *item; + struct option options[] = { + OPT_BOOL(0, "no-push-options", &no_push_options, + "disable push options"), + OPT_BOOL(0, "die-version", &die_version, + "die during version negotiation"), + OPT_BOOL(0, "die-readline", &die_readline, + "die when readline"), + OPT_STRING_LIST('r', "return", &returns, "old/new/ref/status/msg", + "return of results"), + OPT__VERBOSE(&verbose, "be verbose"), + OPT_INTEGER('V', "version", &version, + "use this protocol version number"), + OPT_END() + }; + + argc = parse_options(argc, argv, "test-tools", options, proc_receive_usage, 0); + if (argc > 0) + usage_msg_opt("Too many arguments.", proc_receive_usage, options); + + packet_reader_init(&reader, 0, NULL, 0, + PACKET_READ_CHOMP_NEWLINE | + PACKET_READ_DIE_ON_ERR_PACKET); + + sigchain_push(SIGPIPE, SIG_IGN); + proc_receive_verison(&reader); + proc_receive_read_commands(&reader, &commands); + proc_receive_read_push_options(&reader, &push_options); + + if (verbose) { + struct command *cmd; + + if (use_push_options || use_atomic) + fprintf(stderr, "proc-receive:%s%s\n", + use_atomic? " atomic": "", + use_push_options ? " push_options": ""); + + for (cmd = commands; cmd; cmd = cmd->next) + fprintf(stderr, "proc-receive< %s %s %s\n", + oid_to_hex(&cmd->old_oid), + oid_to_hex(&cmd->new_oid), + cmd->ref_name); + + if (push_options.nr > 0) + for_each_string_list_item(item, &push_options) + fprintf(stderr, "proc-receive< %s\n", item->string); + + if (returns.nr) + for_each_string_list_item(item, &returns) + fprintf(stderr, "proc-receive> %s\n", item->string); + } + + if (returns.nr) + for_each_string_list_item(item, &returns) + packet_write_fmt(1, "%s\n", item->string); + packet_flush(1); + sigchain_pop(SIGPIPE); + + return 0; +} diff --git a/t/helper/test-tool.c b/t/helper/test-tool.c index 31eedcd241..f865433a61 100644 --- a/t/helper/test-tool.c +++ b/t/helper/test-tool.c @@ -44,6 +44,7 @@ static struct test_cmd cmds[] = { { "path-utils", cmd__path_utils }, { "pkt-line", cmd__pkt_line }, { "prio-queue", cmd__prio_queue }, + { "proc-receive", cmd__proc_receive}, { "progress", cmd__progress }, { "reach", cmd__reach }, { "read-cache", cmd__read_cache }, diff --git a/t/helper/test-tool.h b/t/helper/test-tool.h index 4eb5e6609e..059008cf22 100644 --- a/t/helper/test-tool.h +++ b/t/helper/test-tool.h @@ -34,6 +34,7 @@ int cmd__parse_pathspec_file(int argc, const char** argv); int cmd__path_utils(int argc, const char **argv); int cmd__pkt_line(int argc, const char **argv); int cmd__prio_queue(int argc, const char **argv); +int cmd__proc_receive(int argc, const char **argv); int cmd__progress(int argc, const char **argv); int cmd__reach(int argc, const char **argv); int cmd__read_cache(int argc, const char **argv); diff --git a/t/t5411/test-0011-no-hook-error.sh b/t/t5411/test-0011-no-hook-error.sh new file mode 100644 index 0000000000..bb6ec92a92 --- /dev/null +++ b/t/t5411/test-0011-no-hook-error.sh @@ -0,0 +1,64 @@ +# Refs of upstream : master(A) +# Refs of workbench: master(A) tags/v123 +# git push : next(A) refs/for/master/topic(A) +test_expect_success "proc-receive: no hook, fail to push special ref ($PROTOCOL)" ' + test_must_fail git -C workbench push origin \ + HEAD:next \ + HEAD:refs/for/master/topic \ + >out 2>&1 && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + remote: # pre-receive hook + remote: pre-receive< refs/heads/next + remote: pre-receive< refs/for/master/topic + remote: error: cannot find hook "proc-receive" + remote: # post-receive hook + remote: post-receive< refs/heads/next + To + * [new branch] HEAD -> next + ! [remote rejected] HEAD -> refs/for/master/topic (fail to run proc-receive hook) + EOF + test_cmp expect actual && + git -C "$upstream" show-ref >out && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + refs/heads/master + refs/heads/next + EOF + test_cmp expect actual +' + +# Refs of upstream : master(A) next(A) +# Refs of workbench: master(A) tags/v123 +test_expect_success "cleanup ($PROTOCOL)" ' + git -C "$upstream" update-ref -d refs/heads/next +' + +# Refs of upstream : master(A) +# Refs of workbench: master(A) tags/v123 +# git push --atomic: (B) next(A) refs/for/master/topic(A) +test_expect_success "proc-receive: no hook, all failed for atomic push ($PROTOCOL)" ' + test_must_fail git -C workbench push --atomic origin \ + $B:master \ + HEAD:next \ + HEAD:refs/for/master/topic >out 2>&1 && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + remote: # pre-receive hook + remote: pre-receive< refs/heads/master + remote: pre-receive< refs/heads/next + remote: pre-receive< refs/for/master/topic + remote: error: cannot find hook "proc-receive" + To + ! [remote rejected] -> master (fail to run proc-receive hook) + ! [remote rejected] HEAD -> next (fail to run proc-receive hook) + ! [remote rejected] HEAD -> refs/for/master/topic (fail to run proc-receive hook) + EOF + test_cmp expect actual && + git -C "$upstream" show-ref >out && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + refs/heads/master + EOF + test_cmp expect actual +' diff --git a/t/t5411/test-0012-no-hook-error--porcelain.sh b/t/t5411/test-0012-no-hook-error--porcelain.sh new file mode 100644 index 0000000000..e3bd0962ab --- /dev/null +++ b/t/t5411/test-0012-no-hook-error--porcelain.sh @@ -0,0 +1,66 @@ +# Refs of upstream : master(A) +# Refs of workbench: master(A) tags/v123 +# git push : next(A) refs/for/master/topic(A) +test_expect_success "proc-receive: no hook, fail to push special ref (--porcelain, $PROTOCOL)" ' + test_must_fail git -C workbench push --porcelain origin \ + HEAD:next \ + HEAD:refs/for/master/topic \ + >out 2>&1 && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + remote: # pre-receive hook + remote: pre-receive< refs/heads/next + remote: pre-receive< refs/for/master/topic + remote: error: cannot find hook "proc-receive" + remote: # post-receive hook + remote: post-receive< refs/heads/next + To + * HEAD:refs/heads/next [new branch] + ! HEAD:refs/for/master/topic [remote rejected] (fail to run proc-receive hook) + Done + EOF + test_cmp expect actual && + git -C "$upstream" show-ref >out && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + refs/heads/master + refs/heads/next + EOF + test_cmp expect actual +' + +# Refs of upstream : master(A) next(A) +# Refs of workbench: master(A) tags/v123 +test_expect_success "cleanup ($PROTOCOL)" ' + git -C "$upstream" update-ref -d refs/heads/next +' + +# Refs of upstream : master(A) +# Refs of workbench: master(A) tags/v123 +# git push --atomic: (B) next(A) refs/for/master/topic(A) +test_expect_success "proc-receive: no hook, all failed for atomic push (--porcelain, $PROTOCOL)" ' + test_must_fail git -C workbench push --porcelain --atomic origin \ + $B:master \ + HEAD:next \ + HEAD:refs/for/master/topic >out 2>&1 && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + remote: # pre-receive hook + remote: pre-receive< refs/heads/master + remote: pre-receive< refs/heads/next + remote: pre-receive< refs/for/master/topic + remote: error: cannot find hook "proc-receive" + To + ! :refs/heads/master [remote rejected] (fail to run proc-receive hook) + ! HEAD:refs/heads/next [remote rejected] (fail to run proc-receive hook) + ! HEAD:refs/for/master/topic [remote rejected] (fail to run proc-receive hook) + Done + EOF + test_cmp expect actual && + git -C "$upstream" show-ref >out && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + refs/heads/master + EOF + test_cmp expect actual +' diff --git a/t/t5411/test-0013-bad-protocol.sh b/t/t5411/test-0013-bad-protocol.sh new file mode 100644 index 0000000000..a375ddffd9 --- /dev/null +++ b/t/t5411/test-0013-bad-protocol.sh @@ -0,0 +1,225 @@ +test_expect_success "setup proc-receive hook (unknown version, $PROTOCOL)" ' + write_script "$upstream/hooks/proc-receive" <<-EOF + printf >&2 "# proc-receive hook\n" + test-tool proc-receive -v --version 2 + EOF +' + +# Refs of upstream : master(A) +# Refs of workbench: master(A) tags/v123 +# git push : refs/for/master/topic(A) +test_expect_success "proc-receive: bad protocol (unknown version, $PROTOCOL)" ' + test_must_fail git -C workbench push origin \ + HEAD:refs/for/master/topic \ + >out 2>&1 && + make_user_friendly_and_stable_output actual && + + # Check status report for git-push + sed -n \ + -e "/^To / { p; n; p; }" \ + actual-report && + cat >expect <<-EOF && + To + ! [remote rejected] HEAD -> refs/for/master/topic (fail to run proc-receive hook) + EOF + test_cmp expect actual-report && + + # Check error message from "receive-pack", but ignore unstable fatal error + # message ("remote: fatal: the remote end hung up unexpectedly") which + # is different from the remote HTTP server with different locale settings. + grep "^remote: error:" actual-error && + cat >expect <<-EOF && + remote: error: proc-receive version "2" is not supported + EOF + test_cmp expect actual-error && + + git -C "$upstream" show-ref >out && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + refs/heads/master + EOF + test_cmp expect actual +' + +test_expect_success "setup proc-receive hook (hook --die-version, $PROTOCOL)" ' + write_script "$upstream/hooks/proc-receive" <<-EOF + printf >&2 "# proc-receive hook\n" + test-tool proc-receive -v --die-version + EOF +' + +# Refs of upstream : master(A) +# Refs of workbench: master(A) tags/v123 +# git push : refs/for/master/topic(A) +test_expect_success "proc-receive: bad protocol (hook --die-version, $PROTOCOL)" ' + test_must_fail git -C workbench push origin \ + HEAD:refs/for/master/topic \ + >out 2>&1 && + make_user_friendly_and_stable_output actual && + + cat >expect <<-EOF && + remote: # pre-receive hook + remote: pre-receive< refs/for/master/topic + remote: # proc-receive hook + remote: fatal: bad protocol version: 1 + remote: error: proc-receive version "0" is not supported + To + ! [remote rejected] HEAD -> refs/for/master/topic (fail to run proc-receive hook) + EOF + test_cmp expect actual && + + git -C "$upstream" show-ref >out && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + refs/heads/master + EOF + test_cmp expect actual +' + +test_expect_success "setup proc-receive hook (hook --die-readline, $PROTOCOL)" ' + write_script "$upstream/hooks/proc-receive" <<-EOF + printf >&2 "# proc-receive hook\n" + test-tool proc-receive -v --die-readline + EOF +' + +# Refs of upstream : master(A) +# Refs of workbench: master(A) tags/v123 +# git push : refs/for/master/topic(A) +test_expect_success "proc-receive: bad protocol (hook --die-readline, $PROTOCOL)" ' + test_must_fail git -C workbench push origin \ + HEAD:refs/for/master/topic \ + >out 2>&1 && + make_user_friendly_and_stable_output actual && + + cat >expect <<-EOF && + remote: # pre-receive hook + remote: pre-receive< refs/for/master/topic + remote: # proc-receive hook + remote: fatal: protocol error: expected "old new ref", got " refs/for/master/topic" + To + ! [remote rejected] HEAD -> refs/for/master/topic (proc-receive failed to report status) + EOF + test_cmp expect actual && + + git -C "$upstream" show-ref >out && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + refs/heads/master + EOF + test_cmp expect actual +' + +test_expect_success "setup proc-receive hook (no report, $PROTOCOL)" ' + write_script "$upstream/hooks/proc-receive" <<-EOF + printf >&2 "# proc-receive hook\n" + test-tool proc-receive -v + EOF +' + +# Refs of upstream : master(A) +# Refs of workbench: master(A) tags/v123 +# git push : next(A) refs/for/master/topic(A) +test_expect_success "proc-receive: bad protocol (no report, $PROTOCOL)" ' + test_must_fail git -C workbench push origin \ + HEAD:refs/heads/next \ + HEAD:refs/for/master/topic >out 2>&1 && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + remote: # pre-receive hook + remote: pre-receive< refs/heads/next + remote: pre-receive< refs/for/master/topic + remote: # proc-receive hook + remote: proc-receive< refs/for/master/topic + remote: # post-receive hook + remote: post-receive< refs/heads/next + To + * [new branch] HEAD -> next + ! [remote rejected] HEAD -> refs/for/master/topic (proc-receive failed to report status) + EOF + test_cmp expect actual && + git -C "$upstream" show-ref >out && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + refs/heads/master + refs/heads/next + EOF + test_cmp expect actual +' + +# Refs of upstream : master(A) next(A) +# Refs of workbench: master(A) tags/v123 +test_expect_success "cleanup ($PROTOCOL)" ' + git -C "$upstream" update-ref -d refs/heads/next + +' + +test_expect_success "setup proc-receive hook (no ref, $PROTOCOL)" ' + write_script "$upstream/hooks/proc-receive" <<-EOF + printf >&2 "# proc-receive hook\n" + test-tool proc-receive -v \ + -r "ok" + EOF +' + +# Refs of upstream : master(A) +# Refs of workbench: master(A) tags/v123 +# git push : refs/for/master/topic +test_expect_success "proc-receive: bad protocol (no ref, $PROTOCOL)" ' + test_must_fail git -C workbench push origin \ + HEAD:refs/for/master/topic\ + >out 2>&1 && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + remote: # pre-receive hook + remote: pre-receive< refs/for/master/topic + remote: # proc-receive hook + remote: proc-receive< refs/for/master/topic + remote: proc-receive> ok + remote: error: proc-receive expected " ...", got "ok" + To + ! [remote rejected] HEAD -> refs/for/master/topic (proc-receive failed to report status) + EOF + test_cmp expect actual && + git -C "$upstream" show-ref >out && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + refs/heads/master + EOF + test_cmp expect actual +' + +test_expect_success "setup proc-receive hook (unknown status, $PROTOCOL)" ' + write_script "$upstream/hooks/proc-receive" <<-EOF + printf >&2 "# proc-receive hook\n" + test-tool proc-receive -v \ + -r "xx refs/for/master/topic" + EOF +' + +# Refs of upstream : master(A) +# Refs of workbench: master(A) tags/v123 +# git push : refs/for/master/topic +test_expect_success "proc-receive: bad protocol (unknown status, $PROTOCOL)" ' + test_must_fail git -C workbench push origin \ + HEAD:refs/for/master/topic \ + >out 2>&1 && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + remote: # pre-receive hook + remote: pre-receive< refs/for/master/topic + remote: # proc-receive hook + remote: proc-receive< refs/for/master/topic + remote: proc-receive> xx refs/for/master/topic + remote: error: proc-receive reported bad status "xx" on ref "refs/for/master/topic" + To + ! [remote rejected] HEAD -> refs/for/master/topic (proc-receive failed to report status) + EOF + test_cmp expect actual && + git -C "$upstream" show-ref >out && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + refs/heads/master + EOF + test_cmp expect actual +' diff --git a/t/t5411/test-0014-bad-protocol--porcelain.sh b/t/t5411/test-0014-bad-protocol--porcelain.sh new file mode 100644 index 0000000000..96bbed08fe --- /dev/null +++ b/t/t5411/test-0014-bad-protocol--porcelain.sh @@ -0,0 +1,160 @@ +test_expect_success "setup proc-receive hook (unknown version, $PROTOCOL)" ' + write_script "$upstream/hooks/proc-receive" <<-EOF + printf >&2 "# proc-receive hook\n" + test-tool proc-receive -v --version 2 + EOF +' + +# Refs of upstream : master(A) +# Refs of workbench: master(A) tags/v123 +# git push : refs/for/master/topic(A) +test_expect_success "proc-receive: bad protocol (unknown version, --porcelain, $PROTOCOL)" ' + test_must_fail git -C workbench push --porcelain origin \ + HEAD:refs/for/master/topic \ + >out 2>&1 && + make_user_friendly_and_stable_output actual && + + # Check status report for git-push + sed -n \ + -e "/^To / { p; n; p; n; p; }" \ + actual-report && + cat >expect <<-EOF && + To + ! HEAD:refs/for/master/topic [remote rejected] (fail to run proc-receive hook) + Done + EOF + test_cmp expect actual-report && + + # Check error message from "receive-pack", but ignore unstable fatal error + # message ("remote: fatal: the remote end hung up unexpectedly") which + # is different from the remote HTTP server with different locale settings. + grep "^remote: error:" actual-error && + cat >expect <<-EOF && + remote: error: proc-receive version "2" is not supported + EOF + test_cmp expect actual-error && + + git -C "$upstream" show-ref >out && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + refs/heads/master + EOF + test_cmp expect actual +' + +test_expect_success "setup proc-receive hook (no report, $PROTOCOL)" ' + write_script "$upstream/hooks/proc-receive" <<-EOF + printf >&2 "# proc-receive hook\n" + test-tool proc-receive -v + EOF +' + +# Refs of upstream : master(A) +# Refs of workbench: master(A) tags/v123 +# git push : next(A) refs/for/master/topic(A) +test_expect_success "proc-receive: bad protocol (no report, --porcelain, $PROTOCOL)" ' + test_must_fail git -C workbench push --porcelain origin \ + HEAD:refs/heads/next \ + HEAD:refs/for/master/topic >out 2>&1 && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + remote: # pre-receive hook + remote: pre-receive< refs/heads/next + remote: pre-receive< refs/for/master/topic + remote: # proc-receive hook + remote: proc-receive< refs/for/master/topic + remote: # post-receive hook + remote: post-receive< refs/heads/next + To + * HEAD:refs/heads/next [new branch] + ! HEAD:refs/for/master/topic [remote rejected] (proc-receive failed to report status) + Done + EOF + test_cmp expect actual && + git -C "$upstream" show-ref >out && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + refs/heads/master + refs/heads/next + EOF + test_cmp expect actual +' + +# Refs of upstream : master(A) next(A) +# Refs of workbench: master(A) tags/v123 +test_expect_success "cleanup ($PROTOCOL)" ' + git -C "$upstream" update-ref -d refs/heads/next + +' + +test_expect_success "setup proc-receive hook (no ref, $PROTOCOL)" ' + write_script "$upstream/hooks/proc-receive" <<-EOF + printf >&2 "# proc-receive hook\n" + test-tool proc-receive -v \ + -r "ok" + EOF +' + +# Refs of upstream : master(A) +# Refs of workbench: master(A) tags/v123 +# git push : refs/for/master/topic +test_expect_success "proc-receive: bad protocol (no ref, --porcelain, $PROTOCOL)" ' + test_must_fail git -C workbench push --porcelain origin \ + HEAD:refs/for/master/topic\ + >out 2>&1 && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + remote: # pre-receive hook + remote: pre-receive< refs/for/master/topic + remote: # proc-receive hook + remote: proc-receive< refs/for/master/topic + remote: proc-receive> ok + remote: error: proc-receive expected " ...", got "ok" + To + ! HEAD:refs/for/master/topic [remote rejected] (proc-receive failed to report status) + Done + EOF + test_cmp expect actual && + git -C "$upstream" show-ref >out && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + refs/heads/master + EOF + test_cmp expect actual +' + +test_expect_success "setup proc-receive hook (unknown status, $PROTOCOL)" ' + write_script "$upstream/hooks/proc-receive" <<-EOF + printf >&2 "# proc-receive hook\n" + test-tool proc-receive -v \ + -r "xx refs/for/master/topic" + EOF +' + +# Refs of upstream : master(A) +# Refs of workbench: master(A) tags/v123 +# git push : refs/for/master/topic +test_expect_success "proc-receive: bad protocol (unknown status, --porcelain, $PROTOCOL)" ' + test_must_fail git -C workbench push --porcelain origin \ + HEAD:refs/for/master/topic \ + >out 2>&1 && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + remote: # pre-receive hook + remote: pre-receive< refs/for/master/topic + remote: # proc-receive hook + remote: proc-receive< refs/for/master/topic + remote: proc-receive> xx refs/for/master/topic + remote: error: proc-receive reported bad status "xx" on ref "refs/for/master/topic" + To + ! HEAD:refs/for/master/topic [remote rejected] (proc-receive failed to report status) + Done + EOF + test_cmp expect actual && + git -C "$upstream" show-ref >out && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + refs/heads/master + EOF + test_cmp expect actual +' diff --git a/t/t5411/test-0020-report-ng.sh b/t/t5411/test-0020-report-ng.sh new file mode 100644 index 0000000000..f726b7ca9c --- /dev/null +++ b/t/t5411/test-0020-report-ng.sh @@ -0,0 +1,67 @@ +test_expect_success "setup proc-receive hook (ng, no message, $PROTOCOL)" ' + write_script "$upstream/hooks/proc-receive" <<-EOF + printf >&2 "# proc-receive hook\n" + test-tool proc-receive -v \ + -r "ng refs/for/master/topic" + EOF +' + +# Refs of upstream : master(A) +# Refs of workbench: master(A) tags/v123 +# git push : refs/for/master/topic +test_expect_success "proc-receive: fail to update (ng, no message, $PROTOCOL)" ' + test_must_fail git -C workbench push origin \ + HEAD:refs/for/master/topic \ + >out 2>&1 && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + remote: # pre-receive hook + remote: pre-receive< refs/for/master/topic + remote: # proc-receive hook + remote: proc-receive< refs/for/master/topic + remote: proc-receive> ng refs/for/master/topic + To + ! [remote rejected] HEAD -> refs/for/master/topic (failed) + EOF + test_cmp expect actual && + git -C "$upstream" show-ref >out && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + refs/heads/master + EOF + test_cmp expect actual +' + +test_expect_success "setup proc-receive hook (ng message, $PROTOCOL)" ' + write_script "$upstream/hooks/proc-receive" <<-EOF + printf >&2 "# proc-receive hook\n" + test-tool proc-receive -v \ + -r "ng refs/for/master/topic error msg" + EOF +' + +# Refs of upstream : master(A) +# Refs of workbench: master(A) tags/v123 +# git push : refs/for/master/topic +test_expect_success "proc-receive: fail to update (ng, with message, $PROTOCOL)" ' + test_must_fail git -C workbench push origin \ + HEAD:refs/for/master/topic \ + >out 2>&1 && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + remote: # pre-receive hook + remote: pre-receive< refs/for/master/topic + remote: # proc-receive hook + remote: proc-receive< refs/for/master/topic + remote: proc-receive> ng refs/for/master/topic error msg + To + ! [remote rejected] HEAD -> refs/for/master/topic (error msg) + EOF + test_cmp expect actual && + git -C "$upstream" show-ref >out && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + refs/heads/master + EOF + test_cmp expect actual +' diff --git a/t/t5411/test-0021-report-ng--porcelain.sh b/t/t5411/test-0021-report-ng--porcelain.sh new file mode 100644 index 0000000000..5c90d63287 --- /dev/null +++ b/t/t5411/test-0021-report-ng--porcelain.sh @@ -0,0 +1,69 @@ +test_expect_success "setup proc-receive hook (ng, no message, $PROTOCOL)" ' + write_script "$upstream/hooks/proc-receive" <<-EOF + printf >&2 "# proc-receive hook\n" + test-tool proc-receive -v \ + -r "ng refs/for/master/topic" + EOF +' + +# Refs of upstream : master(A) +# Refs of workbench: master(A) tags/v123 +# git push : refs/for/master/topic +test_expect_success "proc-receive: fail to update (ng, no message, --porcelain, $PROTOCOL)" ' + test_must_fail git -C workbench push --porcelain origin \ + HEAD:refs/for/master/topic \ + >out 2>&1 && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + remote: # pre-receive hook + remote: pre-receive< refs/for/master/topic + remote: # proc-receive hook + remote: proc-receive< refs/for/master/topic + remote: proc-receive> ng refs/for/master/topic + To + ! HEAD:refs/for/master/topic [remote rejected] (failed) + Done + EOF + test_cmp expect actual && + git -C "$upstream" show-ref >out && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + refs/heads/master + EOF + test_cmp expect actual +' + +test_expect_success "setup proc-receive hook (ng message, $PROTOCOL)" ' + write_script "$upstream/hooks/proc-receive" <<-EOF + printf >&2 "# proc-receive hook\n" + test-tool proc-receive -v \ + -r "ng refs/for/master/topic error msg" + EOF +' + +# Refs of upstream : master(A) +# Refs of workbench: master(A) tags/v123 +# git push : refs/for/master/topic +test_expect_success "proc-receive: fail to update (ng, with message, --porcelain, $PROTOCOL)" ' + test_must_fail git -C workbench push --porcelain origin \ + HEAD:refs/for/master/topic \ + >out 2>&1 && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + remote: # pre-receive hook + remote: pre-receive< refs/for/master/topic + remote: # proc-receive hook + remote: proc-receive< refs/for/master/topic + remote: proc-receive> ng refs/for/master/topic error msg + To + ! HEAD:refs/for/master/topic [remote rejected] (error msg) + Done + EOF + test_cmp expect actual && + git -C "$upstream" show-ref >out && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + refs/heads/master + EOF + test_cmp expect actual +' diff --git a/t/t5411/test-0022-report-unexpect-ref.sh b/t/t5411/test-0022-report-unexpect-ref.sh new file mode 100644 index 0000000000..92a415b929 --- /dev/null +++ b/t/t5411/test-0022-report-unexpect-ref.sh @@ -0,0 +1,45 @@ +test_expect_success "setup proc-receive hook (unexpected ref, $PROTOCOL)" ' + write_script "$upstream/hooks/proc-receive" <<-EOF + printf >&2 "# proc-receive hook\n" + test-tool proc-receive -v \ + -r "ok refs/heads/master" + EOF +' + +# Refs of upstream : master(A) +# Refs of workbench: master(A) tags/v123 +# git push : (B) refs/for/master/topic +test_expect_success "proc-receive: report unexpected ref ($PROTOCOL)" ' + test_must_fail git -C workbench push origin \ + $B:refs/heads/master \ + HEAD:refs/for/master/topic \ + >out 2>&1 && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + remote: # pre-receive hook + remote: pre-receive< refs/heads/master + remote: pre-receive< refs/for/master/topic + remote: # proc-receive hook + remote: proc-receive< refs/for/master/topic + remote: proc-receive> ok refs/heads/master + remote: error: proc-receive reported status on unexpected ref: refs/heads/master + remote: # post-receive hook + remote: post-receive< refs/heads/master + To + .. -> master + ! [remote rejected] HEAD -> refs/for/master/topic (proc-receive failed to report status) + EOF + test_cmp expect actual && + git -C "$upstream" show-ref >out && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + refs/heads/master + EOF + test_cmp expect actual +' + +# Refs of upstream : master(B) +# Refs of workbench: master(A) tags/v123 +test_expect_success "cleanup ($PROTOCOL)" ' + git -C "$upstream" update-ref refs/heads/master $A +' diff --git a/t/t5411/test-0023-report-unexpect-ref--porcelain.sh b/t/t5411/test-0023-report-unexpect-ref--porcelain.sh new file mode 100644 index 0000000000..f10715c2dc --- /dev/null +++ b/t/t5411/test-0023-report-unexpect-ref--porcelain.sh @@ -0,0 +1,46 @@ +test_expect_success "setup proc-receive hook (unexpected ref, $PROTOCOL)" ' + write_script "$upstream/hooks/proc-receive" <<-EOF + printf >&2 "# proc-receive hook\n" + test-tool proc-receive -v \ + -r "ok refs/heads/master" + EOF +' + +# Refs of upstream : master(A) +# Refs of workbench: master(A) tags/v123 +# git push : (B) refs/for/master/topic +test_expect_success "proc-receive: report unexpected ref (--porcelain, $PROTOCOL)" ' + test_must_fail git -C workbench push --porcelain origin \ + $B:refs/heads/master \ + HEAD:refs/for/master/topic \ + >out 2>&1 && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + remote: # pre-receive hook + remote: pre-receive< refs/heads/master + remote: pre-receive< refs/for/master/topic + remote: # proc-receive hook + remote: proc-receive< refs/for/master/topic + remote: proc-receive> ok refs/heads/master + remote: error: proc-receive reported status on unexpected ref: refs/heads/master + remote: # post-receive hook + remote: post-receive< refs/heads/master + To + :refs/heads/master .. + ! HEAD:refs/for/master/topic [remote rejected] (proc-receive failed to report status) + Done + EOF + test_cmp expect actual && + git -C "$upstream" show-ref >out && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + refs/heads/master + EOF + test_cmp expect actual +' + +# Refs of upstream : master(B) +# Refs of workbench: master(A) tags/v123 +test_expect_success "cleanup ($PROTOCOL)" ' + git -C "$upstream" update-ref refs/heads/master $A +' diff --git a/t/t5411/test-0024-report-unknown-ref.sh b/t/t5411/test-0024-report-unknown-ref.sh new file mode 100644 index 0000000000..c3946f329a --- /dev/null +++ b/t/t5411/test-0024-report-unknown-ref.sh @@ -0,0 +1,34 @@ +test_expect_success "setup proc-receive hook (unexpected ref, $PROTOCOL)" ' + write_script "$upstream/hooks/proc-receive" <<-EOF + printf >&2 "# proc-receive hook\n" + test-tool proc-receive -v \ + -r "ok refs/for/master/topic" + EOF +' + +# Refs of upstream : master(A) +# Refs of workbench: master(A) tags/v123 +# git push : refs/for/a/b/c/my/topic +test_expect_success "proc-receive: report unknown reference ($PROTOCOL)" ' + test_must_fail git -C workbench push origin \ + HEAD:refs/for/a/b/c/my/topic \ + >out 2>&1 && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + remote: # pre-receive hook + remote: pre-receive< refs/for/a/b/c/my/topic + remote: # proc-receive hook + remote: proc-receive< refs/for/a/b/c/my/topic + remote: proc-receive> ok refs/for/master/topic + remote: error: proc-receive reported status on unknown ref: refs/for/master/topic + To + ! [remote rejected] HEAD -> refs/for/a/b/c/my/topic (proc-receive failed to report status) + EOF + test_cmp expect actual && + git -C "$upstream" show-ref >out && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + refs/heads/master + EOF + test_cmp expect actual +' diff --git a/t/t5411/test-0025-report-unknown-ref--porcelain.sh b/t/t5411/test-0025-report-unknown-ref--porcelain.sh new file mode 100644 index 0000000000..b5a5d9b992 --- /dev/null +++ b/t/t5411/test-0025-report-unknown-ref--porcelain.sh @@ -0,0 +1,35 @@ +test_expect_success "setup proc-receive hook (unexpected ref, $PROTOCOL)" ' + write_script "$upstream/hooks/proc-receive" <<-EOF + printf >&2 "# proc-receive hook\n" + test-tool proc-receive -v \ + -r "ok refs/for/master/topic" + EOF +' + +# Refs of upstream : master(A) +# Refs of workbench: master(A) tags/v123 +# git push : refs/for/a/b/c/my/topic +test_expect_success "proc-receive: report unknown reference (--porcelain, $PROTOCOL)" ' + test_must_fail git -C workbench push --porcelain origin \ + HEAD:refs/for/a/b/c/my/topic \ + >out 2>&1 && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + remote: # pre-receive hook + remote: pre-receive< refs/for/a/b/c/my/topic + remote: # proc-receive hook + remote: proc-receive< refs/for/a/b/c/my/topic + remote: proc-receive> ok refs/for/master/topic + remote: error: proc-receive reported status on unknown ref: refs/for/master/topic + To + ! HEAD:refs/for/a/b/c/my/topic [remote rejected] (proc-receive failed to report status) + Done + EOF + test_cmp expect actual && + git -C "$upstream" show-ref >out && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + refs/heads/master + EOF + test_cmp expect actual +' diff --git a/t/t5411/test-0026-push-options.sh b/t/t5411/test-0026-push-options.sh new file mode 100644 index 0000000000..d0c4da8b23 --- /dev/null +++ b/t/t5411/test-0026-push-options.sh @@ -0,0 +1,79 @@ +test_expect_success "setup proc-receive hook and disable push-options ($PROTOCOL)" ' + git -C "$upstream" config receive.advertisePushOptions false && + write_script "$upstream/hooks/proc-receive" <<-EOF + printf >&2 "# proc-receive hook\n" + test-tool proc-receive -v \ + -r "ok refs/for/master/topic" + EOF +' + +# Refs of upstream : master(A) +# Refs of workbench: master(A) tags/v123 +# git push -o ... : refs/for/master/topic +test_expect_success "proc-receive: not support push options ($PROTOCOL)" ' + test_must_fail git -C workbench push \ + -o issue=123 \ + -o reviewer=user1 \ + origin \ + HEAD:refs/for/master/topic \ + >out 2>&1 && + make_user_friendly_and_stable_output actual && + test_i18ngrep "fatal: the receiving end does not support push options" \ + actual && + git -C "$upstream" show-ref >out && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + refs/heads/master + EOF + test_cmp expect actual +' + +test_expect_success "enable push options ($PROTOCOL)" ' + git -C "$upstream" config receive.advertisePushOptions true +' + +# Refs of upstream : master(A) +# Refs of workbench: master(A) tags/v123 +# git push -o ... : next(A) refs/for/master/topic +test_expect_success "proc-receive: push with options ($PROTOCOL)" ' + git -C workbench push \ + --atomic \ + -o issue=123 \ + -o reviewer=user1 \ + origin \ + HEAD:refs/heads/next \ + HEAD:refs/for/master/topic \ + >out 2>&1 && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + remote: # pre-receive hook + remote: pre-receive< refs/heads/next + remote: pre-receive< refs/for/master/topic + remote: # proc-receive hook + remote: proc-receive: atomic push_options + remote: proc-receive< refs/for/master/topic + remote: proc-receive< issue=123 + remote: proc-receive< reviewer=user1 + remote: proc-receive> ok refs/for/master/topic + remote: # post-receive hook + remote: post-receive< refs/heads/next + remote: post-receive< refs/for/master/topic + To + * [new branch] HEAD -> next + * [new reference] HEAD -> refs/for/master/topic + EOF + test_cmp expect actual && + git -C "$upstream" show-ref >out && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + refs/heads/master + refs/heads/next + EOF + test_cmp expect actual +' + +# Refs of upstream : master(A) next(A) +# Refs of workbench: master(A) tags/v123 +test_expect_success "cleanup ($PROTOCOL)" ' + git -C "$upstream" update-ref -d refs/heads/next +' diff --git a/t/t5411/test-0027-push-options--porcelain.sh b/t/t5411/test-0027-push-options--porcelain.sh new file mode 100644 index 0000000000..243580db93 --- /dev/null +++ b/t/t5411/test-0027-push-options--porcelain.sh @@ -0,0 +1,82 @@ +test_expect_success "setup proc-receive hook and disable push-options ($PROTOCOL)" ' + git -C "$upstream" config receive.advertisePushOptions false && + write_script "$upstream/hooks/proc-receive" <<-EOF + printf >&2 "# proc-receive hook\n" + test-tool proc-receive -v \ + -r "ok refs/for/master/topic" + EOF +' + +# Refs of upstream : master(A) +# Refs of workbench: master(A) tags/v123 +# git push -o ... : refs/for/master/topic +test_expect_success "proc-receive: not support push options (--porcelain, $PROTOCOL)" ' + test_must_fail git -C workbench push \ + --porcelain \ + -o issue=123 \ + -o reviewer=user1 \ + origin \ + HEAD:refs/for/master/topic \ + >out 2>&1 && + make_user_friendly_and_stable_output actual && + test_i18ngrep "fatal: the receiving end does not support push options" \ + actual && + git -C "$upstream" show-ref >out && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + refs/heads/master + EOF + test_cmp expect actual +' + +test_expect_success "enable push options ($PROTOCOL)" ' + git -C "$upstream" config receive.advertisePushOptions true +' + +# Refs of upstream : master(A) +# Refs of workbench: master(A) tags/v123 +# git push -o ... : next(A) refs/for/master/topic +test_expect_success "proc-receive: push with options (--porcelain, $PROTOCOL)" ' + git -C workbench push \ + --porcelain \ + --atomic \ + -o issue=123 \ + -o reviewer=user1 \ + origin \ + HEAD:refs/heads/next \ + HEAD:refs/for/master/topic \ + >out 2>&1 && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + remote: # pre-receive hook + remote: pre-receive< refs/heads/next + remote: pre-receive< refs/for/master/topic + remote: # proc-receive hook + remote: proc-receive: atomic push_options + remote: proc-receive< refs/for/master/topic + remote: proc-receive< issue=123 + remote: proc-receive< reviewer=user1 + remote: proc-receive> ok refs/for/master/topic + remote: # post-receive hook + remote: post-receive< refs/heads/next + remote: post-receive< refs/for/master/topic + To + * HEAD:refs/heads/next [new branch] + * HEAD:refs/for/master/topic [new reference] + Done + EOF + test_cmp expect actual && + git -C "$upstream" show-ref >out && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + refs/heads/master + refs/heads/next + EOF + test_cmp expect actual +' + +# Refs of upstream : master(A) next(A) +# Refs of workbench: master(A) tags/v123 +test_expect_success "cleanup ($PROTOCOL)" ' + git -C "$upstream" update-ref -d refs/heads/next +' diff --git a/t/t5411/test-0030-report-ok.sh b/t/t5411/test-0030-report-ok.sh new file mode 100644 index 0000000000..44c99d3831 --- /dev/null +++ b/t/t5411/test-0030-report-ok.sh @@ -0,0 +1,35 @@ +test_expect_success "setup proc-receive hook (ok, $PROTOCOL)" ' + write_script "$upstream/hooks/proc-receive" <<-EOF + printf >&2 "# proc-receive hook\n" + test-tool proc-receive -v \ + -r "ok refs/for/master/topic" + EOF +' + +# Refs of upstream : master(A) +# Refs of workbench: master(A) tags/v123 +# git push : refs/for/master/topic +test_expect_success "proc-receive: ok ($PROTOCOL)" ' + git -C workbench push origin \ + HEAD:refs/for/master/topic \ + >out 2>&1 && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + remote: # pre-receive hook + remote: pre-receive< refs/for/master/topic + remote: # proc-receive hook + remote: proc-receive< refs/for/master/topic + remote: proc-receive> ok refs/for/master/topic + remote: # post-receive hook + remote: post-receive< refs/for/master/topic + To + * [new reference] HEAD -> refs/for/master/topic + EOF + test_cmp expect actual && + git -C "$upstream" show-ref >out && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + refs/heads/master + EOF + test_cmp expect actual +' diff --git a/t/t5411/test-0031-report-ok--porcelain.sh b/t/t5411/test-0031-report-ok--porcelain.sh new file mode 100644 index 0000000000..2a10bdc749 --- /dev/null +++ b/t/t5411/test-0031-report-ok--porcelain.sh @@ -0,0 +1,36 @@ +test_expect_success "setup proc-receive hook (ok, $PROTOCOL)" ' + write_script "$upstream/hooks/proc-receive" <<-EOF + printf >&2 "# proc-receive hook\n" + test-tool proc-receive -v \ + -r "ok refs/for/master/topic" + EOF +' + +# Refs of upstream : master(A) +# Refs of workbench: master(A) tags/v123 +# git push : refs/for/master/topic +test_expect_success "proc-receive: ok (--porcelain, $PROTOCOL)" ' + git -C workbench push --porcelain origin \ + HEAD:refs/for/master/topic \ + >out 2>&1 && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + remote: # pre-receive hook + remote: pre-receive< refs/for/master/topic + remote: # proc-receive hook + remote: proc-receive< refs/for/master/topic + remote: proc-receive> ok refs/for/master/topic + remote: # post-receive hook + remote: post-receive< refs/for/master/topic + To + * HEAD:refs/for/master/topic [new reference] + Done + EOF + test_cmp expect actual && + git -C "$upstream" show-ref >out && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + refs/heads/master + EOF + test_cmp expect actual +' diff --git a/t/t5411/test-0032-report-alt.sh b/t/t5411/test-0032-report-alt.sh new file mode 100644 index 0000000000..dec4afc4c1 --- /dev/null +++ b/t/t5411/test-0032-report-alt.sh @@ -0,0 +1,229 @@ +test_expect_success "setup proc-receive hook (alt , $PROTOCOL)" ' + write_script "$upstream/hooks/proc-receive" <<-EOF + printf >&2 "# proc-receive hook\n" + test-tool proc-receive -v \ + -r "alt refs/for/master/topic" + EOF +' + +# Refs of upstream : master(A) +# Refs of workbench: master(A) tags/v123 +# git push : refs/for/next/topic(A) refs/for/a/b/c/topic(A) refs/for/master/topic(A) +test_expect_success "proc-receive: report alt (alt , $PROTOCOL)" ' + test_must_fail git -C workbench push origin \ + HEAD:refs/for/master/topic \ + >out 2>&1 && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + remote: # pre-receive hook + remote: pre-receive< refs/for/master/topic + remote: # proc-receive hook + remote: proc-receive< refs/for/master/topic + remote: proc-receive> alt refs/for/master/topic + remote: error: proc-receive expected "alt ...", got "alt refs/for/master/topic" + To + ! [remote rejected] HEAD -> refs/for/master/topic (proc-receive failed to report status) + EOF + test_cmp expect actual +' + +test_expect_success "setup proc-receive hook (alt , $PROTOCOL)" ' + write_script "$upstream/hooks/proc-receive" <<-EOF + printf >&2 "# proc-receive hook\n" + test-tool proc-receive -v \ + -r "alt refs/for/master/topic refs/pull/123/head" + EOF +' + +# Refs of upstream : master(A) +# Refs of workbench: master(A) tags/v123 +# git push : refs/for/next/topic(A) refs/for/a/b/c/topic(A) refs/for/master/topic(A) +test_expect_success "proc-receive: report alt (alt , $PROTOCOL)" ' + git -C workbench push origin \ + HEAD:refs/for/master/topic \ + >out 2>&1 && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + remote: # pre-receive hook + remote: pre-receive< refs/for/master/topic + remote: # proc-receive hook + remote: proc-receive< refs/for/master/topic + remote: proc-receive> alt refs/for/master/topic refs/pull/123/head + remote: # post-receive hook + remote: post-receive< refs/for/master/topic + To + * [new reference] HEAD -> refs/for/master/topic + EOF + test_cmp expect actual +' + +test_expect_success "setup proc-receive hook (alt forced-update, $PROTOCOL)" ' + write_script "$upstream/hooks/proc-receive" <<-EOF + printf >&2 "# proc-receive hook\n" + test-tool proc-receive -v \ + -r "alt refs/for/master/topic refs/pull/123/head forced-update" + EOF +' + +# Refs of upstream : master(A) +# Refs of workbench: master(A) tags/v123 +# git push : refs/for/next/topic(A) refs/for/a/b/c/topic(A) refs/for/master/topic(A) +test_expect_success "proc-receive: report alt (alt forced-update, $PROTOCOL)" ' + git -C workbench push origin \ + HEAD:refs/for/master/topic \ + >out 2>&1 && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + remote: # pre-receive hook + remote: pre-receive< refs/for/master/topic + remote: # proc-receive hook + remote: proc-receive< refs/for/master/topic + remote: proc-receive> alt refs/for/master/topic refs/pull/123/head forced-update + remote: # post-receive hook + remote: post-receive< refs/for/master/topic + To + * [new reference] HEAD -> refs/for/master/topic + EOF + test_cmp expect actual +' + +test_expect_success "setup proc-receive hook (alt old-oid=X, $PROTOCOL)" ' + write_script "$upstream/hooks/proc-receive" <<-EOF + printf >&2 "# proc-receive hook\n" + test-tool proc-receive -v \ + -r "alt refs/for/master/topic refs/pull/123/head old-oid=$B" + EOF +' + +# Refs of upstream : master(A) +# Refs of workbench: master(A) tags/v123 +# git push : refs/for/next/topic(A) refs/for/a/b/c/topic(A) refs/for/master/topic(A) +test_expect_success "proc-receive: report alt (alt old-oid=X, $PROTOCOL)" ' + git -C workbench push origin \ + HEAD:refs/for/master/topic \ + >out 2>&1 && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + remote: # pre-receive hook + remote: pre-receive< refs/for/master/topic + remote: # proc-receive hook + remote: proc-receive< refs/for/master/topic + remote: proc-receive> alt refs/for/master/topic refs/pull/123/head old-oid= + remote: # post-receive hook + remote: post-receive< refs/for/master/topic + To + * [new reference] HEAD -> refs/for/master/topic + EOF + test_cmp expect actual +' + +test_expect_success "setup proc-receive hook (alt old-oid=X, $PROTOCOL)" ' + write_script "$upstream/hooks/proc-receive" <<-EOF + printf >&2 "# proc-receive hook\n" + test-tool proc-receive -v \ + -r "alt refs/for/master/topic old-oid=$B" + EOF +' + +# Refs of upstream : master(A) +# Refs of workbench: master(A) tags/v123 +# git push : refs/for/next/topic(A) refs/for/a/b/c/topic(A) refs/for/master/topic(A) +test_expect_success "proc-receive: report alt (alt old-oid=X, $PROTOCOL)" ' + git -C workbench push origin \ + HEAD:refs/for/master/topic \ + >out 2>&1 && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + remote: # pre-receive hook + remote: pre-receive< refs/for/master/topic + remote: # proc-receive hook + remote: proc-receive< refs/for/master/topic + remote: proc-receive> alt refs/for/master/topic old-oid= + remote: # post-receive hook + remote: post-receive< refs/for/master/topic + To + * [new reference] HEAD -> refs/for/master/topic + EOF + test_cmp expect actual +' + +test_expect_success "setup proc-receive hook (alt old-oid=X new-oid=Y, $PROTOCOL)" ' + write_script "$upstream/hooks/proc-receive" <<-EOF + printf >&2 "# proc-receive hook\n" + test-tool proc-receive -v \ + -r "alt refs/for/master/topic old-oid=$A new-oid=$B" + EOF +' + +# Refs of upstream : master(A) +# Refs of workbench: master(A) tags/v123 +# git push : refs/for/next/topic(A) refs/for/a/b/c/topic(A) refs/for/master/topic(A) +test_expect_success "proc-receive: report alt (alt old-oid=X new-oid=Y, $PROTOCOL)" ' + git -C workbench push origin \ + HEAD:refs/for/master/topic \ + >out 2>&1 && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + remote: # pre-receive hook + remote: pre-receive< refs/for/master/topic + remote: # proc-receive hook + remote: proc-receive< refs/for/master/topic + remote: proc-receive> alt refs/for/master/topic old-oid= new-oid= + remote: # post-receive hook + remote: post-receive< refs/for/master/topic + To + * [new reference] HEAD -> refs/for/master/topic + EOF + test_cmp expect actual +' + +test_expect_success "setup proc-receive hook (with multiple alt reports, $PROTOCOL)" ' + write_script "$upstream/hooks/proc-receive" <<-EOF + printf >&2 "# proc-receive hook\n" + test-tool proc-receive -v \ + -r "ok refs/for/a/b/c/topic" \ + -r "alt refs/for/next/topic refs/pull/123/head" \ + -r "alt refs/for/master/topic refs/pull/124/head old-oid=$B forced-update new-oid=$A" + EOF +' + +# Refs of upstream : master(A) +# Refs of workbench: master(A) tags/v123 +# git push : refs/for/next/topic(A) refs/for/a/b/c/topic(A) refs/for/master/topic(A) +test_expect_success "proc-receive: with multiple alt reports ($PROTOCOL)" ' + git -C workbench push origin \ + HEAD:refs/for/next/topic \ + HEAD:refs/for/a/b/c/topic \ + HEAD:refs/for/master/topic \ + >out 2>&1 && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + remote: # pre-receive hook + remote: pre-receive< refs/for/next/topic + remote: pre-receive< refs/for/a/b/c/topic + remote: pre-receive< refs/for/master/topic + remote: # proc-receive hook + remote: proc-receive< refs/for/next/topic + remote: proc-receive< refs/for/a/b/c/topic + remote: proc-receive< refs/for/master/topic + remote: proc-receive> ok refs/for/a/b/c/topic + remote: proc-receive> alt refs/for/next/topic refs/pull/123/head + remote: proc-receive> alt refs/for/master/topic refs/pull/124/head old-oid= forced-update new-oid= + remote: # post-receive hook + remote: post-receive< refs/for/next/topic + remote: post-receive< refs/for/a/b/c/topic + remote: post-receive< refs/for/master/topic + To + * [new reference] HEAD -> refs/for/next/topic + * [new reference] HEAD -> refs/for/a/b/c/topic + * [new reference] HEAD -> refs/for/master/topic + EOF + test_cmp expect actual && + + git -C "$upstream" show-ref >out && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + refs/heads/master + EOF + test_cmp expect actual +' diff --git a/t/t5411/test-0033-report-alt--porcelain.sh b/t/t5411/test-0033-report-alt--porcelain.sh new file mode 100644 index 0000000000..49d76892ab --- /dev/null +++ b/t/t5411/test-0033-report-alt--porcelain.sh @@ -0,0 +1,236 @@ +test_expect_success "setup proc-receive hook (alt , --porcelain, $PROTOCOL)" ' + write_script "$upstream/hooks/proc-receive" <<-EOF + printf >&2 "# proc-receive hook\n" + test-tool proc-receive -v \ + -r "alt refs/for/master/topic" + EOF +' + +# Refs of upstream : master(A) +# Refs of workbench: master(A) tags/v123 +# git push : refs/for/next/topic(A) refs/for/a/b/c/topic(A) refs/for/master/topic(A) +test_expect_success "proc-receive: report alt (alt , --porcelain, $PROTOCOL)" ' + test_must_fail git -C workbench push --porcelain origin \ + HEAD:refs/for/master/topic \ + >out 2>&1 && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + remote: # pre-receive hook + remote: pre-receive< refs/for/master/topic + remote: # proc-receive hook + remote: proc-receive< refs/for/master/topic + remote: proc-receive> alt refs/for/master/topic + remote: error: proc-receive expected "alt ...", got "alt refs/for/master/topic" + To + ! HEAD:refs/for/master/topic [remote rejected] (proc-receive failed to report status) + Done + EOF + test_cmp expect actual +' + +test_expect_success "setup proc-receive hook (alt , --porcelain, $PROTOCOL)" ' + write_script "$upstream/hooks/proc-receive" <<-EOF + printf >&2 "# proc-receive hook\n" + test-tool proc-receive -v \ + -r "alt refs/for/master/topic refs/pull/123/head" + EOF +' + +# Refs of upstream : master(A) +# Refs of workbench: master(A) tags/v123 +# git push : refs/for/next/topic(A) refs/for/a/b/c/topic(A) refs/for/master/topic(A) +test_expect_success "proc-receive: report alt (alt , --porcelain, $PROTOCOL)" ' + git -C workbench push --porcelain origin \ + HEAD:refs/for/master/topic \ + >out 2>&1 && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + remote: # pre-receive hook + remote: pre-receive< refs/for/master/topic + remote: # proc-receive hook + remote: proc-receive< refs/for/master/topic + remote: proc-receive> alt refs/for/master/topic refs/pull/123/head + remote: # post-receive hook + remote: post-receive< refs/for/master/topic + To + * HEAD:refs/for/master/topic [new reference] + Done + EOF + test_cmp expect actual +' + +test_expect_success "setup proc-receive hook (alt forced-update, --porcelain, $PROTOCOL)" ' + write_script "$upstream/hooks/proc-receive" <<-EOF + printf >&2 "# proc-receive hook\n" + test-tool proc-receive -v \ + -r "alt refs/for/master/topic refs/pull/123/head forced-update" + EOF +' + +# Refs of upstream : master(A) +# Refs of workbench: master(A) tags/v123 +# git push : refs/for/next/topic(A) refs/for/a/b/c/topic(A) refs/for/master/topic(A) +test_expect_success "proc-receive: report alt (alt forced-update, --porcelain, $PROTOCOL)" ' + git -C workbench push --porcelain origin \ + HEAD:refs/for/master/topic \ + >out 2>&1 && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + remote: # pre-receive hook + remote: pre-receive< refs/for/master/topic + remote: # proc-receive hook + remote: proc-receive< refs/for/master/topic + remote: proc-receive> alt refs/for/master/topic refs/pull/123/head forced-update + remote: # post-receive hook + remote: post-receive< refs/for/master/topic + To + * HEAD:refs/for/master/topic [new reference] + Done + EOF + test_cmp expect actual +' + +test_expect_success "setup proc-receive hook (alt old-oid=X, --porcelain, $PROTOCOL)" ' + write_script "$upstream/hooks/proc-receive" <<-EOF + printf >&2 "# proc-receive hook\n" + test-tool proc-receive -v \ + -r "alt refs/for/master/topic refs/pull/123/head old-oid=$B" + EOF +' + +# Refs of upstream : master(A) +# Refs of workbench: master(A) tags/v123 +# git push : refs/for/next/topic(A) refs/for/a/b/c/topic(A) refs/for/master/topic(A) +test_expect_success "proc-receive: report alt (alt old-oid=X, --porcelain, $PROTOCOL)" ' + git -C workbench push --porcelain origin \ + HEAD:refs/for/master/topic \ + >out 2>&1 && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + remote: # pre-receive hook + remote: pre-receive< refs/for/master/topic + remote: # proc-receive hook + remote: proc-receive< refs/for/master/topic + remote: proc-receive> alt refs/for/master/topic refs/pull/123/head old-oid= + remote: # post-receive hook + remote: post-receive< refs/for/master/topic + To + * HEAD:refs/for/master/topic [new reference] + Done + EOF + test_cmp expect actual +' + +test_expect_success "setup proc-receive hook (alt old-oid=X, --porcelain, $PROTOCOL)" ' + write_script "$upstream/hooks/proc-receive" <<-EOF + printf >&2 "# proc-receive hook\n" + test-tool proc-receive -v \ + -r "alt refs/for/master/topic old-oid=$B" + EOF +' + +# Refs of upstream : master(A) +# Refs of workbench: master(A) tags/v123 +# git push : refs/for/next/topic(A) refs/for/a/b/c/topic(A) refs/for/master/topic(A) +test_expect_success "proc-receive: report alt (alt old-oid=X, --porcelain, $PROTOCOL)" ' + git -C workbench push --porcelain origin \ + HEAD:refs/for/master/topic \ + >out 2>&1 && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + remote: # pre-receive hook + remote: pre-receive< refs/for/master/topic + remote: # proc-receive hook + remote: proc-receive< refs/for/master/topic + remote: proc-receive> alt refs/for/master/topic old-oid= + remote: # post-receive hook + remote: post-receive< refs/for/master/topic + To + * HEAD:refs/for/master/topic [new reference] + Done + EOF + test_cmp expect actual +' + +test_expect_success "setup proc-receive hook (alt old-oid=X new-oid=Y, --porcelain, $PROTOCOL)" ' + write_script "$upstream/hooks/proc-receive" <<-EOF + printf >&2 "# proc-receive hook\n" + test-tool proc-receive -v \ + -r "alt refs/for/master/topic old-oid=$A new-oid=$B" + EOF +' + +# Refs of upstream : master(A) +# Refs of workbench: master(A) tags/v123 +# git push : refs/for/next/topic(A) refs/for/a/b/c/topic(A) refs/for/master/topic(A) +test_expect_success "proc-receive: report alt (alt old-oid=X new-oid=Y, --porcelain, $PROTOCOL)" ' + git -C workbench push --porcelain origin \ + HEAD:refs/for/master/topic \ + >out 2>&1 && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + remote: # pre-receive hook + remote: pre-receive< refs/for/master/topic + remote: # proc-receive hook + remote: proc-receive< refs/for/master/topic + remote: proc-receive> alt refs/for/master/topic old-oid= new-oid= + remote: # post-receive hook + remote: post-receive< refs/for/master/topic + To + * HEAD:refs/for/master/topic [new reference] + Done + EOF + test_cmp expect actual +' + +test_expect_success "setup proc-receive hook (with multiple alt reports, --porcelain, $PROTOCOL)" ' + write_script "$upstream/hooks/proc-receive" <<-EOF + printf >&2 "# proc-receive hook\n" + test-tool proc-receive -v \ + -r "ok refs/for/a/b/c/topic" \ + -r "alt refs/for/next/topic refs/pull/123/head" \ + -r "alt refs/for/master/topic refs/pull/124/head old-oid=$B forced-update new-oid=$A" + EOF +' + +# Refs of upstream : master(A) +# Refs of workbench: master(A) tags/v123 +# git push : refs/for/next/topic(A) refs/for/a/b/c/topic(A) refs/for/master/topic(A) +test_expect_success "proc-receive: with multiple alt reports (--porcelain, $PROTOCOL)" ' + git -C workbench push --porcelain origin \ + HEAD:refs/for/next/topic \ + HEAD:refs/for/a/b/c/topic \ + HEAD:refs/for/master/topic \ + >out 2>&1 && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + remote: # pre-receive hook + remote: pre-receive< refs/for/next/topic + remote: pre-receive< refs/for/a/b/c/topic + remote: pre-receive< refs/for/master/topic + remote: # proc-receive hook + remote: proc-receive< refs/for/next/topic + remote: proc-receive< refs/for/a/b/c/topic + remote: proc-receive< refs/for/master/topic + remote: proc-receive> ok refs/for/a/b/c/topic + remote: proc-receive> alt refs/for/next/topic refs/pull/123/head + remote: proc-receive> alt refs/for/master/topic refs/pull/124/head old-oid= forced-update new-oid= + remote: # post-receive hook + remote: post-receive< refs/for/next/topic + remote: post-receive< refs/for/a/b/c/topic + remote: post-receive< refs/for/master/topic + To + * HEAD:refs/for/next/topic [new reference] + * HEAD:refs/for/a/b/c/topic [new reference] + * HEAD:refs/for/master/topic [new reference] + Done + EOF + test_cmp expect actual && + + git -C "$upstream" show-ref >out && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + refs/heads/master + EOF + test_cmp expect actual +' diff --git a/t/t5411/test-0034-report-ft.sh b/t/t5411/test-0034-report-ft.sh new file mode 100644 index 0000000000..a25fb0505e --- /dev/null +++ b/t/t5411/test-0034-report-ft.sh @@ -0,0 +1,42 @@ +test_expect_success "setup proc-receive hook (ft, $PROTOCOL)" ' + write_script "$upstream/hooks/proc-receive" <<-EOF + printf >&2 "# proc-receive hook\n" + test-tool proc-receive -v \ + -r "ft refs/for/master/topic" + EOF +' + +# Refs of upstream : master(A) +# Refs of workbench: master(A) tags/v123 +# git push : refs/for/master/topic(B) +test_expect_success "proc-receive: fall throught, let receive-pack to execute ($PROTOCOL)" ' + git -C workbench push origin \ + $B:refs/for/master/topic \ + >out 2>&1 && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + remote: # pre-receive hook + remote: pre-receive< refs/for/master/topic + remote: # proc-receive hook + remote: proc-receive< refs/for/master/topic + remote: proc-receive> ft refs/for/master/topic + remote: # post-receive hook + remote: post-receive< refs/for/master/topic + To + * [new reference] -> refs/for/master/topic + EOF + test_cmp expect actual && + git -C "$upstream" show-ref >out && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + refs/for/master/topic + refs/heads/master + EOF + test_cmp expect actual +' + +# Refs of upstream : master(A) refs/for/master/topic(A) +# Refs of workbench: master(A) tags/v123 +test_expect_success "cleanup ($PROTOCOL)" ' + git -C "$upstream" update-ref -d refs/for/master/topic +' diff --git a/t/t5411/test-0035-report-ft--porcelain.sh b/t/t5411/test-0035-report-ft--porcelain.sh new file mode 100644 index 0000000000..e5c6eae544 --- /dev/null +++ b/t/t5411/test-0035-report-ft--porcelain.sh @@ -0,0 +1,43 @@ +test_expect_success "setup proc-receive hook (ft, $PROTOCOL)" ' + write_script "$upstream/hooks/proc-receive" <<-EOF + printf >&2 "# proc-receive hook\n" + test-tool proc-receive -v \ + -r "ft refs/for/master/topic" + EOF +' + +# Refs of upstream : master(A) +# Refs of workbench: master(A) tags/v123 +# git push : refs/for/master/topic(B) +test_expect_success "proc-receive: fall throught, let receive-pack to execute (--porcelain, $PROTOCOL)" ' + git -C workbench push --porcelain origin \ + $B:refs/for/master/topic \ + >out 2>&1 && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + remote: # pre-receive hook + remote: pre-receive< refs/for/master/topic + remote: # proc-receive hook + remote: proc-receive< refs/for/master/topic + remote: proc-receive> ft refs/for/master/topic + remote: # post-receive hook + remote: post-receive< refs/for/master/topic + To + * :refs/for/master/topic [new reference] + Done + EOF + test_cmp expect actual && + git -C "$upstream" show-ref >out && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + refs/for/master/topic + refs/heads/master + EOF + test_cmp expect actual +' + +# Refs of upstream : master(A) refs/for/master/topic(A) +# Refs of workbench: master(A) tags/v123 +test_expect_success "cleanup ($PROTOCOL)" ' + git -C "$upstream" update-ref -d refs/for/master/topic +' diff --git a/t/t5411/test-0036-report-multi-alt-for-one-ref.sh b/t/t5411/test-0036-report-multi-alt-for-one-ref.sh new file mode 100644 index 0000000000..fc019f709b --- /dev/null +++ b/t/t5411/test-0036-report-multi-alt-for-one-ref.sh @@ -0,0 +1,155 @@ +test_expect_success "setup proc-receive hook (multiple alt, no alt-ref for the 1st resp, $PROTOCOL)" ' + write_script "$upstream/hooks/proc-receive" <<-EOF + printf >&2 "# proc-receive hook\n" + test-tool proc-receive -v \ + -r "alt refs/for/master/topic old-oid=$A new-oid=$B" \ + -r "alt refs/for/master/topic refs/changes/24/124/1 old-oid=$ZERO_OID new-oid=$A" \ + -r "alt refs/for/master/topic refs/changes/25/125/1 old-oid=$A new-oid=$B" + EOF +' + +# Refs of upstream : master(A) +# Refs of workbench: master(A) tags/v123 +# git push : refs/for/master/topic(A) +test_expect_success "proc-receive: report multiple alt, no alt-ref for the 1st resp ($PROTOCOL)" ' + git -C workbench push origin \ + HEAD:refs/for/master/topic \ + >out 2>&1 && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + remote: # pre-receive hook + remote: pre-receive< refs/for/master/topic + remote: # proc-receive hook + remote: proc-receive< refs/for/master/topic + remote: proc-receive> alt refs/for/master/topic old-oid= new-oid= + remote: proc-receive> alt refs/for/master/topic refs/changes/24/124/1 old-oid= new-oid= + remote: proc-receive> alt refs/for/master/topic refs/changes/25/125/1 old-oid= new-oid= + remote: # post-receive hook + remote: post-receive< refs/for/master/topic + To + * [new reference] HEAD -> refs/for/master/topic + EOF + test_cmp expect actual && + git -C "$upstream" show-ref >out && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + refs/heads/master + EOF + test_cmp expect actual +' + +test_expect_success "setup proc-receive hook (multiple alt, no alt-ref for the 2nd resp, $PROTOCOL)" ' + write_script "$upstream/hooks/proc-receive" <<-EOF + printf >&2 "# proc-receive hook\n" + test-tool proc-receive -v \ + -r "alt refs/for/master/topic refs/changes/24/124/1 old-oid=$ZERO_OID new-oid=$A" \ + -r "alt refs/for/master/topic old-oid=$A new-oid=$B" \ + -r "alt refs/for/master/topic refs/changes/25/125/1 old-oid=$B new-oid=$A forced-update" + EOF +' + +# Refs of upstream : master(A) +# Refs of workbench: master(A) tags/v123 +# git push : refs/for/master/topic(A) +test_expect_success "proc-receive: report multiple alt, no alt-ref for the 2nd resp ($PROTOCOL)" ' + git -C workbench push origin \ + HEAD:refs/for/master/topic \ + >out 2>&1 && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + remote: # pre-receive hook + remote: pre-receive< refs/for/master/topic + remote: # proc-receive hook + remote: proc-receive< refs/for/master/topic + remote: proc-receive> alt refs/for/master/topic refs/changes/24/124/1 old-oid= new-oid= + remote: proc-receive> alt refs/for/master/topic old-oid= new-oid= + remote: proc-receive> alt refs/for/master/topic refs/changes/25/125/1 old-oid= new-oid= forced-update + remote: # post-receive hook + remote: post-receive< refs/for/master/topic + To + * [new reference] HEAD -> refs/for/master/topic + EOF + test_cmp expect actual && + git -C "$upstream" show-ref >out && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + refs/heads/master + EOF + test_cmp expect actual +' + +test_expect_success "setup proc-receive hook (ok and alt for the same ref, $PROTOCOL)" ' + write_script "$upstream/hooks/proc-receive" <<-EOF + printf >&2 "# proc-receive hook\n" + test-tool proc-receive -v \ + -r "ok refs/for/master/topic" \ + -r "alt refs/for/master/topic refs/changes/24/124/1 new-oid=$B old-oid=$A" + EOF +' + +# Refs of upstream : master(A) +# Refs of workbench: master(A) tags/v123 +# git push : refs/for/master/topic(A) +test_expect_success "proc-receive: report ok and alt for the same ref ($PROTOCOL)" ' + git -C workbench push origin \ + HEAD:refs/for/master/topic \ + >out 2>&1 && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + remote: # pre-receive hook + remote: pre-receive< refs/for/master/topic + remote: # proc-receive hook + remote: proc-receive< refs/for/master/topic + remote: proc-receive> ok refs/for/master/topic + remote: proc-receive> alt refs/for/master/topic refs/changes/24/124/1 new-oid= old-oid= + remote: # post-receive hook + remote: post-receive< refs/for/master/topic + To + * [new reference] HEAD -> refs/for/master/topic + EOF + test_cmp expect actual && + git -C "$upstream" show-ref >out && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + refs/heads/master + EOF + test_cmp expect actual +' + +test_expect_success "setup proc-receive hook (multiple responses, $PROTOCOL)" ' + write_script "$upstream/hooks/proc-receive" <<-EOF + printf >&2 "# proc-receive hook\n" + test-tool proc-receive -v \ + -r "alt refs/for/master/topic refs/changes/23/123/1" \ + -r "alt refs/for/master/topic refs/changes/24/124/2 old-oid=$A new-oid=$B" + EOF +' + +# Refs of upstream : master(A) +# Refs of workbench: master(A) tags/v123 +# git push : refs/for/master/topic(A) +test_expect_success "proc-receive: report multiple response ($PROTOCOL)" ' + git -C workbench push origin \ + HEAD:refs/for/master/topic \ + >out 2>&1 && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + remote: # pre-receive hook + remote: pre-receive< refs/for/master/topic + remote: # proc-receive hook + remote: proc-receive< refs/for/master/topic + remote: proc-receive> alt refs/for/master/topic refs/changes/23/123/1 + remote: proc-receive> alt refs/for/master/topic refs/changes/24/124/2 old-oid= new-oid= + remote: # post-receive hook + remote: post-receive< refs/for/master/topic + To + * [new reference] HEAD -> refs/for/master/topic + EOF + test_cmp expect actual && + git -C "$upstream" show-ref >out && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + refs/heads/master + EOF + test_cmp expect actual +' diff --git a/t/t5411/test-0037-report-multi-alt-for-one-ref--porcelain.sh b/t/t5411/test-0037-report-multi-alt-for-one-ref--porcelain.sh new file mode 100644 index 0000000000..22607b135e --- /dev/null +++ b/t/t5411/test-0037-report-multi-alt-for-one-ref--porcelain.sh @@ -0,0 +1,159 @@ +test_expect_success "setup proc-receive hook (multiple alt, no alt-ref for the 1st resp, $PROTOCOL)" ' + write_script "$upstream/hooks/proc-receive" <<-EOF + printf >&2 "# proc-receive hook\n" + test-tool proc-receive -v \ + -r "alt refs/for/master/topic old-oid=$A new-oid=$B" \ + -r "alt refs/for/master/topic refs/changes/24/124/1 old-oid=$ZERO_OID new-oid=$A" \ + -r "alt refs/for/master/topic refs/changes/25/125/1 old-oid=$A new-oid=$B" + EOF +' + +# Refs of upstream : master(A) +# Refs of workbench: master(A) tags/v123 +# git push : refs/for/master/topic(A) +test_expect_success "proc-receive: report multiple alt, no alt-ref for the 1st resp (--porcelain, $PROTOCOL)" ' + git -C workbench push --porcelain origin \ + HEAD:refs/for/master/topic \ + >out 2>&1 && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + remote: # pre-receive hook + remote: pre-receive< refs/for/master/topic + remote: # proc-receive hook + remote: proc-receive< refs/for/master/topic + remote: proc-receive> alt refs/for/master/topic old-oid= new-oid= + remote: proc-receive> alt refs/for/master/topic refs/changes/24/124/1 old-oid= new-oid= + remote: proc-receive> alt refs/for/master/topic refs/changes/25/125/1 old-oid= new-oid= + remote: # post-receive hook + remote: post-receive< refs/for/master/topic + To + * HEAD:refs/for/master/topic [new reference] + Done + EOF + test_cmp expect actual && + git -C "$upstream" show-ref >out && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + refs/heads/master + EOF + test_cmp expect actual +' + +test_expect_success "setup proc-receive hook (multiple alt, no alt-ref for the 2nd resp, $PROTOCOL)" ' + write_script "$upstream/hooks/proc-receive" <<-EOF + printf >&2 "# proc-receive hook\n" + test-tool proc-receive -v \ + -r "alt refs/for/master/topic refs/changes/24/124/1 old-oid=$ZERO_OID new-oid=$A" \ + -r "alt refs/for/master/topic old-oid=$A new-oid=$B" \ + -r "alt refs/for/master/topic refs/changes/25/125/1 old-oid=$B new-oid=$A forced-update" + EOF +' + +# Refs of upstream : master(A) +# Refs of workbench: master(A) tags/v123 +# git push : refs/for/master/topic(A) +test_expect_success "proc-receive: report multiple alt, no alt-ref for the 2nd resp (--porcelain, $PROTOCOL)" ' + git -C workbench push --porcelain origin \ + HEAD:refs/for/master/topic \ + >out 2>&1 && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + remote: # pre-receive hook + remote: pre-receive< refs/for/master/topic + remote: # proc-receive hook + remote: proc-receive< refs/for/master/topic + remote: proc-receive> alt refs/for/master/topic refs/changes/24/124/1 old-oid= new-oid= + remote: proc-receive> alt refs/for/master/topic old-oid= new-oid= + remote: proc-receive> alt refs/for/master/topic refs/changes/25/125/1 old-oid= new-oid= forced-update + remote: # post-receive hook + remote: post-receive< refs/for/master/topic + To + * HEAD:refs/for/master/topic [new reference] + Done + EOF + test_cmp expect actual && + git -C "$upstream" show-ref >out && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + refs/heads/master + EOF + test_cmp expect actual +' + +test_expect_success "setup proc-receive hook (ok and alt for the same ref, $PROTOCOL)" ' + write_script "$upstream/hooks/proc-receive" <<-EOF + printf >&2 "# proc-receive hook\n" + test-tool proc-receive -v \ + -r "ok refs/for/master/topic" \ + -r "alt refs/for/master/topic refs/changes/24/124/1 new-oid=$B old-oid=$A" + EOF +' + +# Refs of upstream : master(A) +# Refs of workbench: master(A) tags/v123 +# git push : refs/for/master/topic(A) +test_expect_success "proc-receive: report ok and alt for the same ref (--porcelain, $PROTOCOL)" ' + git -C workbench push --porcelain origin \ + HEAD:refs/for/master/topic \ + >out 2>&1 && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + remote: # pre-receive hook + remote: pre-receive< refs/for/master/topic + remote: # proc-receive hook + remote: proc-receive< refs/for/master/topic + remote: proc-receive> ok refs/for/master/topic + remote: proc-receive> alt refs/for/master/topic refs/changes/24/124/1 new-oid= old-oid= + remote: # post-receive hook + remote: post-receive< refs/for/master/topic + To + * HEAD:refs/for/master/topic [new reference] + Done + EOF + test_cmp expect actual && + git -C "$upstream" show-ref >out && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + refs/heads/master + EOF + test_cmp expect actual +' + +test_expect_success "setup proc-receive hook (multiple responses, $PROTOCOL)" ' + write_script "$upstream/hooks/proc-receive" <<-EOF + printf >&2 "# proc-receive hook\n" + test-tool proc-receive -v \ + -r "alt refs/for/master/topic refs/changes/23/123/1" \ + -r "alt refs/for/master/topic refs/changes/24/124/2 old-oid=$A new-oid=$B" + EOF +' + +# Refs of upstream : master(A) +# Refs of workbench: master(A) tags/v123 +# git push : refs/for/master/topic(A) +test_expect_success "proc-receive: report multiple response (--porcelain, $PROTOCOL)" ' + git -C workbench push --porcelain origin \ + HEAD:refs/for/master/topic \ + >out 2>&1 && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + remote: # pre-receive hook + remote: pre-receive< refs/for/master/topic + remote: # proc-receive hook + remote: proc-receive< refs/for/master/topic + remote: proc-receive> alt refs/for/master/topic refs/changes/23/123/1 + remote: proc-receive> alt refs/for/master/topic refs/changes/24/124/2 old-oid= new-oid= + remote: # post-receive hook + remote: post-receive< refs/for/master/topic + To + * HEAD:refs/for/master/topic [new reference] + Done + EOF + test_cmp expect actual && + git -C "$upstream" show-ref >out && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + refs/heads/master + EOF + test_cmp expect actual +' diff --git a/t/t5411/test-0038-report-mixed-refs.sh b/t/t5411/test-0038-report-mixed-refs.sh new file mode 100644 index 0000000000..dd03bf1538 --- /dev/null +++ b/t/t5411/test-0038-report-mixed-refs.sh @@ -0,0 +1,74 @@ +test_expect_success "setup proc-receive hook ($PROTOCOL)" ' + write_script "$upstream/hooks/proc-receive" <<-EOF + printf >&2 "# proc-receive hook\n" + test-tool proc-receive -v \ + -r "ok refs/for/next/topic" \ + -r "alt refs/for/master/topic refs/for/master/topic old-oid=$A new-oid=$B" + EOF +' + +# Refs of upstream : master(A) +# Refs of workbench: master(A) tags/v123 +# git push : (B) bar(A) baz(A) refs/for/next/topic(A) foo(A) refs/for/master/topic(A) +test_expect_success "proc-receive: report update of mixed refs ($PROTOCOL)" ' + git -C workbench push origin \ + $B:refs/heads/master \ + HEAD:refs/heads/bar \ + HEAD:refs/heads/baz \ + HEAD:refs/for/next/topic \ + HEAD:refs/heads/foo \ + HEAD:refs/for/master/topic \ + >out 2>&1 && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + remote: # pre-receive hook + remote: pre-receive< refs/heads/master + remote: pre-receive< refs/heads/bar + remote: pre-receive< refs/heads/baz + remote: pre-receive< refs/for/next/topic + remote: pre-receive< refs/heads/foo + remote: pre-receive< refs/for/master/topic + remote: # proc-receive hook + remote: proc-receive< refs/for/next/topic + remote: proc-receive< refs/for/master/topic + remote: proc-receive> ok refs/for/next/topic + remote: proc-receive> alt refs/for/master/topic refs/for/master/topic old-oid= new-oid= + remote: # post-receive hook + remote: post-receive< refs/heads/master + remote: post-receive< refs/heads/bar + remote: post-receive< refs/heads/baz + remote: post-receive< refs/for/next/topic + remote: post-receive< refs/heads/foo + remote: post-receive< refs/for/master/topic + To + .. -> master + * [new branch] HEAD -> bar + * [new branch] HEAD -> baz + * [new reference] HEAD -> refs/for/next/topic + * [new branch] HEAD -> foo + * [new reference] HEAD -> refs/for/master/topic + EOF + test_cmp expect actual && + git -C "$upstream" show-ref >out && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + refs/heads/bar + refs/heads/baz + refs/heads/foo + refs/heads/master + EOF + test_cmp expect actual +' + +# Refs of upstream : master(B) foo(A) bar(A)) baz(A) +# Refs of workbench: master(A) tags/v123 +test_expect_success "cleanup ($PROTOCOL)" ' + ( + cd "$upstream" && + git update-ref refs/heads/master $A && + git update-ref -d refs/heads/foo && + git update-ref -d refs/heads/bar && + git update-ref -d refs/heads/baz + ) + +' diff --git a/t/t5411/test-0039-report-mixed-refs--porcelain.sh b/t/t5411/test-0039-report-mixed-refs--porcelain.sh new file mode 100644 index 0000000000..e237f40db7 --- /dev/null +++ b/t/t5411/test-0039-report-mixed-refs--porcelain.sh @@ -0,0 +1,75 @@ +test_expect_success "setup proc-receive hook ($PROTOCOL)" ' + write_script "$upstream/hooks/proc-receive" <<-EOF + printf >&2 "# proc-receive hook\n" + test-tool proc-receive -v \ + -r "ok refs/for/next/topic" \ + -r "alt refs/for/master/topic refs/for/master/topic old-oid=$A new-oid=$B" + EOF +' + +# Refs of upstream : master(A) +# Refs of workbench: master(A) tags/v123 +# git push : (B) bar(A) baz(A) refs/for/next/topic(A) foo(A) refs/for/master/topic(A) +test_expect_success "proc-receive: report update of mixed refs (--porcelain, $PROTOCOL)" ' + git -C workbench push --porcelain origin \ + $B:refs/heads/master \ + HEAD:refs/heads/bar \ + HEAD:refs/heads/baz \ + HEAD:refs/for/next/topic \ + HEAD:refs/heads/foo \ + HEAD:refs/for/master/topic \ + >out 2>&1 && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + remote: # pre-receive hook + remote: pre-receive< refs/heads/master + remote: pre-receive< refs/heads/bar + remote: pre-receive< refs/heads/baz + remote: pre-receive< refs/for/next/topic + remote: pre-receive< refs/heads/foo + remote: pre-receive< refs/for/master/topic + remote: # proc-receive hook + remote: proc-receive< refs/for/next/topic + remote: proc-receive< refs/for/master/topic + remote: proc-receive> ok refs/for/next/topic + remote: proc-receive> alt refs/for/master/topic refs/for/master/topic old-oid= new-oid= + remote: # post-receive hook + remote: post-receive< refs/heads/master + remote: post-receive< refs/heads/bar + remote: post-receive< refs/heads/baz + remote: post-receive< refs/for/next/topic + remote: post-receive< refs/heads/foo + remote: post-receive< refs/for/master/topic + To + :refs/heads/master .. + * HEAD:refs/heads/bar [new branch] + * HEAD:refs/heads/baz [new branch] + * HEAD:refs/for/next/topic [new reference] + * HEAD:refs/heads/foo [new branch] + * HEAD:refs/for/master/topic [new reference] + Done + EOF + test_cmp expect actual && + git -C "$upstream" show-ref >out && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + refs/heads/bar + refs/heads/baz + refs/heads/foo + refs/heads/master + EOF + test_cmp expect actual +' + +# Refs of upstream : master(B) foo(A) bar(A)) baz(A) +# Refs of workbench: master(A) tags/v123 +test_expect_success "cleanup ($PROTOCOL)" ' + ( + cd "$upstream" && + git update-ref refs/heads/master $A && + git update-ref -d refs/heads/foo && + git update-ref -d refs/heads/bar && + git update-ref -d refs/heads/baz + ) + +' From patchwork Sat Apr 18 16:03:30 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiang Xin X-Patchwork-Id: 11496635 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 33729912 for ; Sat, 18 Apr 2020 16:03:59 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 0067F2223D for ; Sat, 18 Apr 2020 16:03:58 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="aYIWVO4P" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727803AbgDRQD6 (ORCPT ); Sat, 18 Apr 2020 12:03:58 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45420 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1726408AbgDRQDy (ORCPT ); Sat, 18 Apr 2020 12:03:54 -0400 Received: from mail-pg1-x544.google.com (mail-pg1-x544.google.com [IPv6:2607:f8b0:4864:20::544]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C0C37C061A0C for ; Sat, 18 Apr 2020 09:03:53 -0700 (PDT) Received: by mail-pg1-x544.google.com with SMTP id o15so2177586pgi.1 for ; Sat, 18 Apr 2020 09:03:53 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=EXoBNmz/nNhkIYSx6NzfMs2CrKVG7dMVw5MBn5q2wOc=; b=aYIWVO4PhM6s4I26+EhFj0YY83VhnI6ngOASUevwDb2lQ/i0467EJ3Df/DUgR4Ngbx CwmDlSXe5YCpHpI69QjeRl9luhwypm4pKv8GnAPWbVsQ3bzYhNHZn7Kzd7DqZSFQfeXE aD4bEQb9dHPePV1Asx3OqipPfUTtsPoVY3da6bzfjw/kP3yGxXuKEhJ0kIX/pD09yDxm tNlGmlGeGlqPiNwf9k8Rxr8xE0whiGIGW9VtFzbamn8aI3vkF8RDak1di92rWAmhJNxO 1ct7VIJ/0fGHMrN9PywIzGF9zC0XVXlVR/i/mvS+VP7o+PHn4YNjIUauE+RqwETdcc7m KAuQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=EXoBNmz/nNhkIYSx6NzfMs2CrKVG7dMVw5MBn5q2wOc=; b=YY/AJNmSIZf90paCsMlHfVbWy9q4+IqANwminufVmldOej3q8sQYHXx7w//lNptZZD GmKeBnL0+dtNyjrnCOROVyCCf5WZya4Z2sZvQOvKHga4w+IUyPJvE6BP/glbr19JzfeF dZLuISEUu3SFYlczD0lag+nsKBUa0/N4YhsGsFkKS6sauINEO08/XgsDQBDr+pvViy2u N5olBkP608hPz1yANC/awRioT2grrDRrIEtMsS5KDEj800xruXmqN8FbJmmHGNMyWlBn 4KqrRP265NxYbvBDrCCCT2Vg3fduRjIMAUrmBMDCr3kFenUGLLkBgv4lGU0Z7WsJ6BgD kSqQ== X-Gm-Message-State: AGi0PubpNSYiE+GQugf9i0nCMMC7k4PCLdSyEXeqWMTsCBzF+BOj5v03 BFLBix5yVwioBpA8Uznpgw0= X-Google-Smtp-Source: APiQypJphOEqzReiC06a2sHp/vXabkX4rO4DMq+PZ5Kepe8FKceBiF0h22jGoIeYDEN4rvyB3pf5Vw== X-Received: by 2002:a62:2ec6:: with SMTP id u189mr5097637pfu.306.1587225832909; Sat, 18 Apr 2020 09:03:52 -0700 (PDT) Received: from tigtog.localdomain.localdomain ([144.34.163.219]) by smtp.gmail.com with ESMTPSA id i187sm22461649pfg.33.2020.04.18.09.03.52 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Sat, 18 Apr 2020 09:03:52 -0700 (PDT) From: Jiang Xin To: Junio C Hamano , Git List Cc: Jiang Xin Subject: [PATCH v13 4/8] send-pack: extension for client-side status report Date: Sat, 18 Apr 2020 12:03:30 -0400 Message-Id: <20200418160334.15631-5-worldhello.net@gmail.com> X-Mailer: git-send-email 2.26.0.rc0 In-Reply-To: <20200414123257.27449-1-worldhello.net@gmail.com> References: <20200414123257.27449-1-worldhello.net@gmail.com> MIME-Version: 1.0 Sender: git-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Jiang Xin This is the client-side extension for status report of git-push. The "proc-receive" hook may receive a command for a pseudo-reference with a zero-old as its old-oid, while the result of the hook may point to an alternate reference and the reference may exist already with a non-zero old-oid. Git client may receive a report with extened status as the following example: ok refs/for/master/topic\0ref=refs/pull/123/head old-oid=... Parse the key-value pairs in the extended status after the null character of the report, and show the proper reference name, old-oid and new-oid to the user. Suggested-by: Junio C Hamano Signed-off-by: Jiang Xin --- remote.c | 21 ++++++ remote.h | 3 + send-pack.c | 11 ++- t/t5411/test-0032-report-alt.sh | 14 ++-- t/t5411/test-0033-report-alt--porcelain.sh | 14 ++-- .../test-0036-report-multi-alt-for-one-ref.sh | 12 ++- ...report-multi-alt-for-one-ref--porcelain.sh | 12 ++- t/t5411/test-0038-report-mixed-refs.sh | 2 +- .../test-0039-report-mixed-refs--porcelain.sh | 2 +- transport-helper.c | 64 ++++++++-------- transport.c | 74 +++++++++++++++++-- 11 files changed, 169 insertions(+), 60 deletions(-) diff --git a/remote.c b/remote.c index c43196ec06..4174746bb9 100644 --- a/remote.c +++ b/remote.c @@ -1,5 +1,6 @@ #include "cache.h" #include "config.h" +#include "connect.h" #include "remote.h" #include "refs.h" #include "refspec.h" @@ -2311,3 +2312,23 @@ void apply_push_cas(struct push_cas_option *cas, for (ref = remote_refs; ref; ref = ref->next) apply_cas(cas, remote, ref); } + +void update_ref_from_remote_status(struct ref *ref) +{ + char *val; + int len; + + if (!ref->remote_status) + return; + + val = (char *)parse_feature_value(ref->remote_status, "old-oid", &len); + if (val && len) + get_oid_hex(val, &ref->old_oid); + + val = (char *)parse_feature_value(ref->remote_status, "new-oid", &len); + if (val && len) + get_oid_hex(val, &ref->new_oid); + + if (parse_feature_request(ref->remote_status, "forced-update")) + ref->forced_update = 1; +} diff --git a/remote.h b/remote.h index 11d8719b58..09cf7014e3 100644 --- a/remote.h +++ b/remote.h @@ -345,4 +345,7 @@ int parseopt_push_cas_option(const struct option *, const char *arg, int unset); int is_empty_cas(const struct push_cas_option *); void apply_push_cas(struct push_cas_option *, struct remote *, struct ref *); +/* Parse key-value pairs of remote_status and update the reference accordingly */ +void update_ref_from_remote_status(struct ref *ref); + #endif diff --git a/send-pack.c b/send-pack.c index a7c53193c9..6e2c7a0c0c 100644 --- a/send-pack.c +++ b/send-pack.c @@ -159,6 +159,9 @@ static int receive_status(struct packet_reader *reader, struct ref *refs) while (1) { const char *refname; char *msg; + char *extended_status = NULL; + int len; + if (packet_reader_read(reader) != PACKET_READ_NORMAL) break; if (!starts_with(reader->line, "ok ") && !starts_with(reader->line, "ng ")) { @@ -167,10 +170,13 @@ static int receive_status(struct packet_reader *reader, struct ref *refs) break; } + len = strlen(reader->line); refname = reader->line + 3; msg = strchr(refname, ' '); if (msg) *msg++ = '\0'; + if (reader->pktlen > len) + extended_status = (char *)reader->line + len + 1; /* first try searching at our hint, falling back to all refs */ if (hint) @@ -192,7 +198,10 @@ static int receive_status(struct packet_reader *reader, struct ref *refs) hint->status = REF_STATUS_OK; else hint->status = REF_STATUS_REMOTE_REJECT; - hint->remote_status = xstrdup_or_null(msg); + if (msg) + hint->remote_status = xstrdup(msg); + else if (extended_status) + hint->remote_status = xstrdup_or_null(extended_status); /* start our next search from the next ref */ hint = hint->next; } diff --git a/t/t5411/test-0032-report-alt.sh b/t/t5411/test-0032-report-alt.sh index dec4afc4c1..bf5faf4f2e 100644 --- a/t/t5411/test-0032-report-alt.sh +++ b/t/t5411/test-0032-report-alt.sh @@ -52,7 +52,7 @@ test_expect_success "proc-receive: report alt (alt , $PROTOCOL)" remote: # post-receive hook remote: post-receive< refs/for/master/topic To - * [new reference] HEAD -> refs/for/master/topic + * [new reference] HEAD -> refs/pull/123/head EOF test_cmp expect actual ' @@ -82,7 +82,7 @@ test_expect_success "proc-receive: report alt (alt forced-update remote: # post-receive hook remote: post-receive< refs/for/master/topic To - * [new reference] HEAD -> refs/for/master/topic + * [new reference] HEAD -> refs/pull/123/head EOF test_cmp expect actual ' @@ -112,7 +112,7 @@ test_expect_success "proc-receive: report alt (alt old-oid=X, $P remote: # post-receive hook remote: post-receive< refs/for/master/topic To - * [new reference] HEAD -> refs/for/master/topic + .. HEAD -> refs/pull/123/head EOF test_cmp expect actual ' @@ -142,7 +142,7 @@ test_expect_success "proc-receive: report alt (alt old-oid=X, $PROTOCOL)" remote: # post-receive hook remote: post-receive< refs/for/master/topic To - * [new reference] HEAD -> refs/for/master/topic + .. HEAD -> refs/for/master/topic EOF test_cmp expect actual ' @@ -172,7 +172,7 @@ test_expect_success "proc-receive: report alt (alt old-oid=X new-oid=Y, $P remote: # post-receive hook remote: post-receive< refs/for/master/topic To - * [new reference] HEAD -> refs/for/master/topic + .. HEAD -> refs/for/master/topic EOF test_cmp expect actual ' @@ -214,9 +214,9 @@ test_expect_success "proc-receive: with multiple alt reports ($PROTOCOL)" ' remote: post-receive< refs/for/a/b/c/topic remote: post-receive< refs/for/master/topic To - * [new reference] HEAD -> refs/for/next/topic + * [new reference] HEAD -> refs/pull/123/head * [new reference] HEAD -> refs/for/a/b/c/topic - * [new reference] HEAD -> refs/for/master/topic + + ... HEAD -> refs/pull/124/head (forced update) EOF test_cmp expect actual && diff --git a/t/t5411/test-0033-report-alt--porcelain.sh b/t/t5411/test-0033-report-alt--porcelain.sh index 49d76892ab..3aea911407 100644 --- a/t/t5411/test-0033-report-alt--porcelain.sh +++ b/t/t5411/test-0033-report-alt--porcelain.sh @@ -53,7 +53,7 @@ test_expect_success "proc-receive: report alt (alt , --porcelain, remote: # post-receive hook remote: post-receive< refs/for/master/topic To - * HEAD:refs/for/master/topic [new reference] + * HEAD:refs/pull/123/head [new reference] Done EOF test_cmp expect actual @@ -84,7 +84,7 @@ test_expect_success "proc-receive: report alt (alt forced-update remote: # post-receive hook remote: post-receive< refs/for/master/topic To - * HEAD:refs/for/master/topic [new reference] + * HEAD:refs/pull/123/head [new reference] Done EOF test_cmp expect actual @@ -115,7 +115,7 @@ test_expect_success "proc-receive: report alt (alt old-oid=X, -- remote: # post-receive hook remote: post-receive< refs/for/master/topic To - * HEAD:refs/for/master/topic [new reference] + HEAD:refs/pull/123/head .. Done EOF test_cmp expect actual @@ -146,7 +146,7 @@ test_expect_success "proc-receive: report alt (alt old-oid=X, --porcelain, remote: # post-receive hook remote: post-receive< refs/for/master/topic To - * HEAD:refs/for/master/topic [new reference] + HEAD:refs/for/master/topic .. Done EOF test_cmp expect actual @@ -177,7 +177,7 @@ test_expect_success "proc-receive: report alt (alt old-oid=X new-oid=Y, -- remote: # post-receive hook remote: post-receive< refs/for/master/topic To - * HEAD:refs/for/master/topic [new reference] + HEAD:refs/for/master/topic .. Done EOF test_cmp expect actual @@ -220,9 +220,9 @@ test_expect_success "proc-receive: with multiple alt reports (--porcelain, $PROT remote: post-receive< refs/for/a/b/c/topic remote: post-receive< refs/for/master/topic To - * HEAD:refs/for/next/topic [new reference] + * HEAD:refs/pull/123/head [new reference] * HEAD:refs/for/a/b/c/topic [new reference] - * HEAD:refs/for/master/topic [new reference] + + HEAD:refs/pull/124/head ... (forced update) Done EOF test_cmp expect actual && diff --git a/t/t5411/test-0036-report-multi-alt-for-one-ref.sh b/t/t5411/test-0036-report-multi-alt-for-one-ref.sh index fc019f709b..d82b79ffff 100644 --- a/t/t5411/test-0036-report-multi-alt-for-one-ref.sh +++ b/t/t5411/test-0036-report-multi-alt-for-one-ref.sh @@ -27,7 +27,9 @@ test_expect_success "proc-receive: report multiple alt, no alt-ref for the 1st r remote: # post-receive hook remote: post-receive< refs/for/master/topic To - * [new reference] HEAD -> refs/for/master/topic + .. HEAD -> refs/for/master/topic + * [new reference] HEAD -> refs/changes/24/124/1 + .. HEAD -> refs/changes/25/125/1 EOF test_cmp expect actual && git -C "$upstream" show-ref >out && @@ -67,7 +69,9 @@ test_expect_success "proc-receive: report multiple alt, no alt-ref for the 2nd r remote: # post-receive hook remote: post-receive< refs/for/master/topic To - * [new reference] HEAD -> refs/for/master/topic + * [new reference] HEAD -> refs/changes/24/124/1 + .. HEAD -> refs/for/master/topic + + ... HEAD -> refs/changes/25/125/1 (forced update) EOF test_cmp expect actual && git -C "$upstream" show-ref >out && @@ -106,6 +110,7 @@ test_expect_success "proc-receive: report ok and alt for the same ref ($PROTOCOL remote: post-receive< refs/for/master/topic To * [new reference] HEAD -> refs/for/master/topic + .. HEAD -> refs/changes/24/124/1 EOF test_cmp expect actual && git -C "$upstream" show-ref >out && @@ -143,7 +148,8 @@ test_expect_success "proc-receive: report multiple response ($PROTOCOL)" ' remote: # post-receive hook remote: post-receive< refs/for/master/topic To - * [new reference] HEAD -> refs/for/master/topic + * [new reference] HEAD -> refs/changes/23/123/1 + .. HEAD -> refs/changes/24/124/2 EOF test_cmp expect actual && git -C "$upstream" show-ref >out && diff --git a/t/t5411/test-0037-report-multi-alt-for-one-ref--porcelain.sh b/t/t5411/test-0037-report-multi-alt-for-one-ref--porcelain.sh index 22607b135e..8cca63c2de 100644 --- a/t/t5411/test-0037-report-multi-alt-for-one-ref--porcelain.sh +++ b/t/t5411/test-0037-report-multi-alt-for-one-ref--porcelain.sh @@ -27,7 +27,9 @@ test_expect_success "proc-receive: report multiple alt, no alt-ref for the 1st r remote: # post-receive hook remote: post-receive< refs/for/master/topic To - * HEAD:refs/for/master/topic [new reference] + HEAD:refs/for/master/topic .. + * HEAD:refs/changes/24/124/1 [new reference] + HEAD:refs/changes/25/125/1 .. Done EOF test_cmp expect actual && @@ -68,7 +70,9 @@ test_expect_success "proc-receive: report multiple alt, no alt-ref for the 2nd r remote: # post-receive hook remote: post-receive< refs/for/master/topic To - * HEAD:refs/for/master/topic [new reference] + * HEAD:refs/changes/24/124/1 [new reference] + HEAD:refs/for/master/topic .. + + HEAD:refs/changes/25/125/1 ... (forced update) Done EOF test_cmp expect actual && @@ -108,6 +112,7 @@ test_expect_success "proc-receive: report ok and alt for the same ref (--porcela remote: post-receive< refs/for/master/topic To * HEAD:refs/for/master/topic [new reference] + HEAD:refs/changes/24/124/1 .. Done EOF test_cmp expect actual && @@ -146,7 +151,8 @@ test_expect_success "proc-receive: report multiple response (--porcelain, $PROTO remote: # post-receive hook remote: post-receive< refs/for/master/topic To - * HEAD:refs/for/master/topic [new reference] + * HEAD:refs/changes/23/123/1 [new reference] + HEAD:refs/changes/24/124/2 .. Done EOF test_cmp expect actual && diff --git a/t/t5411/test-0038-report-mixed-refs.sh b/t/t5411/test-0038-report-mixed-refs.sh index dd03bf1538..566cb6e098 100644 --- a/t/t5411/test-0038-report-mixed-refs.sh +++ b/t/t5411/test-0038-report-mixed-refs.sh @@ -46,7 +46,7 @@ test_expect_success "proc-receive: report update of mixed refs ($PROTOCOL)" ' * [new branch] HEAD -> baz * [new reference] HEAD -> refs/for/next/topic * [new branch] HEAD -> foo - * [new reference] HEAD -> refs/for/master/topic + .. HEAD -> refs/for/master/topic EOF test_cmp expect actual && git -C "$upstream" show-ref >out && diff --git a/t/t5411/test-0039-report-mixed-refs--porcelain.sh b/t/t5411/test-0039-report-mixed-refs--porcelain.sh index e237f40db7..4d617abb1a 100644 --- a/t/t5411/test-0039-report-mixed-refs--porcelain.sh +++ b/t/t5411/test-0039-report-mixed-refs--porcelain.sh @@ -46,7 +46,7 @@ test_expect_success "proc-receive: report update of mixed refs (--porcelain, $PR * HEAD:refs/heads/baz [new branch] * HEAD:refs/for/next/topic [new reference] * HEAD:refs/heads/foo [new branch] - * HEAD:refs/for/master/topic [new reference] + HEAD:refs/for/master/topic .. Done EOF test_cmp expect actual && diff --git a/transport-helper.c b/transport-helper.c index a46afcb69d..0c835c5495 100644 --- a/transport-helper.c +++ b/transport-helper.c @@ -747,37 +747,39 @@ static int push_update_ref_status(struct strbuf *buf, msg = xstrdup(msg); strbuf_release(&msg_buf); - if (!strcmp(msg, "no match")) { - status = REF_STATUS_NONE; - FREE_AND_NULL(msg); - } - else if (!strcmp(msg, "up to date")) { - status = REF_STATUS_UPTODATE; - FREE_AND_NULL(msg); - } - else if (!strcmp(msg, "non-fast forward")) { - status = REF_STATUS_REJECT_NONFASTFORWARD; - FREE_AND_NULL(msg); - } - else if (!strcmp(msg, "already exists")) { - status = REF_STATUS_REJECT_ALREADY_EXISTS; - FREE_AND_NULL(msg); - } - else if (!strcmp(msg, "fetch first")) { - status = REF_STATUS_REJECT_FETCH_FIRST; - FREE_AND_NULL(msg); - } - else if (!strcmp(msg, "needs force")) { - status = REF_STATUS_REJECT_NEEDS_FORCE; - FREE_AND_NULL(msg); - } - else if (!strcmp(msg, "stale info")) { - status = REF_STATUS_REJECT_STALE; - FREE_AND_NULL(msg); - } - else if (!strcmp(msg, "forced update")) { - forced = 1; - FREE_AND_NULL(msg); + if (status != REF_STATUS_OK) { + if (!strcmp(msg, "no match")) { + status = REF_STATUS_NONE; + FREE_AND_NULL(msg); + } + else if (!strcmp(msg, "up to date")) { + status = REF_STATUS_UPTODATE; + FREE_AND_NULL(msg); + } + else if (!strcmp(msg, "non-fast forward")) { + status = REF_STATUS_REJECT_NONFASTFORWARD; + FREE_AND_NULL(msg); + } + else if (!strcmp(msg, "already exists")) { + status = REF_STATUS_REJECT_ALREADY_EXISTS; + FREE_AND_NULL(msg); + } + else if (!strcmp(msg, "fetch first")) { + status = REF_STATUS_REJECT_FETCH_FIRST; + FREE_AND_NULL(msg); + } + else if (!strcmp(msg, "needs force")) { + status = REF_STATUS_REJECT_NEEDS_FORCE; + FREE_AND_NULL(msg); + } + else if (!strcmp(msg, "stale info")) { + status = REF_STATUS_REJECT_STALE; + FREE_AND_NULL(msg); + } + else if (!strcmp(msg, "forced update")) { + forced = 1; + FREE_AND_NULL(msg); + } } } diff --git a/transport.c b/transport.c index 73defc4a5a..ecdcaae90d 100644 --- a/transport.c +++ b/transport.c @@ -463,11 +463,23 @@ static void print_ref_status(char flag, const char *summary, struct ref *to, struct ref *from, const char *msg, int porcelain, int summary_width) { + char *to_name = NULL; + const char *val; + int len; + + if (to && to->remote_status) { + val = parse_feature_value(to->remote_status, "ref", &len); + if (val && len) + to_name = xmemdupz(val, len); + } + if (porcelain) { if (from) - fprintf(stdout, "%c\t%s:%s\t", flag, from->name, to->name); + fprintf(stdout, "%c\t%s:%s\t", flag, from->name, + to_name ? to_name : to->name); else - fprintf(stdout, "%c\t:%s\t", flag, to->name); + fprintf(stdout, "%c\t:%s\t", flag, + to_name ? to_name : to->name); if (msg) fprintf(stdout, "%s (%s)\n", summary, msg); else @@ -481,9 +493,11 @@ static void print_ref_status(char flag, const char *summary, fprintf(stderr, " %s%c %-*s%s ", red, flag, summary_width, summary, reset); if (from) - fprintf(stderr, "%s -> %s", prettify_refname(from->name), prettify_refname(to->name)); + fprintf(stderr, "%s -> %s", + prettify_refname(from->name), + prettify_refname(to_name ? to_name : to->name)); else - fputs(prettify_refname(to->name), stderr); + fputs(prettify_refname(to_name ? to_name : to->name), stderr); if (msg) { fputs(" (", stderr); fputs(msg, stderr); @@ -491,6 +505,7 @@ static void print_ref_status(char flag, const char *summary, } fputc('\n', stderr); } + free(to_name); } static void print_ok_ref_status(struct ref *ref, int porcelain, int summary_width) @@ -531,8 +546,8 @@ static void print_ok_ref_status(struct ref *ref, int porcelain, int summary_widt } } -static int print_one_push_status(struct ref *ref, const char *dest, int count, - int porcelain, int summary_width) +static int _print_one_push_status(struct ref *ref, const char *dest, int count, + int porcelain, int summary_width) { if (!count) { char *url = transport_anonymize_url(dest); @@ -602,6 +617,53 @@ static int print_one_push_status(struct ref *ref, const char *dest, int count, return 1; } +static int print_one_push_status(struct ref *ref, const char *dest, int count, + int porcelain, int summary_width) +{ + char *head; + char *begin; + int n = 0; + + if (!ref->remote_status) + return _print_one_push_status(ref, dest, count, + porcelain, summary_width); + + head = ref->remote_status; + begin = head; + for (;;) { + char *end; + struct object_id old_oid; + struct object_id new_oid; + int forced_update; + + end = strstr(begin + 4, "ref="); + if (end) + *(end-1) = '\0'; + + oidcpy(&old_oid, &ref->old_oid); + oidcpy(&new_oid, &ref->new_oid); + forced_update = ref->forced_update; + + ref->remote_status = begin; + update_ref_from_remote_status(ref); + _print_one_push_status(ref, dest, count + n++, + porcelain, summary_width); + + oidcpy(&ref->old_oid, &old_oid); + oidcpy(&ref->new_oid, &new_oid); + ref->forced_update = forced_update; + + if (end) { + begin = end; + *(end-1) = ' '; + } else { + break; + } + } + ref->remote_status = head; + return n; +} + static int measure_abbrev(const struct object_id *oid, int sofar) { char hex[GIT_MAX_HEXSZ + 1]; From patchwork Sat Apr 18 16:03:31 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiang Xin X-Patchwork-Id: 11496643 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 8DFC9112C for ; Sat, 18 Apr 2020 16:04:05 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 6BDAC21D93 for ; Sat, 18 Apr 2020 16:04:05 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Jk9D9D5w" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727829AbgDRQEE (ORCPT ); Sat, 18 Apr 2020 12:04:04 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45424 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1727782AbgDRQDy (ORCPT ); Sat, 18 Apr 2020 12:03:54 -0400 Received: from mail-pg1-x541.google.com (mail-pg1-x541.google.com [IPv6:2607:f8b0:4864:20::541]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6F843C061A41 for ; Sat, 18 Apr 2020 09:03:54 -0700 (PDT) Received: by mail-pg1-x541.google.com with SMTP id r4so2745348pgg.4 for ; Sat, 18 Apr 2020 09:03:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=d/DgP5T5zsc04C29q+POM7cdXFPVFCDcqqnHcI0JCcI=; b=Jk9D9D5wVdxaSZMfcjD5MiLDg7H+4bo4s8r/LTFPCIE5smd/UhGJRL8h7DegvGGDeX wiaJ389DCiZxIW5wMBpCwEzRX8ziclGuwn4GkJE80vfD4iAhCyEZbO3VZL+rfnZjK8Fe Z1qsILnSiHikhmnUwxXe+B+FoviSsmLHEB89SKqidN/M0D71zGbWURU9IrROaXUhGKHK BFlaHAPSDsRpsu/Vl6Wsnul8x1almnxF4JqipfMPPB0clXs0QZeOxi67XZcD5vvoad8Q vUCbTF2TlZxvMYZSm9DGIVPVs64/b4zlyX3SSzNG5wGZgY2kBn1UqvqNNqa2+6Vq2/b3 7E3w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=d/DgP5T5zsc04C29q+POM7cdXFPVFCDcqqnHcI0JCcI=; b=ea9FR9ELXNkN+T5Q1lyj421WdX+0AKwSuUwyAltAjj0E3eSmHVEA0/od9ag0zO/RTc t1wk8KanxQ7yDGYHdyqBq8yltuBkc1RBrJGW9wi6vjJpOHKbh25utIs+w7vP2rfDmyPb 9U01FJN74VfzqwXe3n5ReSpANeXrFaQjLAMsziyp6Gq5Z8fy5A83sTcPZ5LpkOmW3u07 XpNEi4UoSxtPm2WKDplK01aBeze5zQE2XWaTxkI8ive08BKyPxXp5PENzXu8WBaoxyjf UZhIFpD8K7F9ocUnJTZxnI2IzO1r5lVh1L8qh2rHvCV5uQftIXUlrhvvftKiEkJvXau5 dGCQ== X-Gm-Message-State: AGi0PubruxQuvBRYQQtCEf/GEDiTnvT+MTyeQtlKtB7tJeA+KnIlHPSW +Xt7yuq5N82huuyd7KmRXHc= X-Google-Smtp-Source: APiQypKIUl6A+i8Y2m9KWrO1DqXH5nhQrIFGnY+XCrRceOPnvEP5M+jJ2nNzItImkUYl9IJmpKvCsg== X-Received: by 2002:aa7:9106:: with SMTP id 6mr8407689pfh.181.1587225833720; Sat, 18 Apr 2020 09:03:53 -0700 (PDT) Received: from tigtog.localdomain.localdomain ([144.34.163.219]) by smtp.gmail.com with ESMTPSA id i187sm22461649pfg.33.2020.04.18.09.03.53 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Sat, 18 Apr 2020 09:03:53 -0700 (PDT) From: Jiang Xin To: Junio C Hamano , Git List Cc: Jiang Xin Subject: [PATCH v13 5/8] receive-pack: feed extended_status to post-receive Date: Sat, 18 Apr 2020 12:03:31 -0400 Message-Id: <20200418160334.15631-6-worldhello.net@gmail.com> X-Mailer: git-send-email 2.26.0.rc0 In-Reply-To: <20200414123257.27449-1-worldhello.net@gmail.com> References: <20200414123257.27449-1-worldhello.net@gmail.com> MIME-Version: 1.0 Sender: git-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Jiang Xin When commands are fed to the "post-receive" hook, `extended_status` will be parsed and the real old-oid, new-oid, reference name will feed to the "post-receive" hook. Signed-off-by: Jiang Xin --- builtin/receive-pack.c | 57 +++++++++++++++++-- t/t5411/test-0032-report-alt.sh | 14 ++--- t/t5411/test-0033-report-alt--porcelain.sh | 14 ++--- .../test-0036-report-multi-alt-for-one-ref.sh | 12 +++- ...report-multi-alt-for-one-ref--porcelain.sh | 12 +++- t/t5411/test-0038-report-mixed-refs.sh | 2 +- .../test-0039-report-mixed-refs--porcelain.sh | 2 +- 7 files changed, 87 insertions(+), 26 deletions(-) diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c index 0081bf1415..529ac01e1c 100644 --- a/builtin/receive-pack.c +++ b/builtin/receive-pack.c @@ -754,17 +754,66 @@ static int feed_receive_hook(void *state_, const char **bufp, size_t *sizep) { struct receive_hook_feed_state *state = state_; struct command *cmd = state->cmd; + static char *extended_status = NULL; while (cmd && state->skip_broken && (cmd->error_string || cmd->did_not_exist)) cmd = cmd->next; if (!cmd) return -1; /* EOF */ + if (!bufp) + return 0; /* OK, can feed something. */ strbuf_reset(&state->buf); - strbuf_addf(&state->buf, "%s %s %s\n", - oid_to_hex(&cmd->old_oid), oid_to_hex(&cmd->new_oid), - cmd->ref_name); - state->cmd = cmd->next; + if (cmd->extended_status && extended_status == NULL) + extended_status = (char *)cmd->extended_status; + if (extended_status) { + struct object_id old_oid; + struct object_id new_oid; + char *end; + char *val; + int len; + + end = strstr(extended_status + 4, "ref="); + if (end) + *(end-1) = '\0'; + + val = (char *)parse_feature_value(extended_status, "old-oid", &len); + if (val && len && !get_oid_hex(val, &old_oid)) + strbuf_addf(&state->buf, "%s ", + oid_to_hex(&old_oid)); + else + strbuf_addf(&state->buf, "%s ", + oid_to_hex(&cmd->old_oid)); + + val = (char *)parse_feature_value(extended_status, "new-oid", &len); + if (val && len && !get_oid_hex(val, &new_oid)) + strbuf_addf(&state->buf, "%s ", + oid_to_hex(&new_oid)); + else + strbuf_addf(&state->buf, "%s ", + oid_to_hex(&cmd->new_oid)); + + val = (char *)parse_feature_value(extended_status, "ref", &len); + if (val && len) + strbuf_add(&state->buf, val, len); + else + strbuf_addstr(&state->buf, cmd->ref_name); + + strbuf_addch(&state->buf, '\n'); + + if (end) { + extended_status = end; + *(end-1) = ' '; + } else { + extended_status = NULL; + state->cmd = cmd->next; + } + } else { + strbuf_addf(&state->buf, "%s %s %s\n", + oid_to_hex(&cmd->old_oid), oid_to_hex(&cmd->new_oid), + cmd->ref_name); + state->cmd = cmd->next; + } if (bufp) { *bufp = state->buf.buf; *sizep = state->buf.len; diff --git a/t/t5411/test-0032-report-alt.sh b/t/t5411/test-0032-report-alt.sh index bf5faf4f2e..25bffd1127 100644 --- a/t/t5411/test-0032-report-alt.sh +++ b/t/t5411/test-0032-report-alt.sh @@ -50,7 +50,7 @@ test_expect_success "proc-receive: report alt (alt , $PROTOCOL)" remote: proc-receive< refs/for/master/topic remote: proc-receive> alt refs/for/master/topic refs/pull/123/head remote: # post-receive hook - remote: post-receive< refs/for/master/topic + remote: post-receive< refs/pull/123/head To * [new reference] HEAD -> refs/pull/123/head EOF @@ -80,7 +80,7 @@ test_expect_success "proc-receive: report alt (alt forced-update remote: proc-receive< refs/for/master/topic remote: proc-receive> alt refs/for/master/topic refs/pull/123/head forced-update remote: # post-receive hook - remote: post-receive< refs/for/master/topic + remote: post-receive< refs/pull/123/head To * [new reference] HEAD -> refs/pull/123/head EOF @@ -110,7 +110,7 @@ test_expect_success "proc-receive: report alt (alt old-oid=X, $P remote: proc-receive< refs/for/master/topic remote: proc-receive> alt refs/for/master/topic refs/pull/123/head old-oid= remote: # post-receive hook - remote: post-receive< refs/for/master/topic + remote: post-receive< refs/pull/123/head To .. HEAD -> refs/pull/123/head EOF @@ -140,7 +140,7 @@ test_expect_success "proc-receive: report alt (alt old-oid=X, $PROTOCOL)" remote: proc-receive< refs/for/master/topic remote: proc-receive> alt refs/for/master/topic old-oid= remote: # post-receive hook - remote: post-receive< refs/for/master/topic + remote: post-receive< refs/for/master/topic To .. HEAD -> refs/for/master/topic EOF @@ -170,7 +170,7 @@ test_expect_success "proc-receive: report alt (alt old-oid=X new-oid=Y, $P remote: proc-receive< refs/for/master/topic remote: proc-receive> alt refs/for/master/topic old-oid= new-oid= remote: # post-receive hook - remote: post-receive< refs/for/master/topic + remote: post-receive< refs/for/master/topic To .. HEAD -> refs/for/master/topic EOF @@ -210,9 +210,9 @@ test_expect_success "proc-receive: with multiple alt reports ($PROTOCOL)" ' remote: proc-receive> alt refs/for/next/topic refs/pull/123/head remote: proc-receive> alt refs/for/master/topic refs/pull/124/head old-oid= forced-update new-oid= remote: # post-receive hook - remote: post-receive< refs/for/next/topic + remote: post-receive< refs/pull/123/head remote: post-receive< refs/for/a/b/c/topic - remote: post-receive< refs/for/master/topic + remote: post-receive< refs/pull/124/head To * [new reference] HEAD -> refs/pull/123/head * [new reference] HEAD -> refs/for/a/b/c/topic diff --git a/t/t5411/test-0033-report-alt--porcelain.sh b/t/t5411/test-0033-report-alt--porcelain.sh index 3aea911407..9f1b577424 100644 --- a/t/t5411/test-0033-report-alt--porcelain.sh +++ b/t/t5411/test-0033-report-alt--porcelain.sh @@ -51,7 +51,7 @@ test_expect_success "proc-receive: report alt (alt , --porcelain, remote: proc-receive< refs/for/master/topic remote: proc-receive> alt refs/for/master/topic refs/pull/123/head remote: # post-receive hook - remote: post-receive< refs/for/master/topic + remote: post-receive< refs/pull/123/head To * HEAD:refs/pull/123/head [new reference] Done @@ -82,7 +82,7 @@ test_expect_success "proc-receive: report alt (alt forced-update remote: proc-receive< refs/for/master/topic remote: proc-receive> alt refs/for/master/topic refs/pull/123/head forced-update remote: # post-receive hook - remote: post-receive< refs/for/master/topic + remote: post-receive< refs/pull/123/head To * HEAD:refs/pull/123/head [new reference] Done @@ -113,7 +113,7 @@ test_expect_success "proc-receive: report alt (alt old-oid=X, -- remote: proc-receive< refs/for/master/topic remote: proc-receive> alt refs/for/master/topic refs/pull/123/head old-oid= remote: # post-receive hook - remote: post-receive< refs/for/master/topic + remote: post-receive< refs/pull/123/head To HEAD:refs/pull/123/head .. Done @@ -144,7 +144,7 @@ test_expect_success "proc-receive: report alt (alt old-oid=X, --porcelain, remote: proc-receive< refs/for/master/topic remote: proc-receive> alt refs/for/master/topic old-oid= remote: # post-receive hook - remote: post-receive< refs/for/master/topic + remote: post-receive< refs/for/master/topic To HEAD:refs/for/master/topic .. Done @@ -175,7 +175,7 @@ test_expect_success "proc-receive: report alt (alt old-oid=X new-oid=Y, -- remote: proc-receive< refs/for/master/topic remote: proc-receive> alt refs/for/master/topic old-oid= new-oid= remote: # post-receive hook - remote: post-receive< refs/for/master/topic + remote: post-receive< refs/for/master/topic To HEAD:refs/for/master/topic .. Done @@ -216,9 +216,9 @@ test_expect_success "proc-receive: with multiple alt reports (--porcelain, $PROT remote: proc-receive> alt refs/for/next/topic refs/pull/123/head remote: proc-receive> alt refs/for/master/topic refs/pull/124/head old-oid= forced-update new-oid= remote: # post-receive hook - remote: post-receive< refs/for/next/topic + remote: post-receive< refs/pull/123/head remote: post-receive< refs/for/a/b/c/topic - remote: post-receive< refs/for/master/topic + remote: post-receive< refs/pull/124/head To * HEAD:refs/pull/123/head [new reference] * HEAD:refs/for/a/b/c/topic [new reference] diff --git a/t/t5411/test-0036-report-multi-alt-for-one-ref.sh b/t/t5411/test-0036-report-multi-alt-for-one-ref.sh index d82b79ffff..1f6a4e10b2 100644 --- a/t/t5411/test-0036-report-multi-alt-for-one-ref.sh +++ b/t/t5411/test-0036-report-multi-alt-for-one-ref.sh @@ -25,7 +25,9 @@ test_expect_success "proc-receive: report multiple alt, no alt-ref for the 1st r remote: proc-receive> alt refs/for/master/topic refs/changes/24/124/1 old-oid= new-oid= remote: proc-receive> alt refs/for/master/topic refs/changes/25/125/1 old-oid= new-oid= remote: # post-receive hook - remote: post-receive< refs/for/master/topic + remote: post-receive< refs/for/master/topic + remote: post-receive< refs/changes/24/124/1 + remote: post-receive< refs/changes/25/125/1 To .. HEAD -> refs/for/master/topic * [new reference] HEAD -> refs/changes/24/124/1 @@ -67,7 +69,9 @@ test_expect_success "proc-receive: report multiple alt, no alt-ref for the 2nd r remote: proc-receive> alt refs/for/master/topic old-oid= new-oid= remote: proc-receive> alt refs/for/master/topic refs/changes/25/125/1 old-oid= new-oid= forced-update remote: # post-receive hook - remote: post-receive< refs/for/master/topic + remote: post-receive< refs/changes/24/124/1 + remote: post-receive< refs/for/master/topic + remote: post-receive< refs/changes/25/125/1 To * [new reference] HEAD -> refs/changes/24/124/1 .. HEAD -> refs/for/master/topic @@ -108,6 +112,7 @@ test_expect_success "proc-receive: report ok and alt for the same ref ($PROTOCOL remote: proc-receive> alt refs/for/master/topic refs/changes/24/124/1 new-oid= old-oid= remote: # post-receive hook remote: post-receive< refs/for/master/topic + remote: post-receive< refs/changes/24/124/1 To * [new reference] HEAD -> refs/for/master/topic .. HEAD -> refs/changes/24/124/1 @@ -146,7 +151,8 @@ test_expect_success "proc-receive: report multiple response ($PROTOCOL)" ' remote: proc-receive> alt refs/for/master/topic refs/changes/23/123/1 remote: proc-receive> alt refs/for/master/topic refs/changes/24/124/2 old-oid= new-oid= remote: # post-receive hook - remote: post-receive< refs/for/master/topic + remote: post-receive< refs/changes/23/123/1 + remote: post-receive< refs/changes/24/124/2 To * [new reference] HEAD -> refs/changes/23/123/1 .. HEAD -> refs/changes/24/124/2 diff --git a/t/t5411/test-0037-report-multi-alt-for-one-ref--porcelain.sh b/t/t5411/test-0037-report-multi-alt-for-one-ref--porcelain.sh index 8cca63c2de..3a08a21b87 100644 --- a/t/t5411/test-0037-report-multi-alt-for-one-ref--porcelain.sh +++ b/t/t5411/test-0037-report-multi-alt-for-one-ref--porcelain.sh @@ -25,7 +25,9 @@ test_expect_success "proc-receive: report multiple alt, no alt-ref for the 1st r remote: proc-receive> alt refs/for/master/topic refs/changes/24/124/1 old-oid= new-oid= remote: proc-receive> alt refs/for/master/topic refs/changes/25/125/1 old-oid= new-oid= remote: # post-receive hook - remote: post-receive< refs/for/master/topic + remote: post-receive< refs/for/master/topic + remote: post-receive< refs/changes/24/124/1 + remote: post-receive< refs/changes/25/125/1 To HEAD:refs/for/master/topic .. * HEAD:refs/changes/24/124/1 [new reference] @@ -68,7 +70,9 @@ test_expect_success "proc-receive: report multiple alt, no alt-ref for the 2nd r remote: proc-receive> alt refs/for/master/topic old-oid= new-oid= remote: proc-receive> alt refs/for/master/topic refs/changes/25/125/1 old-oid= new-oid= forced-update remote: # post-receive hook - remote: post-receive< refs/for/master/topic + remote: post-receive< refs/changes/24/124/1 + remote: post-receive< refs/for/master/topic + remote: post-receive< refs/changes/25/125/1 To * HEAD:refs/changes/24/124/1 [new reference] HEAD:refs/for/master/topic .. @@ -110,6 +114,7 @@ test_expect_success "proc-receive: report ok and alt for the same ref (--porcela remote: proc-receive> alt refs/for/master/topic refs/changes/24/124/1 new-oid= old-oid= remote: # post-receive hook remote: post-receive< refs/for/master/topic + remote: post-receive< refs/changes/24/124/1 To * HEAD:refs/for/master/topic [new reference] HEAD:refs/changes/24/124/1 .. @@ -149,7 +154,8 @@ test_expect_success "proc-receive: report multiple response (--porcelain, $PROTO remote: proc-receive> alt refs/for/master/topic refs/changes/23/123/1 remote: proc-receive> alt refs/for/master/topic refs/changes/24/124/2 old-oid= new-oid= remote: # post-receive hook - remote: post-receive< refs/for/master/topic + remote: post-receive< refs/changes/23/123/1 + remote: post-receive< refs/changes/24/124/2 To * HEAD:refs/changes/23/123/1 [new reference] HEAD:refs/changes/24/124/2 .. diff --git a/t/t5411/test-0038-report-mixed-refs.sh b/t/t5411/test-0038-report-mixed-refs.sh index 566cb6e098..5ac2771914 100644 --- a/t/t5411/test-0038-report-mixed-refs.sh +++ b/t/t5411/test-0038-report-mixed-refs.sh @@ -39,7 +39,7 @@ test_expect_success "proc-receive: report update of mixed refs ($PROTOCOL)" ' remote: post-receive< refs/heads/baz remote: post-receive< refs/for/next/topic remote: post-receive< refs/heads/foo - remote: post-receive< refs/for/master/topic + remote: post-receive< refs/for/master/topic To .. -> master * [new branch] HEAD -> bar diff --git a/t/t5411/test-0039-report-mixed-refs--porcelain.sh b/t/t5411/test-0039-report-mixed-refs--porcelain.sh index 4d617abb1a..55b408aca1 100644 --- a/t/t5411/test-0039-report-mixed-refs--porcelain.sh +++ b/t/t5411/test-0039-report-mixed-refs--porcelain.sh @@ -39,7 +39,7 @@ test_expect_success "proc-receive: report update of mixed refs (--porcelain, $PR remote: post-receive< refs/heads/baz remote: post-receive< refs/for/next/topic remote: post-receive< refs/heads/foo - remote: post-receive< refs/for/master/topic + remote: post-receive< refs/for/master/topic To :refs/heads/master .. * HEAD:refs/heads/bar [new branch] From patchwork Sat Apr 18 16:03:32 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiang Xin X-Patchwork-Id: 11496639 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 8BD81112C for ; Sat, 18 Apr 2020 16:04:03 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 73A9022242 for ; Sat, 18 Apr 2020 16:04:03 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="DEm/zWT5" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727818AbgDRQEC (ORCPT ); Sat, 18 Apr 2020 12:04:02 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45426 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1727783AbgDRQDz (ORCPT ); Sat, 18 Apr 2020 12:03:55 -0400 Received: from mail-pf1-x443.google.com (mail-pf1-x443.google.com [IPv6:2607:f8b0:4864:20::443]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0A6C0C0610D5 for ; Sat, 18 Apr 2020 09:03:55 -0700 (PDT) Received: by mail-pf1-x443.google.com with SMTP id w65so2655629pfc.12 for ; Sat, 18 Apr 2020 09:03:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=JYboaKpjAoYwIKr0RNOYcugoTKy6HS62FUf5oeWWZHc=; b=DEm/zWT5GICEGJB5EESzXuzcY90Pc//t4X9aRtChwKkBIUgvqz4ePzeHQ1SIuVQlf/ w8HT6T0h0Oz7RPGFdPzavzg/GhxzX3VjR4nXeJpQV92G7WBLPotoVVIcnGOvUXuab9cm Z1pwnJeo36mvNrmkQyQFeuC/RJtMPn7EeCDyLRUDmAMf9GTecTZpQiDw/7JPi9jVs/dI sB8x4Vaghfr3RcDcnjZMGggzYebPkaAYzvdPKNv/rA7k5o0bCrIFOaYYNbhtFVSkf4mA FZXM/xWITC4nJEEKI+7lwXDct9raFbmCW5ivmoshw5mXmc/xyiA1QVdzosqp61+svh+0 FVNg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=JYboaKpjAoYwIKr0RNOYcugoTKy6HS62FUf5oeWWZHc=; b=heUzE8ELYa8AHzCNtqbFnyPz6aHqheYpmmSWcpleBZJkK84sH2+s884b19BTnCJ20c /oKVYtgVH9f+Mq+qV3IpLL8JAH/e/Wo86c7VThHCefeZXPMouvZmpdk47ab/QBe8ZhVi u6r/JQCi2aFk7RUG7T89QF1CHp6n4nBDhEq8PXPoch7n22SXj5G7gTmUKmKnamXw9iix JFETfD9Wk79WWGlxwjLsevwQE2UK8v+Ls5K/bE+q/DrdAahmTdmc4OpEjbDtOhb6FmkL E5VTSmw3vW7VtVpS+IQD9mlmEEKxqbFRHc7yTU6bXMw54JJ4jocu0uN224Zum4EwqmG0 bybw== X-Gm-Message-State: AGi0PuY6Yce4V/6GgYr1Ra/DOgpVfPx3cBMWSQ0/diAMZiAfQ2YfsXpA s7qNldByqIT1Wy2xUYrwUJY= X-Google-Smtp-Source: APiQypKCXKEmSpziPp/2olqZdrrCpIaMOrTVPuVUn2ftwJqEvAHvgO+LED+XtGmWzdHVfcHmfGsDBw== X-Received: by 2002:aa7:96c1:: with SMTP id h1mr8868674pfq.212.1587225834604; Sat, 18 Apr 2020 09:03:54 -0700 (PDT) Received: from tigtog.localdomain.localdomain ([144.34.163.219]) by smtp.gmail.com with ESMTPSA id i187sm22461649pfg.33.2020.04.18.09.03.53 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Sat, 18 Apr 2020 09:03:54 -0700 (PDT) From: Jiang Xin To: Junio C Hamano , Git List Cc: Jiang Xin Subject: [PATCH v13 6/8] refs.c: refactor to reuse ref_is_hidden() Date: Sat, 18 Apr 2020 12:03:32 -0400 Message-Id: <20200418160334.15631-7-worldhello.net@gmail.com> X-Mailer: git-send-email 2.26.0.rc0 In-Reply-To: <20200414123257.27449-1-worldhello.net@gmail.com> References: <20200414123257.27449-1-worldhello.net@gmail.com> MIME-Version: 1.0 Sender: git-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Jiang Xin Add new function `ref_is_matched()` to reuse `ref_is_hidden()`. Will use this function for `receive-pack` to check commands with specific prefixes. Test case t5512 covered this change. Signed-off-by: Jiang Xin --- refs.c | 13 +++++++++---- refs.h | 1 + 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/refs.c b/refs.c index 1ab0bb54d3..a20f56a463 100644 --- a/refs.c +++ b/refs.c @@ -1388,14 +1388,14 @@ int parse_hide_refs_config(const char *var, const char *value, const char *secti return 0; } -int ref_is_hidden(const char *refname, const char *refname_full) +int ref_matches(struct string_list *match_refs, const char *refname, const char *refname_full) { int i; - if (!hide_refs) + if (!match_refs) return 0; - for (i = hide_refs->nr - 1; i >= 0; i--) { - const char *match = hide_refs->items[i].string; + for (i = match_refs->nr - 1; i >= 0; i--) { + const char *match = match_refs->items[i].string; const char *subject; int neg = 0; const char *p; @@ -1421,6 +1421,11 @@ int ref_is_hidden(const char *refname, const char *refname_full) return 0; } +int ref_is_hidden(const char *refname, const char *refname_full) +{ + return ref_matches(hide_refs, refname, refname_full); +} + const char *find_descendant_ref(const char *dirname, const struct string_list *extras, const struct string_list *skip) diff --git a/refs.h b/refs.h index 545029c6d8..d02c72d3ad 100644 --- a/refs.h +++ b/refs.h @@ -739,6 +739,7 @@ int parse_hide_refs_config(const char *var, const char *value, const char *); * parameter always points to the full ref name. */ int ref_is_hidden(const char *, const char *); +int ref_matches(struct string_list *, const char *, const char *); enum ref_type { REF_TYPE_PER_WORKTREE, /* refs inside refs/ but not shared */ From patchwork Sat Apr 18 16:03:33 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiang Xin X-Patchwork-Id: 11496641 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 64FAA912 for ; Sat, 18 Apr 2020 16:04:04 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 41FEA221F7 for ; Sat, 18 Apr 2020 16:04:04 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="IGXz5EaT" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727783AbgDRQED (ORCPT ); Sat, 18 Apr 2020 12:04:03 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45432 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1727784AbgDRQD4 (ORCPT ); Sat, 18 Apr 2020 12:03:56 -0400 Received: from mail-pf1-x42a.google.com (mail-pf1-x42a.google.com [IPv6:2607:f8b0:4864:20::42a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9599DC061A10 for ; Sat, 18 Apr 2020 09:03:56 -0700 (PDT) Received: by mail-pf1-x42a.google.com with SMTP id k15so2674540pfh.6 for ; Sat, 18 Apr 2020 09:03:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=YO+Jild8cK2jj0ZaoXmG/dP6f5PV/a/I0McRT+cpVh4=; b=IGXz5EaTo6eAQAiQeOibdUzxtRUfBYiVZ4EEf7cyFXFcXSzYEnva3TA1Hh/lisLn/W BlsA7cNU0khedTkR8XXWxTnod0AAkX2m+1xXAjPEFbVM9Bnhz0S/1dKBOTHSr2BDXlhu 7nlWsr0mA6lOiTJ1UHnqtWi5sbPnb14CTGv5xP2YAjVD3BpsWgbexzGYejcBvkqCB3pA eXfPDwGRdQ6W7f/FnOVtSM0YeJeVsejgg5exvbY32ZlFdCJoNYKq8WznRZVU+GmxfBlM Mg/tKM/stYMhgkTT0i6COPudVKYJksSJ3H2I1vmyt0/pr2avXA5LCrmXPQ9Rdsh5+eK7 JaIA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=YO+Jild8cK2jj0ZaoXmG/dP6f5PV/a/I0McRT+cpVh4=; b=LEHeUKRJ3FHyO1H7soI/FCM5H9oUrpsh+0O6d8PYijqika7Sg3KYO5mXIPWif4cBuu JGzUjQiU/XDs6vE1CkRlvo8lcL+vMpu7mdy90kBgUImH0WiZbURld3iX+eX7Xb2GIbmp DbnDBrQsTbqfwFdnW1dWBj5N2Cbukk4spdhrV6olPEVV9Jj4QtxjIbJwZ2agekdgSHtv ChMn1yu/zqkzzvL6CxOiMnv/r9fFgJfygKFPb3jssg6OnoeIJSNiSa0Xa3c+nsX8Rxvu r1trW9O+7srfr82PBeR7hyJDjvPNIFwFO79mn0tlIVaHKXE9e7dqDss+zNwmWNTf0IMk sJ3A== X-Gm-Message-State: AGi0PuYjeBExOgHjglRYFp9aq+QHZqFdBgTkKcMcl90Nzf1FyZ/I31Z6 j1PLeEhmoyibxodaBQNEWWLNYZb0 X-Google-Smtp-Source: APiQypLyVyXpRHZN8+eBkHkXIg0v725uA40kixjowq+wq8XuRiHrun7m/iecut7iPLZAei8w6OXYuw== X-Received: by 2002:a62:6204:: with SMTP id w4mr8183506pfb.273.1587225835646; Sat, 18 Apr 2020 09:03:55 -0700 (PDT) Received: from tigtog.localdomain.localdomain ([144.34.163.219]) by smtp.gmail.com with ESMTPSA id i187sm22461649pfg.33.2020.04.18.09.03.54 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Sat, 18 Apr 2020 09:03:55 -0700 (PDT) From: Jiang Xin To: Junio C Hamano , Git List Cc: Jiang Xin Subject: [PATCH v13 7/8] receive-pack: new config receive.procReceiveRefs Date: Sat, 18 Apr 2020 12:03:33 -0400 Message-Id: <20200418160334.15631-8-worldhello.net@gmail.com> X-Mailer: git-send-email 2.26.0.rc0 In-Reply-To: <20200414123257.27449-1-worldhello.net@gmail.com> References: <20200414123257.27449-1-worldhello.net@gmail.com> MIME-Version: 1.0 Sender: git-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Jiang Xin Add a new multi-valued config variable "receive.procReceiveRefs" for `receive-pack` command, like the follows: git config --system --add receive.procReceiveRefs refs/for git config --system --add receive.procReceiveRefs refs/drafts If the specific prefix strings match the reference names of the commands which are sent from git client to `receive-pack`, these commands will be executed by an external hook (named "proc-receive"), instead of the internal `execute_commands` function. For example, if it is set to "refs/for", pushing to a reference such as "refs/for/master" will not create or update reference "refs/for/master", but may create or update a pull request directly by running the hook "proc-receive". Signed-off-by: Jiang Xin --- Documentation/config/receive.txt | 14 +++ builtin/receive-pack.c | 43 +++++++-- t/t5411/test-0010-proc-receive-settings.sh | 7 ++ t/t5411/test-0040-process-all-refs.sh | 93 ++++++++++++++++++ .../test-0041-process-all-refs--porcelain.sh | 94 +++++++++++++++++++ 5 files changed, 244 insertions(+), 7 deletions(-) create mode 100644 t/t5411/test-0010-proc-receive-settings.sh create mode 100644 t/t5411/test-0040-process-all-refs.sh create mode 100644 t/t5411/test-0041-process-all-refs--porcelain.sh diff --git a/Documentation/config/receive.txt b/Documentation/config/receive.txt index 65f78aac37..e7b967feeb 100644 --- a/Documentation/config/receive.txt +++ b/Documentation/config/receive.txt @@ -114,6 +114,20 @@ receive.hideRefs:: An attempt to update or delete a hidden ref by `git push` is rejected. +receive.procReceiveRefs:: + This is a multi-valued variable that defines reference prefixes + to match the commands in `receive-pack`. Commands matching the + prefixes will be executed by an external hook "proc-receive", + instead of the internal `execute_commands` function. If this + variable is not defined, the "proc-receive" hook will never be + used, and all commands will be executed by the internal + `execute_commands` function. + + For example, if this variable is set to "refs/for", pushing to + reference such as "refs/for/master" will not create or update a + reference named "refs/for/master", but may create or update a + pull request directly by running the hook "proc-receive". + receive.updateServerInfo:: If set to true, git-receive-pack will run git-update-server-info after receiving data from git-push and updating refs. diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c index 529ac01e1c..25ff718cdf 100644 --- a/builtin/receive-pack.c +++ b/builtin/receive-pack.c @@ -76,6 +76,7 @@ static struct object_id push_cert_oid; static struct signature_check sigcheck; static const char *push_cert_nonce; static const char *cert_nonce_seed; +static struct string_list proc_receive_refs; static const char *NONCE_UNSOLICITED = "UNSOLICITED"; static const char *NONCE_BAD = "BAD"; @@ -228,6 +229,20 @@ static int receive_pack_config(const char *var, const char *value, void *cb) return 0; } + if (strcmp(var, "receive.procreceiverefs") == 0) { + char *prefix; + int len; + + if (!value) + return config_error_nonbool(var); + prefix = xstrdup(value); + len = strlen(prefix); + while (len && prefix[len - 1] == '/') + prefix[--len] = '\0'; + string_list_append(&proc_receive_refs, prefix); + return 0; + } + return git_default_config(var, value, cb); } @@ -1856,15 +1871,26 @@ static void execute_commands(struct command *commands, * Try to find commands that have special prefix in their reference names, * and mark them to run an external "proc-receive" hook later. */ - for (cmd = commands; cmd; cmd = cmd->next) { - if (!should_process_cmd(cmd)) - continue; + if (proc_receive_refs.nr > 0) { + struct strbuf refname_full = STRBUF_INIT; + size_t prefix_len; - /* TODO: replace the fixed prefix by looking up git config variables. */ - if (!strncmp(cmd->ref_name, "refs/for/", 9)) { - cmd->run_proc_receive = RUN_PROC_RECEIVE_SCHEDULED; - run_proc_receive = 1; + strbuf_addstr(&refname_full, get_git_namespace()); + prefix_len = refname_full.len; + + for (cmd = commands; cmd; cmd = cmd->next) { + if (!should_process_cmd(cmd)) + continue; + + strbuf_setlen(&refname_full, prefix_len); + strbuf_addstr(&refname_full, cmd->ref_name); + if (ref_matches(&proc_receive_refs, cmd->ref_name, refname_full.buf)) { + cmd->run_proc_receive = RUN_PROC_RECEIVE_SCHEDULED; + run_proc_receive = 1; + } } + + strbuf_release(&refname_full); } if (run_receive_hook(commands, "pre-receive", 0, push_options)) { @@ -2329,6 +2355,8 @@ int cmd_receive_pack(int argc, const char **argv, const char *prefix) OPT_END() }; + string_list_init(&proc_receive_refs, 0); + packet_trace_identity("receive-pack"); argc = parse_options(argc, argv, prefix, options, receive_pack_usage, 0); @@ -2444,5 +2472,6 @@ int cmd_receive_pack(int argc, const char **argv, const char *prefix) oid_array_clear(&shallow); oid_array_clear(&ref); free((void *)push_cert_nonce); + string_list_clear(&proc_receive_refs, 0); return 0; } diff --git a/t/t5411/test-0010-proc-receive-settings.sh b/t/t5411/test-0010-proc-receive-settings.sh new file mode 100644 index 0000000000..a36809927b --- /dev/null +++ b/t/t5411/test-0010-proc-receive-settings.sh @@ -0,0 +1,7 @@ +test_expect_success "add two receive.procReceiveRefs settings" ' + ( + cd "$upstream" && + git config --add receive.procReceiveRefs refs/for && + git config --add receive.procReceiveRefs refs/review/ + ) +' diff --git a/t/t5411/test-0040-process-all-refs.sh b/t/t5411/test-0040-process-all-refs.sh new file mode 100644 index 0000000000..bfb14c53fc --- /dev/null +++ b/t/t5411/test-0040-process-all-refs.sh @@ -0,0 +1,93 @@ +test_expect_success "config receive.procReceiveRefs = refs ($PROTOCOL)" ' + git -C "$upstream" config --unset-all receive.procReceiveRefs && + git -C "$upstream" config --add receive.procReceiveRefs refs +' + +# Refs of upstream : master(A) +# Refs of workbench: master(A) tags/v123 +test_expect_success "setup upstream branches ($PROTOCOL)" ' + ( + cd "$upstream" && + git update-ref refs/heads/master $B && + git update-ref refs/heads/foo $A && + git update-ref refs/heads/bar $A && + git update-ref refs/heads/baz $A + ) + +' + +test_expect_success "setup proc-receive hook ($PROTOCOL)" ' + write_script "$upstream/hooks/proc-receive" <<-EOF + printf >&2 "# proc-receive hook\n" + test-tool proc-receive -v \ + -r "ft refs/heads/master" \ + -r "ft refs/heads/foo" \ + -r "ft refs/heads/bar" \ + -r "alt refs/for/master/topic refs/pull/123/head old-oid=$A new-oid=$B " \ + -r "alt refs/for/next/topic refs/pull/124/head old-oid=$B new-oid=$A forced-update" + EOF +' + +# Refs of upstream : master(B) foo(A) bar(A)) baz(A) +# Refs of workbench: master(A) tags/v123 +# git push -f : master(A) (NULL) (B) refs/for/master/topic(A) refs/for/next/topic(A) +test_expect_success "proc-receive: process all refs ($PROTOCOL)" ' + git -C workbench push -f origin \ + HEAD:refs/heads/master \ + :refs/heads/foo \ + $B:refs/heads/bar \ + HEAD:refs/for/master/topic \ + HEAD:refs/for/next/topic \ + >out 2>&1 && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + remote: # pre-receive hook + remote: pre-receive< refs/heads/bar + remote: pre-receive< refs/heads/foo + remote: pre-receive< refs/heads/master + remote: pre-receive< refs/for/master/topic + remote: pre-receive< refs/for/next/topic + remote: # proc-receive hook + remote: proc-receive< refs/heads/bar + remote: proc-receive< refs/heads/foo + remote: proc-receive< refs/heads/master + remote: proc-receive< refs/for/master/topic + remote: proc-receive< refs/for/next/topic + remote: proc-receive> ft refs/heads/master + remote: proc-receive> ft refs/heads/foo + remote: proc-receive> ft refs/heads/bar + remote: proc-receive> alt refs/for/master/topic refs/pull/123/head old-oid= new-oid= + remote: proc-receive> alt refs/for/next/topic refs/pull/124/head old-oid= new-oid= forced-update + remote: # post-receive hook + remote: post-receive< refs/heads/bar + remote: post-receive< refs/heads/foo + remote: post-receive< refs/heads/master + remote: post-receive< refs/pull/123/head + remote: post-receive< refs/pull/124/head + To + .. -> bar + - [deleted] foo + + ... HEAD -> master (forced update) + .. HEAD -> refs/pull/123/head + + ... HEAD -> refs/pull/124/head (forced update) + EOF + test_cmp expect actual && + git -C "$upstream" show-ref >out && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + refs/heads/bar + refs/heads/baz + refs/heads/master + EOF + test_cmp expect actual +' + +# Refs of upstream : master(A) bar(A) baz(B) +# Refs of workbench: master(A) tags/v123 +test_expect_success "cleanup ($PROTOCOL)" ' + ( + cd "$upstream" && + git update-ref -d refs/heads/bar && + git update-ref -d refs/heads/baz + ) +' diff --git a/t/t5411/test-0041-process-all-refs--porcelain.sh b/t/t5411/test-0041-process-all-refs--porcelain.sh new file mode 100644 index 0000000000..02b24f4b16 --- /dev/null +++ b/t/t5411/test-0041-process-all-refs--porcelain.sh @@ -0,0 +1,94 @@ +test_expect_success "config receive.procReceiveRefs = refs ($PROTOCOL)" ' + git -C "$upstream" config --unset-all receive.procReceiveRefs && + git -C "$upstream" config --add receive.procReceiveRefs refs +' + +# Refs of upstream : master(A) +# Refs of workbench: master(A) tags/v123 +test_expect_success "setup upstream branches ($PROTOCOL)" ' + ( + cd "$upstream" && + git update-ref refs/heads/master $B && + git update-ref refs/heads/foo $A && + git update-ref refs/heads/bar $A && + git update-ref refs/heads/baz $A + ) + +' + +test_expect_success "setup proc-receive hook ($PROTOCOL)" ' + write_script "$upstream/hooks/proc-receive" <<-EOF + printf >&2 "# proc-receive hook\n" + test-tool proc-receive -v \ + -r "ft refs/heads/master" \ + -r "ft refs/heads/foo" \ + -r "ft refs/heads/bar" \ + -r "alt refs/for/master/topic refs/pull/123/head old-oid=$A new-oid=$B " \ + -r "alt refs/for/next/topic refs/pull/124/head old-oid=$B new-oid=$A forced-update" + EOF +' + +# Refs of upstream : master(B) foo(A) bar(A)) baz(A) +# Refs of workbench: master(A) tags/v123 +# git push -f : master(A) (NULL) (B) refs/for/master/topic(A) refs/for/next/topic(A) +test_expect_success "proc-receive: process all refs (--porcelain) ($PROTOCOL)" ' + git -C workbench push --porcelain -f origin \ + HEAD:refs/heads/master \ + :refs/heads/foo \ + $B:refs/heads/bar \ + HEAD:refs/for/master/topic \ + HEAD:refs/for/next/topic \ + >out 2>&1 && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + remote: # pre-receive hook + remote: pre-receive< refs/heads/bar + remote: pre-receive< refs/heads/foo + remote: pre-receive< refs/heads/master + remote: pre-receive< refs/for/master/topic + remote: pre-receive< refs/for/next/topic + remote: # proc-receive hook + remote: proc-receive< refs/heads/bar + remote: proc-receive< refs/heads/foo + remote: proc-receive< refs/heads/master + remote: proc-receive< refs/for/master/topic + remote: proc-receive< refs/for/next/topic + remote: proc-receive> ft refs/heads/master + remote: proc-receive> ft refs/heads/foo + remote: proc-receive> ft refs/heads/bar + remote: proc-receive> alt refs/for/master/topic refs/pull/123/head old-oid= new-oid= + remote: proc-receive> alt refs/for/next/topic refs/pull/124/head old-oid= new-oid= forced-update + remote: # post-receive hook + remote: post-receive< refs/heads/bar + remote: post-receive< refs/heads/foo + remote: post-receive< refs/heads/master + remote: post-receive< refs/pull/123/head + remote: post-receive< refs/pull/124/head + To + :refs/heads/bar .. + - :refs/heads/foo [deleted] + + HEAD:refs/heads/master ... (forced update) + HEAD:refs/pull/123/head .. + + HEAD:refs/pull/124/head ... (forced update) + Done + EOF + test_cmp expect actual && + git -C "$upstream" show-ref >out && + make_user_friendly_and_stable_output actual && + cat >expect <<-EOF && + refs/heads/bar + refs/heads/baz + refs/heads/master + EOF + test_cmp expect actual +' + +# Refs of upstream : master(A) bar(A) baz(B) +# Refs of workbench: master(A) tags/v123 +test_expect_success "cleanup ($PROTOCOL)" ' + ( + cd "$upstream" && + git update-ref -d refs/heads/bar && + git update-ref -d refs/heads/baz + ) +' From patchwork Sat Apr 18 16:03:34 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiang Xin X-Patchwork-Id: 11496637 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 743C3112C for ; Sat, 18 Apr 2020 16:04:00 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 5B51021D93 for ; Sat, 18 Apr 2020 16:04:00 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="bVQxsYUL" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727812AbgDRQD7 (ORCPT ); Sat, 18 Apr 2020 12:03:59 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45434 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1727790AbgDRQD5 (ORCPT ); Sat, 18 Apr 2020 12:03:57 -0400 Received: from mail-pf1-x42a.google.com (mail-pf1-x42a.google.com [IPv6:2607:f8b0:4864:20::42a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D3046C061A0C for ; Sat, 18 Apr 2020 09:03:56 -0700 (PDT) Received: by mail-pf1-x42a.google.com with SMTP id x3so2668023pfp.7 for ; Sat, 18 Apr 2020 09:03:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=aFVbeO4bXagJhDbblegxUu51pn+AAl+6nu9bWOWjzwo=; b=bVQxsYULp3NEtergVq/5qXTKOiOD5OnqSTaTSwJ0GSTTkI1jOJutYn4zm6RNtU4Mtl p7rl6IU5BRmMG4UYAHTLc7/Q7YrFBK/jKDz9yA475TbYagB0McVd15FFbnHvg4cip3lv tiEvkR5DIBmNAOKpl7Mfbey9muYXiGqBkk28hz1taXQWBcrP4B4qeYHk/yJrXAKGCqxZ yphastErvvjVEjfW+ZFJihjnN+xkffoH2aCdoU2k4IYAy5qI0jiHdjyPGj5vCRnmSsCv yKBmdbDNeSvSiebUYLePKPtthKASWcgGJNF0CbOUAedzAQfS2f668ulSHAdBUoWgOtK2 SVQA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=aFVbeO4bXagJhDbblegxUu51pn+AAl+6nu9bWOWjzwo=; b=S9KYJF9wA5czLTMV7kFP/WqJFdR3zNeGaqSlRptfcofdp3YG3mdSUV4HZl81hkNzU6 aqt8jisjgKO8A5To9Qy+XQVaPWG20n5PEej5cDcHF3zHZT6HuS+MYiADgxEZ/gFJKt7Q t7Gfuw3Z4J6SPZZzw23C33gLbq9lCbgG3OtJEperGUnp2DQOqwDOQnzbff/S5ca7i3zM XPN0ZdJuZa39FxZCSErgXkaEIHRhLu6zkNNaKM1ZP7tWNvkl/E1Qnv9B/Jnq7rL6q4Ii u8BIZTQvCsyw2n895CJ/DOXrQDV2/Kn9ton+zz8dBWXl39S3ndJo1XPZ2mczl9t26hhn 3TVA== X-Gm-Message-State: AGi0PuY9WOsQ3oO3k77YdcnmjSZuDjpoqEjcjkgwUpQ9y8JcG7mT97jD 5UmspUgp8jrgE/dtxlAuxZM= X-Google-Smtp-Source: APiQypJEi+oioEl9p+S6bXZi+X/77Qx6YV3FxPIWuNkOSFR6x6xHXqxjSt5Ug6FoYjL0otHjknDlaA== X-Received: by 2002:a62:2a8d:: with SMTP id q135mr1684764pfq.10.1587225836404; Sat, 18 Apr 2020 09:03:56 -0700 (PDT) Received: from tigtog.localdomain.localdomain ([144.34.163.219]) by smtp.gmail.com with ESMTPSA id i187sm22461649pfg.33.2020.04.18.09.03.55 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Sat, 18 Apr 2020 09:03:56 -0700 (PDT) From: Jiang Xin To: Junio C Hamano , Git List Cc: Jiang Xin Subject: [PATCH v13 8/8] doc: add documentation for the proc-receive hook Date: Sat, 18 Apr 2020 12:03:34 -0400 Message-Id: <20200418160334.15631-9-worldhello.net@gmail.com> X-Mailer: git-send-email 2.26.0.rc0 In-Reply-To: <20200414123257.27449-1-worldhello.net@gmail.com> References: <20200414123257.27449-1-worldhello.net@gmail.com> MIME-Version: 1.0 Sender: git-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Jiang Xin Add documentation for the new "proc-receive" hook. Signed-off-by: Jiang Xin --- Documentation/githooks.txt | 58 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/Documentation/githooks.txt b/Documentation/githooks.txt index 3dccab5375..a0ea829435 100644 --- a/Documentation/githooks.txt +++ b/Documentation/githooks.txt @@ -333,6 +333,64 @@ The default 'update' hook, when enabled--and with `hooks.allowunannotated` config option unset or set to false--prevents unannotated tags to be pushed. +proc-receive +~~~~~~~~~~~~ + +This hook is invoked by linkgit:git-receive-pack[1]. If the server has +set the multi-valued config variable `receive.procReceiveRefs`, and the +commands sent to 'receive-pack' have matching reference names, these +commands will be executed by this hook, instead of by the internal +`execute_commands()` function. This hook is responsible for updating +the relevant references and reporting the results back to 'receive-pack'. + +This hook executes once for the receive operation. It takes no +arguments, but uses a pkt-line format protocol to communicate with +'receive-pack' to read commands, push-options and send results. In the +following example for the protocol, the letter 'S' stands for +'receive-pack' and the letter 'H' stands for this hook. + + # Version and features negotiation. + S: PKT-LINE(version=1\0push-options atomic...) + S: flush-pkt + H: PKT-LINE(version=1\0push-options...) + H: flush-pkt + + # Send commands from server to the hook. + S: PKT-LINE( ) + S: ... ... + S: flush-pkt + # Send push-options only if the 'push-options' feature is enabled. + S: PKT-LINE(push-option) + S: ... ... + S: flush-pkt + + # Receive result from the hook. + # OK, run this command successfully. + H: PKT-LINE(ok ) + # NO, I reject it. + H: PKT-LINE(ng ) + # Fall through, let 'receive-pack' to execute it. + H: PKT-LINE(ft ) + # OK, but has an alternate reference. The alternate reference name + # is given in the third parameter, and other status can be given in + # key-value pairs. + H: PKT-LINE(alt old-oid= new-oid= + forced-update) + H: ... ... + H: flush-pkt + +Each command for the 'proc-receive' hook may point to a pseudo-reference +and always has a zero-old as its old-oid, while the 'proc-receive' hook +may update an alternate reference and the alternate reference may exist +already with a non-zero old-oid. For this case, this hook may return +different OID and different reference name as extended status of the +report line. + +The report of the commands of this hook should have the same order as +the input. The exit status of the 'proc-receive' hook only determines +the success or failure of the group of commands sent to it, unless +atomic push is in use. + [[post-receive]] post-receive ~~~~~~~~~~~~