From patchwork Sun Mar 8 15:38:15 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jiang Xin X-Patchwork-Id: 11425711 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 6542E14B7 for ; Sun, 8 Mar 2020 15:38:23 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 463E120866 for ; Sun, 8 Mar 2020 15:38:23 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="EQsf3s5F" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726318AbgCHPiW (ORCPT ); Sun, 8 Mar 2020 11:38:22 -0400 Received: from mail-pf1-f182.google.com ([209.85.210.182]:43741 "EHLO mail-pf1-f182.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726271AbgCHPiW (ORCPT ); Sun, 8 Mar 2020 11:38:22 -0400 Received: by mail-pf1-f182.google.com with SMTP id c144so3657366pfb.10 for ; Sun, 08 Mar 2020 08:38:21 -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=vc5YaSnlEaNjsL7hECj+viFsVC6sdb8TgOzX+JmXC3I=; b=EQsf3s5FOEmsHeCEOO/zKGga2XbYUqv/A9vpvqjnhy2JT2sAcVwBENjByVE1mQVCkH Fhs1kKzZPW+mg8NRAvqudpY2fXw5fdFZ4qzPub+EGzmx8PQh5+0Uz8WVUx4x7Gvo86Ru aEa++073XKmZQV+SMJSSA34K6clNjLX317fbVhwiWMhM/yqFttHFAIBdvGGkuLoLO2MH 0KyXs2JsUKwiYR4iqc4guE9hkC4dRr4gsqu/wTP82kFPQp06wadqyRAzSjfCbXuq3tXt vQ+A3TIv8A2mOlLBrCgCDIlQ8M4MZtsyHlXWz4ffXziSbybppWJnoyGPzlbVptqK7kVh jNZg== 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=vc5YaSnlEaNjsL7hECj+viFsVC6sdb8TgOzX+JmXC3I=; b=fE5X7pi9Jc0dS/2ZpkBCJrSaXQMu6F+QvDzsu3HacPD0W66Phc77wAi/YvW5Y8s1ue P974xNeMRLzi8QZQ3zCi2YedP/YFqcGREpa5d6ARjQQ+jmkvZ8wQjQhSDcCuDSw/lq9d IIwVlteO+dSs7b87OPV8QFFHfEaxyak1Wz2+Z+TjBqPSf52kY7k/HP1XElzJtWmpYYK4 M5xNMX8LdWdr7yD6F66+XI1X2KWYo0gF0zFBIZIUyJrxjeShrSnDHHMEjxsfgHk4GI1J Mfn6sNz+x6KgIJhAcModxoylB6zbZMMRH6oV4uRwF83ol/kImdP4bPwIbzPilBs2WalV BT5A== X-Gm-Message-State: ANhLgQ3Dg5gTbVFdBYiQDBLd/qIzw/RMuqECbA0rnHKOWBAJb5sUwUP1 UlpUDGiY6NEbSAQvBhnlup776ieXwZOBTw== X-Google-Smtp-Source: ADFU+vvAN/04bz/XpeV1J2dcYwbwa+o7jDlPiGRwOxiUOE8jikrlltIGYswqdeZqwTyLR4v07izGxQ== X-Received: by 2002:a62:2ad1:: with SMTP id q200mr13290217pfq.123.1583681900757; Sun, 08 Mar 2020 08:38:20 -0700 (PDT) Received: from tigtog.localdomain.localdomain ([144.34.163.219]) by smtp.gmail.com with ESMTPSA id a143sm18141508pfd.108.2020.03.08.08.38.20 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 08 Mar 2020 08:38:20 -0700 (PDT) From: Jiang Xin To: Junio C Hamano , Git List Cc: Jiang Xin Subject: [PATCH v2 4/5] receive-pack: read env from proc-receive output Date: Sun, 8 Mar 2020 11:38:15 -0400 Message-Id: <20200308153816.4690-2-worldhello.net@gmail.com> X-Mailer: git-send-email 2.26.0.rc0 In-Reply-To: References: MIME-Version: 1.0 Sender: git-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Jiang Xin The “post-receive” hook may need the pull request ID generated by the “proc-receive” hook. The results can be passed between hooks by environment variables. Each line of the message received from the standard output of the “proc-receive” hook in the key=value format is parsed as environment and these variables will be sent to environment of the “post-receive” hook. Signed-off-by: Jiang Xin --- builtin/receive-pack.c | 38 ++++++++++++++++++-- t/t5411-proc-receive-hook.sh | 70 ++++++++++++++++++++++++++++++++++++ 2 files changed, 105 insertions(+), 3 deletions(-) diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c index 5aff682758..d854952410 100644 --- a/builtin/receive-pack.c +++ b/builtin/receive-pack.c @@ -87,6 +87,7 @@ static const char *nonce_status; static long nonce_stamp_slop; static timestamp_t nonce_stamp_slop_limit; static struct ref_transaction *transaction; +struct argv_array post_receive_env_array; static enum { KEEPALIVE_NEVER = 0, @@ -694,7 +695,9 @@ struct receive_hook_feed_state { }; typedef int (*feed_fn)(void *, const char **, size_t *); +typedef void (*stdout_handler_fn)(int out); static int run_and_feed_hook(const char *hook_name, feed_fn feed, + stdout_handler_fn stdout_handler, struct receive_hook_feed_state *feed_state) { struct child_process proc = CHILD_PROCESS_INIT; @@ -716,9 +719,15 @@ static int run_and_feed_hook(const char *hook_name, feed_fn feed, proc.argv = argv; proc.in = -1; - proc.stdout_to_stderr = 1; + if (stdout_handler) + proc.out = -1; + else + proc.stdout_to_stderr = 1; proc.trace2_hook_name = hook_name; + if (!strcmp(hook_name, "post-receive") && post_receive_env_array.argc > 0) + argv_array_pushv(&proc.env_array, post_receive_env_array.argv); + if (feed_state->push_options) { int i; for (i = 0; i < feed_state->push_options->nr; i++) @@ -763,6 +772,10 @@ static int run_and_feed_hook(const char *hook_name, feed_fn feed, break; } close(proc.in); + + if (stdout_handler) + stdout_handler(proc.out); + if (use_sideband) finish_async(&muxer); @@ -819,7 +832,7 @@ static int run_receive_hook(struct command *commands, return 0; state.cmd = commands; state.push_options = push_options; - status = run_and_feed_hook(hook_name, feed_receive_hook, &state); + status = run_and_feed_hook(hook_name, feed_receive_hook, NULL, &state); strbuf_release(&state.buf); return status; } @@ -853,6 +866,23 @@ static int run_update_hook(struct command *cmd) return finish_command(&proc); } +static void prepare_post_receive_env(int in) +{ + struct strbuf stdout_buf = STRBUF_INIT; + + while (strbuf_getwholeline_fd(&stdout_buf, in, '\n') != EOF) { + char *p = stdout_buf.buf + stdout_buf.len -1; + if (*p =='\n') + *p = '\0'; + p = strchr(stdout_buf.buf, '='); + if (p == NULL) + continue; + argv_array_push(&post_receive_env_array, stdout_buf.buf); + strbuf_reset(&stdout_buf); + } + strbuf_release(&stdout_buf); +} + static int run_proc_receive_hook(struct command *commands, const struct string_list *push_options) { @@ -869,7 +899,8 @@ static int run_proc_receive_hook(struct command *commands, return 0; state.cmd = commands; state.push_options = push_options; - status = run_and_feed_hook("proc-receive", feed_receive_hook, &state); + status = run_and_feed_hook("proc-receive", + feed_receive_hook, prepare_post_receive_env, &state); strbuf_release(&state.buf); return status; } @@ -2040,6 +2071,7 @@ int cmd_receive_pack(int argc, const char **argv, const char *prefix) }; string_list_init(&proc_receive_refs, 0); + argv_array_init(&post_receive_env_array); packet_trace_identity("receive-pack"); diff --git a/t/t5411-proc-receive-hook.sh b/t/t5411-proc-receive-hook.sh index e3bb421078..6f35867e85 100755 --- a/t/t5411-proc-receive-hook.sh +++ b/t/t5411-proc-receive-hook.sh @@ -687,4 +687,74 @@ test_expect_success "(6) push both a normal and a special refs (declined)" ' test_cmp expect actual ' +test_expect_success "(7) restore pre-receive hook" ' + mv $bare/hooks/pre-receive $bare/hooks/pre-receive.fail && + mv $bare/hooks/pre-receive.ok $bare/hooks/pre-receive +' + +test_expect_success "(7) new proc-receive and post-receive hooks (pass environment variables)" ' + ## proc-receive hook + mv $bare/hooks/proc-receive $bare/hooks/proc-receive.ok && + cat >$bare/hooks/proc-receive <<-EOF && + #!/bin/sh + + printf >&2 "execute: proc-receive hook\n" + + while read old new ref + do + printf >&2 ">> old: \$old, new: \$new, ref: \$ref.\n" + done + + printf "GIT_VAR1=var1\n" + printf "GIT_VAR2=var2\n" + printf "AGIT_VAR1=foo\n" + printf "AGIT_VAR2=bar\n" + EOF + chmod a+x $bare/hooks/proc-receive && + + ## post-receive hook + mv $bare/hooks/post-receive $bare/hooks/post-receive.ok && + cat >$bare/hooks/post-receive <<-EOF && + #!/bin/sh + + printf >&2 "execute: post-receive hook\n" + + while read old new ref + do + printf >&2 ">> old: \$old, new: \$new, ref: \$ref.\n" + done + + for k in GIT_VAR1 GIT_VAR2 AGIT_VAR1 AGIT_VAR2 + do + if test -n "\$(eval echo \\"\\\$\$k\")" + then + printf >&2 ">> has env: \$k=\$(eval echo \\"\\\$\$k\").\n" + fi + done + EOF + chmod a+x $bare/hooks/post-receive +' + +test_expect_success "(7) push one special ref (show environments)" ' + ( + cd work && + git push origin \ + HEAD:refs/for/master/my/topic + ) >out 2>&1 && + grep "^remote:" out | sed -e "s/ *\$//g" >actual && + cat >expect <<-EOF && + remote: execute: pre-receive hook + remote: >> old: $ZERO_OID, new: $B, ref: refs/for/master/my/topic. + remote: execute: proc-receive hook + remote: >> old: $ZERO_OID, new: $B, ref: refs/for/master/my/topic. + remote: execute: post-receive hook + remote: >> old: $ZERO_OID, new: $B, ref: refs/for/master/my/topic. + remote: >> has env: GIT_VAR1=var1. + remote: >> has env: GIT_VAR2=var2. + remote: >> has env: AGIT_VAR1=foo. + remote: >> has env: AGIT_VAR2=bar. + EOF + test_cmp expect actual +' + test_done