From patchwork Thu Mar 7 19:59:35 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Kristoffer Haugsbakk X-Patchwork-Id: 13586207 Received: from fout5-smtp.messagingengine.com (fout5-smtp.messagingengine.com [103.168.172.148]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 23AB0138484 for ; Thu, 7 Mar 2024 20:00:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=103.168.172.148 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1709841622; cv=none; b=g5bw51qOUrQK8+07M6eatQZVBoW1lXkS38m5hSwv4XXnOxwagw+YmVivFsH8Q+HrzG6FtQaESWK0WIJCJxx9Bf0jSuyavRUB8Je5h71qsqN40QmmjZ7AgYbVtXA/NrZ61zpIHE5TIWgOOhT+hvGLkdPfV49tZKRkiC7vlrQM94A= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1709841622; c=relaxed/simple; bh=BcZNKx1Y5GsB302yMqh5pZfqdAvKP6vd/HLEOuDoMw4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=GAIKE3Vc/m+ZuM1z+IK2pc8nQeEIn838R2ywtRPQ6gi6HxYZzAEg+lH3gBbQ7yX3XQyq+inNEKIbXBPZVMsJ4FClHlZkS61Hwqk/T3C3wZ59v6Yh4jfONeXJKYJgLbcDAzMq+JHjk1QAn4GmbvXGdq/RiojZoWWY8ZzZ10KeBp0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=khaugsbakk.name; spf=pass smtp.mailfrom=khaugsbakk.name; dkim=pass (2048-bit key) header.d=khaugsbakk.name header.i=@khaugsbakk.name header.b=YD3q6lAY; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=WpjkOLaD; arc=none smtp.client-ip=103.168.172.148 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=khaugsbakk.name Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=khaugsbakk.name Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=khaugsbakk.name header.i=@khaugsbakk.name header.b="YD3q6lAY"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="WpjkOLaD" Received: from compute4.internal (compute4.nyi.internal [10.202.2.44]) by mailfout.nyi.internal (Postfix) with ESMTP id 0CD251380114; Thu, 7 Mar 2024 15:00:19 -0500 (EST) Received: from mailfrontend1 ([10.202.2.162]) by compute4.internal (MEProxy); Thu, 07 Mar 2024 15:00:19 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=khaugsbakk.name; h=cc:cc:content-transfer-encoding:content-type:content-type :date:date:from:from:in-reply-to:in-reply-to:message-id :mime-version:references:reply-to:subject:subject:to:to; s=fm3; t=1709841619; x=1709928019; bh=gcwrHNk4q8xm1qgVnUUJe9drgX4iZOAV 2m5Wxx5cNiw=; b=YD3q6lAYwC1Nrvg4MvIvTIxmxnVt5AesMnVE9tCbp9BzB4lI jC3Xmk8ZDr11+1bL9jyIIbP8inMbnowJg5sAtexujOvEwZpZi8W15/ru53dCC0SU Y+Jjd3k6KC+q6kHjpBPHIxqjrToMpmBD+satG2cE9YcIcWaYTVr/E+nabc1QCNrG o7ixRIlYznLP78wTMSEi2A6jd5STzh8YBxyW4DL79v4ktgkdhYMsZDloE1ZcrUnL 2NwS/9iPVnv8xJxxEs48cRc2cwP+WO2hHjgqbH0hqMjmP7/uFjUhrEnSvFJEGeRf AaV4fujDsuN9iPNh0Hn+gt07neerFV3ctsQr7g== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:content-type:date:date:feedback-id:feedback-id :from:from:in-reply-to:in-reply-to:message-id:mime-version :references:reply-to:subject:subject:to:to:x-me-proxy:x-me-proxy :x-me-sender:x-me-sender:x-sasl-enc; s=fm1; t=1709841619; x= 1709928019; bh=gcwrHNk4q8xm1qgVnUUJe9drgX4iZOAV2m5Wxx5cNiw=; b=W pjkOLaDNajkVDal4BGdOjcxD7eWiuYJXDhk14bWYscDQ8rCBpi/cgZrY32mBabXt Z7M8wM+v3VA9/k0XHPpP+t43FxaXd0fflxhJ1NIAr2lU5R+j/MN+d9rTZ6d875KI 4Va4dX0Xx+h7l20iY2K+AqoGjQ3PDPtxm1X3WUXop4CvhaRA6A8zhaeXiL2zYNcQ yIEoioFqdPHHahlkAX7TM0XrbAtkTLKKDxzW/HRaCq1khTnLf3owjSgGhx8+XI85 7bYD/IOpUPUWOZS17B7ZfNZ4R9ADZ39vLwlANWbdV8JGXFPUj7q3ecRqPIVauWYm wkLKl2GqDuSBXjbl8C0aw== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvledrieefgddufedtucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucenucfjughrpefhvfevufffkffojghfgggtgfesth ekredtredtjeenucfhrhhomhepmfhrihhsthhofhhfvghrucfjrghughhssggrkhhkuceo tghouggvsehkhhgruhhgshgsrghkkhdrnhgrmhgvqeenucggtffrrghtthgvrhhnpeevgf elveeikeegjeeikeeuvefhleeiuddvleegfeekjedtkeevtdetgfffveettdenucevlhhu shhtvghrufhiiigvpedtnecurfgrrhgrmhepmhgrihhlfhhrohhmpegtohguvgeskhhhrg hughhssggrkhhkrdhnrghmvg X-ME-Proxy: Feedback-ID: i2671468f:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Thu, 7 Mar 2024 15:00:18 -0500 (EST) From: Kristoffer Haugsbakk To: git@vger.kernel.org Cc: Kristoffer Haugsbakk Subject: [PATCH 1/3] log-tree: take ownership of pointer Date: Thu, 7 Mar 2024 20:59:35 +0100 Message-ID: <3b12a8cf393b6d8f0877fd7d87173c565d7d5a90.1709841147.git.code@khaugsbakk.name> X-Mailer: git-send-email 2.44.0.64.g52b67adbeb2 In-Reply-To: References: Precedence: bulk X-Mailing-List: git@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Commit-Hash: 3b12a8cf393b6d8f0877fd7d87173c565d7d5a90 The MIME header handling started using string buffers in d50b69b868d (log_write_email_headers: use strbufs, 2018-05-18). The subject buffer is given to `extra_headers` without that variable taking ownership; the commit “punts on that ownership” (in general, not just for this buffer). In an upcoming commit we will first assign `extra_headers` to the owned pointer from another `strbuf`. In turn we need this variable to always contain an owned pointer so that we can free it in the calling function. Signed-off-by: Kristoffer Haugsbakk --- log-tree.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/log-tree.c b/log-tree.c index 337b9334cdb..2eabd19962b 100644 --- a/log-tree.c +++ b/log-tree.c @@ -519,7 +519,7 @@ void log_write_email_headers(struct rev_info *opt, struct commit *commit, extra_headers ? extra_headers : "", mime_boundary_leader, opt->mime_boundary, mime_boundary_leader, opt->mime_boundary); - extra_headers = subject_buffer.buf; + extra_headers = strbuf_detach(&subject_buffer, NULL); if (opt->numbered_files) strbuf_addf(&filename, "%d", opt->nr); From patchwork Thu Mar 7 19:59:36 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Kristoffer Haugsbakk X-Patchwork-Id: 13586208 Received: from fhigh7-smtp.messagingengine.com (fhigh7-smtp.messagingengine.com [103.168.172.158]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 10A7A1350D6 for ; Thu, 7 Mar 2024 20:00:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=103.168.172.158 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1709841623; cv=none; b=amvVdgJfodtm1g5MHpZM/7Qv3eXHZDcUZ2C89Diy9tLxDv2uu+hvTVH8RaAlRewu1zRl43mcXw4gefi/WMmmdJuSV8VhPbIUFnBfX1mX4SIjcRBZU67f/mb+d90Bjm6lNFlLfWF7J1lrlNWOiWX2HUiNPuBHIDEutNMs6oDPtyk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1709841623; c=relaxed/simple; bh=m2AITGLOWEGXGKkO422d1TWDCgqyCKeyE/UvUdyRGag=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=ib6iNw1daPvxVk6MsGqTGKPvRu05fmOU8h6SClQEdVtVnFkYYaR1IlEgoUXY8WG+zBnjqE37OPLd7oA8nWPXDQx/8WKsxuOk6AykT+a+3mjBaYRi3VxLZEaf/jcq7gpj/JdyY//oXTnQGxDyTLbEzSNIx3u3TjdnDUR9jn/Oxt0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=khaugsbakk.name; spf=pass smtp.mailfrom=khaugsbakk.name; dkim=pass (2048-bit key) header.d=khaugsbakk.name header.i=@khaugsbakk.name header.b=CTIE8gl7; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=QUmbutgx; arc=none smtp.client-ip=103.168.172.158 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=khaugsbakk.name Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=khaugsbakk.name Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=khaugsbakk.name header.i=@khaugsbakk.name header.b="CTIE8gl7"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="QUmbutgx" Received: from compute4.internal (compute4.nyi.internal [10.202.2.44]) by mailfhigh.nyi.internal (Postfix) with ESMTP id 3B8D411400E5; Thu, 7 Mar 2024 15:00:20 -0500 (EST) Received: from mailfrontend1 ([10.202.2.162]) by compute4.internal (MEProxy); Thu, 07 Mar 2024 15:00:20 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=khaugsbakk.name; h=cc:cc:content-transfer-encoding:content-type:content-type :date:date:from:from:in-reply-to:in-reply-to:message-id :mime-version:references:reply-to:subject:subject:to:to; s=fm3; t=1709841620; x=1709928020; bh=CLGcmNaoSpwAeM5vJYndjQMIazmvt+E/ bN85QX5IXDg=; b=CTIE8gl7Mjq9H7+q0B//cRy8yyM9QUpg8vM00uuQeCw49K+4 dUts9LUiCjoMYcAwPuZv1H/Pc08vH8m8IxUaObOpUJY55H9f+fEsrk2PxU2ZOQGs GJQCOvw6gw+vE1XSDam8N3nJAdMaXqd3VX+zsL/O8wsWSP3mTOj66vexbs4Ag+qs eY1WQncIvSo1XoUN8ApHbDa6A2bOTFEtUf7fXh04ayHIzL24umxWMHUIT/7joe8m 6jVCx50+I9ZWRMe6h1F93on2eDpgfG6wOW4CVPUeL48QD4kcaTym6YblouREf3/Z 53OWUBQSTGXZqzhoy7AYzfxTgBKApZJ4AN87cQ== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:content-type:date:date:feedback-id:feedback-id :from:from:in-reply-to:in-reply-to:message-id:mime-version :references:reply-to:subject:subject:to:to:x-me-proxy:x-me-proxy :x-me-sender:x-me-sender:x-sasl-enc; s=fm1; t=1709841620; x= 1709928020; bh=CLGcmNaoSpwAeM5vJYndjQMIazmvt+E/bN85QX5IXDg=; b=Q UmbutgxeWX4u755N48x7DFY6z3rLvNICuNpq/LjhyJs5l3fES8EOq9grYZGVmvoo HYtzfHtAtxlH/siunFSJfSPGKO705YPm7X0XMiV56L3bRmUHl6F21nBYUpMlwbgO lutEuGqeMmtwoz+d6USdB7uRiGUM2mK/7Q4+8c/Er/E02EjnjRUVwcP800ykDymf tAlZWwIIsdfGCpP4vF5sjfomxkd1Aw96O5XD84fdo/Fidp6YFHPCX2I6+SJlG+sb uPp7zMUhrHd1F4EMhpTeB8ANWKZcymROW3tESr5yMH649SMsOoFmZ7uXxQECEIR3 f5mKV8eM/DLFUhPXZ4+IQ== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvledrieefgddufedtucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucenucfjughrpefhvfevufffkffojghfgggtgfesth ekredtredtjeenucfhrhhomhepmfhrihhsthhofhhfvghrucfjrghughhssggrkhhkuceo tghouggvsehkhhgruhhgshgsrghkkhdrnhgrmhgvqeenucggtffrrghtthgvrhhnpeevgf elveeikeegjeeikeeuvefhleeiuddvleegfeekjedtkeevtdetgfffveettdenucevlhhu shhtvghrufhiiigvpedtnecurfgrrhgrmhepmhgrihhlfhhrohhmpegtohguvgeskhhhrg hughhssggrkhhkrdhnrghmvg X-ME-Proxy: Feedback-ID: i2671468f:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Thu, 7 Mar 2024 15:00:19 -0500 (EST) From: Kristoffer Haugsbakk To: git@vger.kernel.org Cc: Kristoffer Haugsbakk Subject: [PATCH 2/3] format-patch: teach `--header-cmd` Date: Thu, 7 Mar 2024 20:59:36 +0100 Message-ID: X-Mailer: git-send-email 2.44.0.64.g52b67adbeb2 In-Reply-To: References: Precedence: bulk X-Mailing-List: git@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Commit-Hash: f405a0140b5655bc66a0a7a603517a421d7669cf Teach git-format-patch(1) `--header-cmd` (with negation) and the accompanying config variable `format.headerCmd` which allows the user to add extra headers per-patch. format-patch knows `--add-header`. However, that seems most useful for series-wide headers; you cannot really control what the header is like per patch or specifically for the cover letter. To that end, teach format-patch a new option which runs a command that has access to the hash of the current commit (if it is a code patch) and the patch count which is used for the patch files that this command outputs. Also include an environment variable which tells the version of this API so that the command can detect and error out in case the API changes. This is inspired by `--header-cmd` of git-send-email(1). § Discussion The command can use the provided commit hash to provide relevant information in the header. For example, the command could output a header for the current commit as well as the previously-published commits: X-Commit-Hash: 97b53c04894578b23d0c650f69885f734699afc7 X-Previous-Commits: 4ad5d4190649dcb5f26c73a6f15ab731891b9dfd d275d1d179b90592ddd7b5da2ae4573b3f7a37b7 402b7937951073466bf4527caffd38175391c7da Now interested parties can use this information to track where the patches come from. This information could of course be given between the three-dash/three-hyphen line and the patch proper. However, the project might prefer to use this part for extra patch information written by the author and leave the above information for tooling; this way the extra information does not need to disturb the reader. Signed-off-by: Kristoffer Haugsbakk --- Notes (series): Documentation/config/format.txt: • I get the impression that `_` is the convention for placeholders now: `__` Documentation/config/format.txt | 5 ++++ Documentation/git-format-patch.txt | 26 ++++++++++++++++++ builtin/log.c | 43 ++++++++++++++++++++++++++++++ log-tree.c | 16 ++++++++++- revision.h | 2 ++ t/t4014-format-patch.sh | 42 +++++++++++++++++++++++++++++ 6 files changed, 133 insertions(+), 1 deletion(-) diff --git a/Documentation/config/format.txt b/Documentation/config/format.txt index 7410e930e53..c184b865824 100644 --- a/Documentation/config/format.txt +++ b/Documentation/config/format.txt @@ -31,6 +31,11 @@ format.headers:: Additional email headers to include in a patch to be submitted by mail. See linkgit:git-format-patch[1]. +format.headerCmd:: + Command to run for each patch that should output RFC 2822 email + headers. Has access to some information per patch via + environment variables. See linkgit:git-format-patch[1]. + format.to:: format.cc:: Additional recipients to include in a patch to be submitted diff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt index 728bb3821c1..41c344902e9 100644 --- a/Documentation/git-format-patch.txt +++ b/Documentation/git-format-patch.txt @@ -303,6 +303,32 @@ feeding the result to `git send-email`. `Cc:`, and custom) headers added so far from config or command line. +--[no-]header-cmd=:: + Run __ for each patch. __ should output valid RFC 2822 + email headers. This can also be configured with + the configuration variable `format.headerCmd`. Can be turned off + with `--no-header-cmd`. This works independently of + `--[no-]add-header`. ++ +__ has access to these environment variables: ++ + GIT_FP_HEADER_CMD_VERSION ++ +The version of this API. Currently `1`. __ may return exit code +`2` in order to signal that it does not support the given version. ++ + GIT_FP_HEADER_CMD_HASH ++ +The hash of the commit corresponding to the current patch. Not set if +the current patch is the cover letter. ++ + GIT_FP_HEADER_CMD_COUNT ++ +The current patch count. Increments for each patch. ++ +`git format-patch` will error out if __ returns a non-zero exit +code. + --[no-]cover-letter:: In addition to the patches, generate a cover letter file containing the branch description, shortlog and the overall diffstat. You can diff --git a/builtin/log.c b/builtin/log.c index db1808d7c13..eecbcdf1d6d 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -43,10 +43,13 @@ #include "tmp-objdir.h" #include "tree.h" #include "write-or-die.h" +#include "run-command.h" #define MAIL_DEFAULT_WRAP 72 #define COVER_FROM_AUTO_MAX_SUBJECT_LEN 100 #define FORMAT_PATCH_NAME_MAX_DEFAULT 64 +#define HC_VERSION "1" +#define HC_NOT_SUPPORTED 2 /* Set a default date-time format for git log ("log.date" config variable) */ static const char *default_date_mode = NULL; @@ -902,6 +905,7 @@ static int auto_number = 1; static char *default_attach = NULL; +static const char *header_cmd = NULL; static struct string_list extra_hdr = STRING_LIST_INIT_NODUP; static struct string_list extra_to = STRING_LIST_INIT_NODUP; static struct string_list extra_cc = STRING_LIST_INIT_NODUP; @@ -1100,6 +1104,8 @@ static int git_format_config(const char *var, const char *value, format_no_prefix = 1; return 0; } + if (!strcmp(var, "format.headercmd")) + return git_config_string(&header_cmd, var, value); /* * ignore some porcelain config which would otherwise be parsed by @@ -1419,6 +1425,7 @@ static void make_cover_letter(struct rev_info *rev, int use_separate_file, show_range_diff(rev->rdiff1, rev->rdiff2, &range_diff_opts); strvec_clear(&other_arg); } + free((char *)pp.after_subject); } static char *clean_message_id(const char *msg_id) @@ -1865,6 +1872,35 @@ static void infer_range_diff_ranges(struct strbuf *r1, } } +/* Returns an owned pointer */ +static char *header_cmd_output(struct rev_info *rev, const struct commit *cmit) +{ + struct child_process header_cmd_proc = CHILD_PROCESS_INIT; + struct strbuf output = STRBUF_INIT; + int res; + + strvec_pushl(&header_cmd_proc.args, header_cmd, NULL); + if (cmit) + strvec_pushf(&header_cmd_proc.env, "GIT_FP_HEADER_CMD_HASH=%s", + oid_to_hex(&cmit->object.oid)); + strvec_pushl(&header_cmd_proc.env, + "GIT_FP_HEADER_CMD_VERSION=" HC_VERSION, NULL); + strvec_pushf(&header_cmd_proc.env, "GIT_FP_HEADER_CMD_COUNT=%" PRIuMAX, + (uintmax_t)rev->nr); + res = capture_command(&header_cmd_proc, &output, 0); + if (res) { + if (res == HC_NOT_SUPPORTED) + die(_("header-cmd %s: returned exit " + "code %d; the command does not support " + "version " HC_VERSION), + header_cmd, HC_NOT_SUPPORTED); + else + die(_("header-cmd %s: failed with exit code %d"), + header_cmd, res); + } + return strbuf_detach(&output, NULL); +} + int cmd_format_patch(int argc, const char **argv, const char *prefix) { struct commit *commit; @@ -1955,6 +1991,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) OPT_GROUP(N_("Messaging")), OPT_CALLBACK(0, "add-header", NULL, N_("header"), N_("add email header"), header_callback), + OPT_STRING(0, "header-cmd", &header_cmd, N_("email"), N_("command that will be run to generate headers")), OPT_STRING_LIST(0, "to", &extra_to, N_("email"), N_("add To: header")), OPT_STRING_LIST(0, "cc", &extra_cc, N_("email"), N_("add Cc: header")), OPT_CALLBACK_F(0, "from", &from, N_("ident"), @@ -2321,6 +2358,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) if (cover_letter) { if (thread) gen_message_id(&rev, "cover"); + if (header_cmd) + rev.pe_headers = header_cmd_output(&rev, NULL); make_cover_letter(&rev, !!output_directory, origin, nr, list, description_file, branch_name, quiet); print_bases(&bases, rev.diffopt.file); @@ -2330,6 +2369,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) /* interdiff/range-diff in cover-letter; omit from patches */ rev.idiff_oid1 = NULL; rev.rdiff1 = NULL; + free((char *)rev.pe_headers); } rev.add_signoff = do_signoff; @@ -2376,6 +2416,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) gen_message_id(&rev, oid_to_hex(&commit->object.oid)); } + if (header_cmd) + rev.pe_headers = header_cmd_output(&rev, commit); if (output_directory && open_next_file(rev.numbered_files ? NULL : commit, NULL, &rev, quiet)) die(_("failed to create output files")); @@ -2402,6 +2444,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) } if (output_directory) fclose(rev.diffopt.file); + free((char *)rev.pe_headers); } stop_progress(&progress); free(list); diff --git a/log-tree.c b/log-tree.c index 2eabd19962b..3ca383d099f 100644 --- a/log-tree.c +++ b/log-tree.c @@ -469,12 +469,24 @@ void fmt_output_email_subject(struct strbuf *sb, struct rev_info *opt) } } +static char *extra_and_pe_headers(const char *extra_headers, const char *pe_headers) { + struct strbuf all_headers = STRBUF_INIT; + + if (extra_headers) + strbuf_addstr(&all_headers, extra_headers); + if (pe_headers) { + strbuf_addstr(&all_headers, pe_headers); + } + return strbuf_detach(&all_headers, NULL); +} + void log_write_email_headers(struct rev_info *opt, struct commit *commit, const char **extra_headers_p, int *need_8bit_cte_p, int maybe_multipart) { - const char *extra_headers = opt->extra_headers; + const char *extra_headers = + extra_and_pe_headers(opt->extra_headers, opt->pe_headers); const char *name = oid_to_hex(opt->zero_commit ? null_oid() : &commit->object.oid); @@ -519,6 +531,7 @@ void log_write_email_headers(struct rev_info *opt, struct commit *commit, extra_headers ? extra_headers : "", mime_boundary_leader, opt->mime_boundary, mime_boundary_leader, opt->mime_boundary); + free((char *)extra_headers); extra_headers = strbuf_detach(&subject_buffer, NULL); if (opt->numbered_files) @@ -857,6 +870,7 @@ void show_log(struct rev_info *opt) strbuf_release(&msgbuf); free(ctx.notes_message); + free((char *)ctx.after_subject); if (cmit_fmt_is_mail(ctx.fmt) && opt->idiff_oid1) { struct diff_queue_struct dq; diff --git a/revision.h b/revision.h index 94c43138bc3..eb36bdea36e 100644 --- a/revision.h +++ b/revision.h @@ -291,6 +291,8 @@ struct rev_info { struct string_list *ref_message_ids; int add_signoff; const char *extra_headers; + /* per-email headers */ + const char *pe_headers; const char *log_reencode; const char *subject_prefix; int patch_name_max; diff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh index e37a1411ee2..dfda21d4b2b 100755 --- a/t/t4014-format-patch.sh +++ b/t/t4014-format-patch.sh @@ -238,6 +238,48 @@ test_expect_failure 'configuration To: header (rfc2047)' ' grep "^To: =?UTF-8?q?R=20=C3=84=20Cipient?= \$" hdrs9 ' +test_expect_success '--header-cmd' ' + write_script cmd <<-\EOF && + printf "X-S: $GIT_FP_HEADER_CMD_HASH\n" + printf "X-V: $GIT_FP_HEADER_CMD_VERSION\n" + printf "X-C: $GIT_FP_HEADER_CMD_COUNT\n" + EOF + expect_sha1=$(git rev-parse side) && + git format-patch --header-cmd=./cmd --stdout main..side >patch && + grep "^X-S: $expect_sha1" patch && + grep "^X-V: 1" patch && + grep "^X-C: 3" patch +' + +test_expect_success '--header-cmd with no output works' ' + write_script cmd <<-\EOF && + exit 0 + EOF + git format-patch --header-cmd=./cmd --stdout main..side +' + +test_expect_success '--header-cmd reports failed command' ' + write_script cmd <<-\EOF && + exit 1 + EOF + cat > expect <<-\EOF && + fatal: header-cmd ./cmd: failed with exit code 1 + EOF + test_must_fail git format-patch --header-cmd=./cmd --stdout main..side >actual 2>&1 && + test_cmp expect actual +' + +test_expect_success '--header-cmd reports exit code 2' ' + write_script cmd <<-\EOF && + exit 2 + EOF + cat > expect <<-\EOF && + fatal: header-cmd ./cmd: returned exit code 2; the command does not support version 1 + EOF + test_must_fail git format-patch --header-cmd=./cmd --stdout main..side >actual 2>&1 && + test_cmp expect actual +' + # check_patch : Verify that looks like a half-sane # patch email to avoid a false positive with !grep check_patch () { From patchwork Thu Mar 7 19:59:37 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kristoffer Haugsbakk X-Patchwork-Id: 13586209 Received: from out3-smtp.messagingengine.com (out3-smtp.messagingengine.com [66.111.4.27]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 62DCF138494 for ; Thu, 7 Mar 2024 20:00:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=66.111.4.27 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1709841624; cv=none; b=WRKj8m/pC/2wUcPjZE96FqxdXhoozO6gzP2rLZqQmb4x8h/0xONZ1ZF1a+O0nWBCl2DQhd/dkBCGL6uOEf0AX+b4YGVddnS4xwXeOA1Bda/r5hjuE6q0cIwEMLdyIdYPILE+5qkc7/1WPiRy1lI/DOR4z0KXeuEmGD+CxyaW8uE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1709841624; c=relaxed/simple; bh=qoEg2HQT+5EEpXwuHIsbVEyNlIXVjA7VRt6zrmgMomM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ZQK434HHaIJpaNxJ01l1MeoflnfuUe6vCfUYqcQwMrGECgqEZaf7zZA/1CpWn2ZuzNwbCp9WLJsCdLzpmxl+2JRyxgrp3WNFSvDY5113LLwfzh0wu8ScKcoOUc0+77kvDYiAzph6szl9E8PX25wLO9hAfuxC2NtMni9cnATl+Fg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=khaugsbakk.name; spf=pass smtp.mailfrom=khaugsbakk.name; dkim=pass (2048-bit key) header.d=khaugsbakk.name header.i=@khaugsbakk.name header.b=jMfmdbMX; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=rOiNu+qw; arc=none smtp.client-ip=66.111.4.27 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=khaugsbakk.name Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=khaugsbakk.name Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=khaugsbakk.name header.i=@khaugsbakk.name header.b="jMfmdbMX"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="rOiNu+qw" Received: from compute7.internal (compute7.nyi.internal [10.202.2.48]) by mailout.nyi.internal (Postfix) with ESMTP id 7C3515C0076; Thu, 7 Mar 2024 15:00:21 -0500 (EST) Received: from mailfrontend1 ([10.202.2.162]) by compute7.internal (MEProxy); Thu, 07 Mar 2024 15:00:21 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=khaugsbakk.name; h=cc:cc:content-transfer-encoding:content-type:date:date:from :from:in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to; s=fm3; t=1709841621; x= 1709928021; bh=Ub8fbcl6KS2OuYDodgAgrdZoJj66Y276f7ABDV+08Vs=; b=j MfmdbMXONFze2PCBDJ4GvfeW4KXdW90ArKADXvZVIBVZS++evShdG3Bj4spW+Unx NGjbypFISDChK3o/gAccNjNAmnXRSboh9PQTbNzGNVNm/uD3VdW/d/hV/7t4dD8t 0jNv0Wo45R4eAsjdlUxGMkYSgHQuJl0EpU3hw2AGolrF2kNLbQTyxLYrk//pO5Gv aPyKKvgJQFSGAxwXUMScN5nl0y1FzcI3BdlNZhleKtW6sVE9ssMy0JekF1+62h8G icaVm/G8D2aFva8mmpiV0Jmp0K0O5E/wpXFPfU5tqOG6bRVXeMQlTQ5bxpIGq2xq tdN1LYmVMtxN69tFik3wA== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to:x-me-proxy:x-me-proxy :x-me-sender:x-me-sender:x-sasl-enc; s=fm1; t=1709841621; x= 1709928021; bh=Ub8fbcl6KS2OuYDodgAgrdZoJj66Y276f7ABDV+08Vs=; b=r OiNu+qwifuxy0g8HyqO2t4WGjZsP1dcki5/UUm/cNKzvLdyB/xmxHXSlU2Vu8pWs VGHhdM7GkT4gtQ2p7ml46ckpt2dkLQFb7OpLa2d+2UiNmdQ66yxcjsGeVb/LTGYz B2bIVZ9aIwqof5DYTj4tyDs7oqaF+aBwILaqE87OTcoruXK8BsgRLpGjFZ/fU10i UfqPJIKfoRir4gFYBZE9iEtKVt+u9bcKSg1xPLteBhmvKyzzgJAu7rHaOOm5C3/f MR9J7CGCLMpYUWHTPk5iUy9XV1/9NppmyDmg2qD1IzMR8lr6ipZ/eDsR/YBEIizR eCwF3xzJkN60t8jh/nmTw== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvledrieefgddufeduucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucenucfjughrpefhvfevufffkffojghfggfgsedtke ertdertddtnecuhfhrohhmpefmrhhishhtohhffhgvrhcujfgruhhgshgsrghkkhcuoegt ohguvgeskhhhrghughhssggrkhhkrdhnrghmvgeqnecuggftrfgrthhtvghrnhepteduie ehgedutdfgudevkefhveduieeiteejhfffteeitdegjeeihedthfejgfetnecuvehluhhs thgvrhfuihiivgeptdenucfrrghrrghmpehmrghilhhfrhhomheptghouggvsehkhhgruh hgshgsrghkkhdrnhgrmhgv X-ME-Proxy: Feedback-ID: i2671468f:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Thu, 7 Mar 2024 15:00:20 -0500 (EST) From: Kristoffer Haugsbakk To: git@vger.kernel.org Cc: Kristoffer Haugsbakk Subject: [PATCH 3/3] format-patch: check if header output looks valid Date: Thu, 7 Mar 2024 20:59:37 +0100 Message-ID: <0e8409227e4e8eb73bac7dff97e3f53584b4e283.1709841147.git.code@khaugsbakk.name> X-Mailer: git-send-email 2.44.0.64.g52b67adbeb2 In-Reply-To: References: Precedence: bulk X-Mailing-List: git@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Commit-Hash: 0e8409227e4e8eb73bac7dff97e3f53584b4e283 Implement a function based on `mailinfo.c:is_mail`. Signed-off-by: Kristoffer Haugsbakk --- Notes (series): Isolating this for review as its own commit so that I can point out the provenance. May well be squashed into the main patch eventually. builtin/log.c | 33 +++++++++++++++++++++++++++++++++ t/t4014-format-patch.sh | 13 +++++++++++++ 2 files changed, 46 insertions(+) diff --git a/builtin/log.c b/builtin/log.c index eecbcdf1d6d..27e1a66dd03 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -1872,6 +1872,35 @@ static void infer_range_diff_ranges(struct strbuf *r1, } } +static int is_mail(struct strbuf *sb) +{ + const char *header_regex = "^[!-9;-~]+:"; + regex_t regex; + int ret = 1, i; + struct string_list list = STRING_LIST_INIT_DUP; + + if (regcomp(®ex, header_regex, REG_NOSUB | REG_EXTENDED)) + die("invalid pattern: %s", header_regex); + string_list_split(&list, sb->buf, '\n', -1); + for (i = 0; i < list.nr; i++) { + /* End of header */ + if (!*list.items[i].string && i == (list.nr - 1)) + break; + /* Ignore indented folded lines */ + if (*list.items[i].string == '\t' || + *list.items[i].string == ' ') + continue; + /* It's a header if it matches header_regex */ + if (regexec(®ex, list.items[i].string, 0, NULL, 0)) { + ret = 0; + break; + } + } + string_list_clear(&list, 1); + regfree(®ex); + return ret; +} + /* Returns an owned pointer */ static char *header_cmd_output(struct rev_info *rev, const struct commit *cmit) { @@ -1898,6 +1927,10 @@ static char *header_cmd_output(struct rev_info *rev, const struct commit *cmit) die(_("header-cmd %s: failed with exit code %d"), header_cmd, res); } + if (!is_mail(&output)) + die(_("header-cmd %s: returned output which was " + "not recognized as valid RFC 2822 headers"), + header_cmd); return strbuf_detach(&output, NULL); } diff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh index dfda21d4b2b..98e0eb706e6 100755 --- a/t/t4014-format-patch.sh +++ b/t/t4014-format-patch.sh @@ -258,6 +258,19 @@ test_expect_success '--header-cmd with no output works' ' git format-patch --header-cmd=./cmd --stdout main..side ' +test_expect_success '--header-cmd without headers-like output fails' ' + write_script cmd <<-\EOF && + printf "X-S: $GIT_FP_HEADER_CMD_HASH\n" + printf "\n" + printf "X-C: $GIT_FP_HEADER_CMD_COUNT\n" + EOF + cat > expect <<-\EOF && + fatal: header-cmd ./cmd: returned output which was not recognized as valid RFC 2822 headers + EOF + test_must_fail git format-patch --header-cmd=./cmd --stdout main..side >actual 2>&1 && + test_cmp expect actual +' + test_expect_success '--header-cmd reports failed command' ' write_script cmd <<-\EOF && exit 1