From patchwork Wed Dec 9 20:06:47 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Orgad Shaneh X-Patchwork-Id: 11962451 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.7 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 007E8C4361B for ; Wed, 9 Dec 2020 20:07:39 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id C149D23A02 for ; Wed, 9 Dec 2020 20:07:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1732003AbgLIUHi (ORCPT ); Wed, 9 Dec 2020 15:07:38 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60486 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728197AbgLIUHc (ORCPT ); Wed, 9 Dec 2020 15:07:32 -0500 Received: from mail-wr1-x42c.google.com (mail-wr1-x42c.google.com [IPv6:2a00:1450:4864:20::42c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3FB94C0613D6 for ; Wed, 9 Dec 2020 12:06:52 -0800 (PST) Received: by mail-wr1-x42c.google.com with SMTP id y17so3089233wrr.10 for ; Wed, 09 Dec 2020 12:06:52 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=message-id:in-reply-to:references:from:date:subject:fcc :content-transfer-encoding:mime-version:to:cc; bh=V5jL6CvthRDOm7VFkTZI+7ymROBsvC8v5TDlobM54nQ=; b=h5v98Vu3EDotimjXWeAY0prT1XAQ1mt8S4r32wQ/3kQf3Yfm4L1ZZN5i7EROo+y5P9 1uL13xwwd2/dZdt2HuZavM6MoSE/OwoAk3e9vCdKQbtBUP87VIgemayL5D2z8e0Nvda2 Oj0MO80xiVkGlFzdHSRdKlRlE5vrxIsTcwQCcA+q2EZ3443iPuLiE5cPBQhkHzGtSS/y 98Rj4HIVeKrIeftuvEMJnxUof5AdBKew6+u1GsTfdgKLrOwQetKr6BeFatz2fk7nTTT9 /3hLqjTUtYSh9F/mzKm+/jpJH3jajFtR4fkZMYL9uWirc4Llfsx4rGyHSlWlimA5TCOg C9qw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:message-id:in-reply-to:references:from:date :subject:fcc:content-transfer-encoding:mime-version:to:cc; bh=V5jL6CvthRDOm7VFkTZI+7ymROBsvC8v5TDlobM54nQ=; b=f/xKLYSxNRfNy7i2dmt067mfGFdg+CLGmFzEr9NlCjnie5A4JtyY3CS1JJpWGyrb/o 76V1B3ZvCR89VY9zfDaPiOg65ddCpyw6fVP8qvV1iPb+yOAQjOksePjjNa+Cn1TYqD6u REm4lGsKM08ElKux3QMtgG1za92YnbygctNElTjMrvqe4kvKysiD1Gy+jf5ilNJ3AAnR WZI6ZwyJwXJDa0SEb3u4PEIplOjtiJSWMbWAu+CNVceA5c7pF6SBXY0LdTUJwFbeKJzs XUGBqW86olu7ZLtCT5Rg7Y4XgSo91imLiTmKtUa+/UsjaB3+dV/NCOb55gDyhV7SRcKN My/A== X-Gm-Message-State: AOAM532gY5Q5Mwq59v4w1UFE/9VdZ609CuLoCez2Rt6Qqe1PTt2rCtp0 JMvwskVeIXyRKh1VcB/EzUXJ5wf9a8s= X-Google-Smtp-Source: ABdhPJy35ktkuW69NT5XaIShnHkF4qRM3Gh2/yFIHBONhOMaOEi/HRDG8cIOwQHw7Pyo/RhsJuBL8A== X-Received: by 2002:a5d:690d:: with SMTP id t13mr4463259wru.410.1607544410653; Wed, 09 Dec 2020 12:06:50 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id c81sm5817065wmd.6.2020.12.09.12.06.50 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 09 Dec 2020 12:06:50 -0800 (PST) Message-Id: <27e66d43c833c2e5b8b612e91b6b513076d7fcb7.1607544408.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Wed, 09 Dec 2020 20:06:47 +0000 Subject: [PATCH v5 1/2] hooks: lay foundations for passing stdin to hooks Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: Orgad Shaneh , Eric Sunshine , =?utf-8?b?w4Z2YXIgQXJuZmrDtnLDsA==?= Bjarmason , Orgad Shaneh , Orgad Shaneh Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Orgad Shaneh From: Orgad Shaneh Used in the follow-up commit for enabling stdin for commit-related hooks. Signed-off-by: Orgad Shaneh --- builtin/commit.c | 8 ++++---- builtin/merge.c | 6 +++--- commit.c | 4 ++-- commit.h | 3 ++- run-command.c | 6 +++--- run-command.h | 17 ++++++++++++----- sequencer.c | 4 ++-- 7 files changed, 28 insertions(+), 20 deletions(-) diff --git a/builtin/commit.c b/builtin/commit.c index 505fe60956d..70a7842e224 100644 --- a/builtin/commit.c +++ b/builtin/commit.c @@ -699,7 +699,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix, /* This checks and barfs if author is badly specified */ determine_author_info(author_ident); - if (!no_verify && run_commit_hook(use_editor, index_file, "pre-commit", NULL)) + if (!no_verify && run_commit_hook(use_editor, index_file, 0, "pre-commit", NULL)) return 0; if (squash_message) { @@ -998,7 +998,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix, return 0; } - if (run_commit_hook(use_editor, index_file, "prepare-commit-msg", + if (run_commit_hook(use_editor, index_file, 0, "prepare-commit-msg", git_path_commit_editmsg(), hook_arg1, hook_arg2, NULL)) return 0; @@ -1015,7 +1015,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix, } if (!no_verify && - run_commit_hook(use_editor, index_file, "commit-msg", git_path_commit_editmsg(), NULL)) { + run_commit_hook(use_editor, index_file, 0, "commit-msg", git_path_commit_editmsg(), NULL)) { return 0; } @@ -1701,7 +1701,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix) repo_rerere(the_repository, 0); run_auto_maintenance(quiet); - run_commit_hook(use_editor, get_index_file(), "post-commit", NULL); + run_commit_hook(use_editor, get_index_file(), 0, "post-commit", NULL); if (amend && !no_post_rewrite) { commit_post_rewrite(the_repository, current_head, &oid); } diff --git a/builtin/merge.c b/builtin/merge.c index 1cff7307153..26e6ae15993 100644 --- a/builtin/merge.c +++ b/builtin/merge.c @@ -836,7 +836,7 @@ static void prepare_to_commit(struct commit_list *remoteheads) struct strbuf msg = STRBUF_INIT; const char *index_file = get_index_file(); - if (!no_verify && run_commit_hook(0 < option_edit, index_file, "pre-merge-commit", NULL)) + if (!no_verify && run_commit_hook(0 < option_edit, index_file, 0, "pre-merge-commit", NULL)) abort_commit(remoteheads, NULL); /* * Re-read the index as pre-merge-commit hook could have updated it, @@ -864,7 +864,7 @@ static void prepare_to_commit(struct commit_list *remoteheads) append_signoff(&msg, ignore_non_trailer(msg.buf, msg.len), 0); write_merge_heads(remoteheads); write_file_buf(git_path_merge_msg(the_repository), msg.buf, msg.len); - if (run_commit_hook(0 < option_edit, get_index_file(), "prepare-commit-msg", + if (run_commit_hook(0 < option_edit, get_index_file(), 0, "prepare-commit-msg", git_path_merge_msg(the_repository), "merge", NULL)) abort_commit(remoteheads, NULL); if (0 < option_edit) { @@ -873,7 +873,7 @@ static void prepare_to_commit(struct commit_list *remoteheads) } if (!no_verify && run_commit_hook(0 < option_edit, get_index_file(), - "commit-msg", + 0, "commit-msg", git_path_merge_msg(the_repository), NULL)) abort_commit(remoteheads, NULL); diff --git a/commit.c b/commit.c index fe1fa3dc41f..3f5a50164eb 100644 --- a/commit.c +++ b/commit.c @@ -1631,7 +1631,7 @@ size_t ignore_non_trailer(const char *buf, size_t len) } int run_commit_hook(int editor_is_used, const char *index_file, - const char *name, ...) + unsigned flags, const char *name, ...) { struct strvec hook_env = STRVEC_INIT; va_list args; @@ -1646,7 +1646,7 @@ int run_commit_hook(int editor_is_used, const char *index_file, strvec_push(&hook_env, "GIT_EDITOR=:"); va_start(args, name); - ret = run_hook_ve(hook_env.v, name, args); + ret = run_hook_ve(hook_env.v, flags, name, args); va_end(args); strvec_clear(&hook_env); diff --git a/commit.h b/commit.h index 5467786c7be..72215d57fb2 100644 --- a/commit.h +++ b/commit.h @@ -352,6 +352,7 @@ int compare_commits_by_commit_date(const void *a_, const void *b_, void *unused) int compare_commits_by_gen_then_commit_date(const void *a_, const void *b_, void *unused); LAST_ARG_MUST_BE_NULL -int run_commit_hook(int editor_is_used, const char *index_file, const char *name, ...); +int run_commit_hook(int editor_is_used, const char *index_file, unsigned flags, + const char *name, ...); #endif /* COMMIT_H */ diff --git a/run-command.c b/run-command.c index ea4d0fb4b15..30d69562f43 100644 --- a/run-command.c +++ b/run-command.c @@ -1344,7 +1344,7 @@ const char *find_hook(const char *name) return path.buf; } -int run_hook_ve(const char *const *env, const char *name, va_list args) +int run_hook_ve(const char *const *env, unsigned flags, const char *name, va_list args) { struct child_process hook = CHILD_PROCESS_INIT; const char *p; @@ -1357,7 +1357,7 @@ int run_hook_ve(const char *const *env, const char *name, va_list args) while ((p = va_arg(args, const char *))) strvec_push(&hook.args, p); hook.env = env; - hook.no_stdin = 1; + hook.no_stdin = !(flags & RUN_HOOK_ALLOW_STDIN); hook.stdout_to_stderr = 1; hook.trace2_hook_name = name; @@ -1370,7 +1370,7 @@ int run_hook_le(const char *const *env, const char *name, ...) int ret; va_start(args, name); - ret = run_hook_ve(env, name, args); + ret = run_hook_ve(env, 0, name, args); va_end(args); return ret; diff --git a/run-command.h b/run-command.h index 6472b38bde4..e613e5e3f92 100644 --- a/run-command.h +++ b/run-command.h @@ -201,22 +201,29 @@ int run_command(struct child_process *); */ const char *find_hook(const char *name); +#define RUN_HOOK_ALLOW_STDIN 1 + /** * Run a hook. - * The first argument is a pathname to an index file, or NULL - * if the hook uses the default index file or no index is needed. - * The second argument is the name of the hook. + * The env argument is an array of environment variables, or NULL + * if the hook uses the default environment and doesn't require + * additional variables. + * The flags argument is an OR'ed collection of feature bits like + * RUN_HOOK_ALLOW_STDIN defined above, which enables + * stdin for the child process (the default is no_stdin). + * The name argument is the name of the hook. * The further arguments correspond to the hook arguments. * The last argument has to be NULL to terminate the arguments list. * If the hook does not exist or is not executable, the return * value will be zero. * If it is executable, the hook will be executed and the exit * status of the hook is returned. - * On execution, .stdout_to_stderr and .no_stdin will be set. + * On execution, .stdout_to_stderr will be set, and .no_stdin will be + * set unless RUN_HOOK_ALLOW_STDIN flag is requested. */ LAST_ARG_MUST_BE_NULL int run_hook_le(const char *const *env, const char *name, ...); -int run_hook_ve(const char *const *env, const char *name, va_list args); +int run_hook_ve(const char *const *env, unsigned flags, const char *name, va_list args); /* * Trigger an auto-gc diff --git a/sequencer.c b/sequencer.c index 8909a467700..5f48d32e2fa 100644 --- a/sequencer.c +++ b/sequencer.c @@ -1203,7 +1203,7 @@ static int run_prepare_commit_msg_hook(struct repository *r, } else { arg1 = "message"; } - if (run_commit_hook(0, r->index_file, "prepare-commit-msg", name, + if (run_commit_hook(0, r->index_file, 0, "prepare-commit-msg", name, arg1, arg2, NULL)) ret = error(_("'prepare-commit-msg' hook failed")); @@ -1528,7 +1528,7 @@ static int try_to_commit(struct repository *r, goto out; } - run_commit_hook(0, r->index_file, "post-commit", NULL); + run_commit_hook(0, r->index_file, 0, "post-commit", NULL); if (flags & AMEND_MSG) commit_post_rewrite(r, current_head, oid); From patchwork Wed Dec 9 20:06:48 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Orgad Shaneh X-Patchwork-Id: 11962453 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.7 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5C238C433FE for ; Wed, 9 Dec 2020 20:08:01 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 2A46723A02 for ; Wed, 9 Dec 2020 20:08:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2388135AbgLIUHi (ORCPT ); Wed, 9 Dec 2020 15:07:38 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60488 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731920AbgLIUHd (ORCPT ); Wed, 9 Dec 2020 15:07:33 -0500 Received: from mail-wr1-x42b.google.com (mail-wr1-x42b.google.com [IPv6:2a00:1450:4864:20::42b]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 25189C061793 for ; Wed, 9 Dec 2020 12:06:53 -0800 (PST) Received: by mail-wr1-x42b.google.com with SMTP id r7so3100425wrc.5 for ; Wed, 09 Dec 2020 12:06:53 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=message-id:in-reply-to:references:from:date:subject:fcc :content-transfer-encoding:mime-version:to:cc; bh=FmgNRbyjUoRS4/6Ti3xTllFp9JJ7Tn2iIHP8SrSOZxs=; b=aiNiGm1aiFJnpEE0RhMLUWPJiAgubbt916kDY2NvUmCUfN5ey7DZh+dRgzDIKIorBt MAuqnYGpAlQpZr1a4asP2fPqE/R82jNF9GFcMBUCraStDkt2IMqLQl+wWh6BjM11zq+J FsFOpBnfAQGWhQh7XGYtGLtONZkkkFpR7TbCKXy1HFJZZLyDZ6OCE8GX6+vClD/MpWcq vQ0YYeQ/6gO8eoSCcZCHlTSlQfryL2qcw8fZY2FxjzJ0Z0KWpeTlzWxrpgBBt2nWVCIJ CJrzEuTFX596ndzCq6lZd1JX5V32KPrwqMT/4DH4S6JMjU1Lgfadr5ojCbutdIY4BqEY h4uQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:message-id:in-reply-to:references:from:date :subject:fcc:content-transfer-encoding:mime-version:to:cc; bh=FmgNRbyjUoRS4/6Ti3xTllFp9JJ7Tn2iIHP8SrSOZxs=; b=mQ0d/zUjQMVwpicwcUQT171h75XJLa+W70YqdM6kcQFOqWK7GChqn6EhxVjynl4/+K z1InAQHvBW8s8xv5H1MDs4sSHpkTsxwTRdlMmSYz/PPfj1kJRQVoULCaJNFBBHqE0YMU vWrBenws/s/c/LdoTd30s2x9PPO4bjdjyWzNDbIgWlsnGmwUksOkq1R1bV6lJ5P2KMLK dU5xhsd1z/T77gghmj0/2AOImVh0tRc8sTIIcpJdOLYQlI/d9lnWt7oYiLKHTejI6TXQ 0mO02WnF/OK3dboZ0Uuz6SSfKPWJBUWK2H3TBOAPPlUZ3TsI/B1S5gzg23uLXai0/KrJ PK/A== X-Gm-Message-State: AOAM5303r/CjCXIerPY3LJPSP14o4JyHIDTihvzNlmb4Q+PQGsF8qRI/ XcPwMxAQ23EPNk/VX1VzL9K05YMymVI= X-Google-Smtp-Source: ABdhPJwXtMZH7Wt8WxneyNCm5dAtBMq9Ae8/DTJeprzNRHpoT9UtlDdNmlPG5Ope+qrA+96G3nLe8Q== X-Received: by 2002:a05:6000:112:: with SMTP id o18mr4433102wrx.7.1607544411537; Wed, 09 Dec 2020 12:06:51 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id h184sm5987371wmh.23.2020.12.09.12.06.50 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 09 Dec 2020 12:06:50 -0800 (PST) Message-Id: <25db4da3cd5fc7e81141078261086c392541c5d1.1607544408.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Wed, 09 Dec 2020 20:06:48 +0000 Subject: [PATCH v5 2/2] hooks: allow input from stdin for commit-related hooks Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: Orgad Shaneh , Eric Sunshine , =?utf-8?b?w4Z2YXIgQXJuZmrDtnLDsA==?= Bjarmason , Orgad Shaneh , Orgad Shaneh Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Orgad Shaneh From: Orgad Shaneh Let hooks receive user input if applicable. Closing stdin originates in f5bbc3225 (Port git commit to C, 2007). Looks like the original shell implementation did have stdin open. Due to stdin being closed, hooks that require user input have to either read the input directly from the console (which can't work when running from GUI applications), or popup a GUI dialog (which is inconvenient when running from the terminal). This allows for example prompting the user to choose an issue in prepare-commit-msg, and add "Fixes #123" to the commit message. Another possible use-case is running sanity test on pre-commit, and having a prompt like "This and that issue were found in your changes. Are you sure you want to commit? [Y/N]". It's important to note that the hook author should be aware that stdin is not always applicable. For example, when running from IDE. This can be checked by isatty on stdin. The hooks should handle cases of closed input, and possibly fall-back to GUI input, or have sane defaults with a message to the user on this case. Allow stdin only for commit-related hooks. Some of the other hooks pass their own input to the hook, so don't change them. Note: If pre-commit reads from stdin, and git commit is executed with -F - (read message from stdin), stdin cannot be passed to the hook, since it will consume it before reaching the point where it is read for the commit message. Signed-off-by: Orgad Shaneh --- builtin/commit.c | 14 ++++-- builtin/merge.c | 12 +++-- sequencer.c | 6 +-- ...3-pre-commit-and-pre-merge-commit-hooks.sh | 46 ++++++++++++++++++- t/t7504-commit-msg-hook.sh | 15 ++++++ t/t7505-prepare-commit-msg-hook.sh | 14 ++++++ 6 files changed, 94 insertions(+), 13 deletions(-) diff --git a/builtin/commit.c b/builtin/commit.c index 70a7842e224..074a57937f1 100644 --- a/builtin/commit.c +++ b/builtin/commit.c @@ -695,11 +695,14 @@ static int prepare_to_commit(const char *index_file, const char *prefix, int clean_message_contents = (cleanup_mode != COMMIT_MSG_CLEANUP_NONE); int old_display_comment_prefix; int merge_contains_scissors = 0; + int message_from_stdin = logfile && !strcmp(logfile, "-"); + const unsigned hook_flags = message_from_stdin ? 0 : RUN_HOOK_ALLOW_STDIN; /* This checks and barfs if author is badly specified */ determine_author_info(author_ident); - if (!no_verify && run_commit_hook(use_editor, index_file, 0, "pre-commit", NULL)) + if (!no_verify && + run_commit_hook(use_editor, index_file, hook_flags, "pre-commit", NULL)) return 0; if (squash_message) { @@ -724,7 +727,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix, if (have_option_m && !fixup_message) { strbuf_addbuf(&sb, &message); hook_arg1 = "message"; - } else if (logfile && !strcmp(logfile, "-")) { + } else if (message_from_stdin) { if (isatty(0)) fprintf(stderr, _("(reading log message from standard input)\n")); if (strbuf_read(&sb, 0, 0) < 0) @@ -998,7 +1001,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix, return 0; } - if (run_commit_hook(use_editor, index_file, 0, "prepare-commit-msg", + if (run_commit_hook(use_editor, index_file, RUN_HOOK_ALLOW_STDIN, "prepare-commit-msg", git_path_commit_editmsg(), hook_arg1, hook_arg2, NULL)) return 0; @@ -1015,7 +1018,8 @@ static int prepare_to_commit(const char *index_file, const char *prefix, } if (!no_verify && - run_commit_hook(use_editor, index_file, 0, "commit-msg", git_path_commit_editmsg(), NULL)) { + run_commit_hook(use_editor, index_file, RUN_HOOK_ALLOW_STDIN, "commit-msg", + git_path_commit_editmsg(), NULL)) { return 0; } @@ -1701,7 +1705,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix) repo_rerere(the_repository, 0); run_auto_maintenance(quiet); - run_commit_hook(use_editor, get_index_file(), 0, "post-commit", NULL); + run_commit_hook(use_editor, get_index_file(), RUN_HOOK_ALLOW_STDIN, "post-commit", NULL); if (amend && !no_post_rewrite) { commit_post_rewrite(the_repository, current_head, &oid); } diff --git a/builtin/merge.c b/builtin/merge.c index 26e6ae15993..d6faca59258 100644 --- a/builtin/merge.c +++ b/builtin/merge.c @@ -836,8 +836,11 @@ static void prepare_to_commit(struct commit_list *remoteheads) struct strbuf msg = STRBUF_INIT; const char *index_file = get_index_file(); - if (!no_verify && run_commit_hook(0 < option_edit, index_file, 0, "pre-merge-commit", NULL)) + if (!no_verify && + run_commit_hook(0 < option_edit, index_file, RUN_HOOK_ALLOW_STDIN, + "pre-merge-commit", NULL)) { abort_commit(remoteheads, NULL); + } /* * Re-read the index as pre-merge-commit hook could have updated it, * and write it out as a tree. We must do this before we invoke @@ -864,8 +867,9 @@ static void prepare_to_commit(struct commit_list *remoteheads) append_signoff(&msg, ignore_non_trailer(msg.buf, msg.len), 0); write_merge_heads(remoteheads); write_file_buf(git_path_merge_msg(the_repository), msg.buf, msg.len); - if (run_commit_hook(0 < option_edit, get_index_file(), 0, "prepare-commit-msg", - git_path_merge_msg(the_repository), "merge", NULL)) + if (run_commit_hook(0 < option_edit, get_index_file(), RUN_HOOK_ALLOW_STDIN, + "prepare-commit-msg", git_path_merge_msg(the_repository), + "merge", NULL)) abort_commit(remoteheads, NULL); if (0 < option_edit) { if (launch_editor(git_path_merge_msg(the_repository), NULL, NULL)) @@ -873,7 +877,7 @@ static void prepare_to_commit(struct commit_list *remoteheads) } if (!no_verify && run_commit_hook(0 < option_edit, get_index_file(), - 0, "commit-msg", + RUN_HOOK_ALLOW_STDIN, "commit-msg", git_path_merge_msg(the_repository), NULL)) abort_commit(remoteheads, NULL); diff --git a/sequencer.c b/sequencer.c index 5f48d32e2fa..5190879695a 100644 --- a/sequencer.c +++ b/sequencer.c @@ -1203,8 +1203,8 @@ static int run_prepare_commit_msg_hook(struct repository *r, } else { arg1 = "message"; } - if (run_commit_hook(0, r->index_file, 0, "prepare-commit-msg", name, - arg1, arg2, NULL)) + if (run_commit_hook(0, r->index_file, RUN_HOOK_ALLOW_STDIN, + "prepare-commit-msg", name, arg1, arg2, NULL)) ret = error(_("'prepare-commit-msg' hook failed")); return ret; @@ -1528,7 +1528,7 @@ static int try_to_commit(struct repository *r, goto out; } - run_commit_hook(0, r->index_file, 0, "post-commit", NULL); + run_commit_hook(0, r->index_file, RUN_HOOK_ALLOW_STDIN, "post-commit", NULL); if (flags & AMEND_MSG) commit_post_rewrite(r, current_head, oid); diff --git a/t/t7503-pre-commit-and-pre-merge-commit-hooks.sh b/t/t7503-pre-commit-and-pre-merge-commit-hooks.sh index b3485450a20..a243b7efa19 100755 --- a/t/t7503-pre-commit-and-pre-merge-commit-hooks.sh +++ b/t/t7503-pre-commit-and-pre-merge-commit-hooks.sh @@ -7,6 +7,7 @@ test_description='pre-commit and pre-merge-commit hooks' HOOKDIR="$(git rev-parse --git-dir)/hooks" PRECOMMIT="$HOOKDIR/pre-commit" PREMERGE="$HOOKDIR/pre-merge-commit" +POSTCOMMIT="$HOOKDIR/post-commit" # Prepare sample scripts that write their $0 to actual_hooks test_expect_success 'sample script setup' ' @@ -28,11 +29,14 @@ test_expect_success 'sample script setup' ' echo $0 >>actual_hooks test $GIT_PREFIX = "success/" EOF - write_script "$HOOKDIR/check-author.sample" <<-\EOF + write_script "$HOOKDIR/check-author.sample" <<-\EOF && echo $0 >>actual_hooks test "$GIT_AUTHOR_NAME" = "New Author" && test "$GIT_AUTHOR_EMAIL" = "newauthor@example.com" EOF + write_script "$HOOKDIR/user-input.sample" <<-\EOF + ! read -r line || echo "$line" >hook_input + EOF ' test_expect_success 'root commit' ' @@ -278,4 +282,44 @@ test_expect_success 'check the author in hook' ' test_cmp expected_hooks actual_hooks ' +test_expect_success 'with user input' ' + test_when_finished "rm -f \"$PRECOMMIT\" user_input hook_input" && + cp "$HOOKDIR/user-input.sample" "$PRECOMMIT" && + echo "user input" >user_input && + echo "more" >>file && + git add file && + git commit -m "more" user_input && + echo "more" >>file && + git add file && + git commit -F - user_input && + echo "more" >>file && + git add file && + git commit -m "more" user_input && + git checkout side && + git merge -m "merge master" master "$HOOK" <<'EOF' +#!/bin/sh +! read -r line || echo "$line" >"$1" +EOF +chmod +x "$HOOK" + +test_expect_success 'hook with user input' ' + + echo "additional" >>file && + git add file && + echo "user input" | git commit -m "additional" && + commit_msg_is "user input" + +' test_done diff --git a/t/t7505-prepare-commit-msg-hook.sh b/t/t7505-prepare-commit-msg-hook.sh index 94f85cdf831..aa9c9375e63 100755 --- a/t/t7505-prepare-commit-msg-hook.sh +++ b/t/t7505-prepare-commit-msg-hook.sh @@ -91,6 +91,11 @@ else fi test "$GIT_EDITOR" = : && source="$source (no editor)" +if read -r line +then + source="$source $line" +fi + if test $rebasing = 1 then echo "$source $(get_last_cmd)" >"$1" @@ -113,6 +118,15 @@ test_expect_success 'with hook (-m)' ' ' +test_expect_success 'with hook (-m and input)' ' + + echo "more" >>file && + git add file && + echo "user input" | git commit -m "more" && + test "$(git log -1 --pretty=format:%s)" = "message (no editor) user input" + +' + test_expect_success 'with hook (-m editor)' ' echo "more" >> file &&