{"thread":{"id":"59067","subject":"[PATCH v5 0/2] send-email: expose header information to git-send-email's sendemail-validate hook","startedAt":"2023-01-10T21:16:27Z","lastAt":"2023-01-17T23:05:45Z","messageCount":16,"participants":["Strawbridge, Michael","Junio C Hamano","Luben Tuikov","Ævar Arnfjörð Bjarmason"],"isPatch":true,"patchVersion":5,"patchTotal":2},"messages":[{"id":"470080","messageId":"20230110211452.2568535-1-michael.strawbridge@amd.com","threadId":"59067","inReplyTo":null,"subject":"[PATCH v5 0/2] send-email: expose header information to git-send-email's sendemail-validate hook","fromName":"Strawbridge, Michael","fromEmail":"michael.strawbridge@amd.com","sentAt":"2023-01-10T21:16:19Z","receivedAt":"2023-01-10T21:16:27Z","isPatch":true,"sender":{"key":"michael.strawbridge@amd.com","avatar":null},"body":"Hi Junio,\n\nI very much appreciate the feedback and believe I have changed things to match.\n\nTo answer your earlier question, the hook doesn't need to support multiple header capitalizations (ie. only Cc is passed). However, it does need to understand that lines beginning with whitespace belong to the previous header.  The header information follows the same format as the confirmation given at the end of send-email.\n\nMichael Strawbridge (2):\n  send-email: refactor header generation functions\n  send-email: expose header information to git-send-email's\n    sendemail-validate hook\n\n Documentation/githooks.txt | 17 ++++++--\n git-send-email.perl        | 80 +++++++++++++++++++++++++-------------\n t/t9001-send-email.sh      | 29 +++++++++++++-\n 3 files changed, 92 insertions(+), 34 deletions(-)\n\n-- \n2.34.1\n"},{"id":"470081","messageId":"20230110211452.2568535-2-michael.strawbridge@amd.com","threadId":"59067","inReplyTo":"20230110211452.2568535-1-michael.strawbridge@amd.com","subject":"[PATCH v5 1/2] send-email: refactor header generation functions","fromName":"Strawbridge, Michael","fromEmail":"michael.strawbridge@amd.com","sentAt":"2023-01-10T21:16:26Z","receivedAt":"2023-01-10T21:16:33Z","isPatch":true,"sender":{"key":"michael.strawbridge@amd.com","avatar":null},"body":"Split process_file and send_message into easier to use functions.\nMaking SMTP header information more widely available.\n\nCc: Luben Tuikov <luben.tuikov@amd.com>\nCc: Junio C Hamano <gitster@pobox.com>\nSigned-off-by: Michael Strawbridge <michael.strawbridge@amd.com>\n---\n git-send-email.perl | 49 ++++++++++++++++++++++++++++-----------------\n 1 file changed, 31 insertions(+), 18 deletions(-)\n\ndiff --git a/git-send-email.perl b/git-send-email.perl\nindex 5861e99a6e..810dd1f1ce 100755\n--- a/git-send-email.perl\n+++ b/git-send-email.perl\n@@ -1495,16 +1495,7 @@ sub file_name_is_absolute {\n \treturn File::Spec::Functions::file_name_is_absolute($path);\n }\n \n-# Prepares the email, then asks the user what to do.\n-#\n-# If the user chooses to send the email, it's sent and 1 is returned.\n-# If the user chooses not to send the email, 0 is returned.\n-# If the user decides they want to make further edits, -1 is returned and the\n-# caller is expected to call send_message again after the edits are performed.\n-#\n-# If an error occurs sending the email, this just dies.\n-\n-sub send_message {\n+sub gen_header {\n \tmy @recipients = unique_email_list(@to);\n \t@cc = (grep { my $cc = extract_valid_address_or_die($_);\n \t\t      not grep { $cc eq $_ || $_ =~ /<\\Q${cc}\\E>$/ } @recipients\n@@ -1546,6 +1537,22 @@ sub send_message {\n \tif (@xh) {\n \t\t$header .= join(\"\\n\", @xh) . \"\\n\";\n \t}\n+\tmy $recipients_ref = \\@recipients;\n+\treturn ($recipients_ref, $to, $date, $gitversion, $cc, $ccline, $header);\n+}\n+\n+# Prepares the email, then asks the user what to do.\n+#\n+# If the user chooses to send the email, it's sent and 1 is returned.\n+# If the user chooses not to send the email, 0 is returned.\n+# If the user decides they want to make further edits, -1 is returned and the\n+# caller is expected to call send_message again after the edits are performed.\n+#\n+# If an error occurs sending the email, this just dies.\n+\n+sub send_message {\n+\tmy ($recipients_ref, $to, $date, $gitversion, $cc, $ccline, $header) = gen_header();\n+\tmy @recipients = @$recipients_ref;\n \n \tmy @sendmail_parameters = ('-i', @recipients);\n \tmy $raw_from = $sender;\n@@ -1735,11 +1742,8 @@ sub send_message {\n $references = $initial_in_reply_to || '';\n $message_num = 0;\n \n-# Prepares the email, prompts the user, sends it out\n-# Returns 0 if an edit was done and the function should be called again, or 1\n-# otherwise.\n-sub process_file {\n-\tmy ($t) = @_;\n+sub pre_process_file {\n+\tmy ($t, $quiet) = @_;\n \n \topen my $fh, \"<\", $t or die sprintf(__(\"can't open file %s\"), $t);\n \n@@ -1893,9 +1897,9 @@ sub process_file {\n \t}\n \tclose $fh;\n \n-\tpush @to, recipients_cmd(\"to-cmd\", \"to\", $to_cmd, $t)\n+\tpush @to, recipients_cmd(\"to-cmd\", \"to\", $to_cmd, $t, $quiet)\n \t\tif defined $to_cmd;\n-\tpush @cc, recipients_cmd(\"cc-cmd\", \"cc\", $cc_cmd, $t)\n+\tpush @cc, recipients_cmd(\"cc-cmd\", \"cc\", $cc_cmd, $t, $quiet)\n \t\tif defined $cc_cmd && !$suppress_cc{'cccmd'};\n \n \tif ($broken_encoding{$t} && !$has_content_type) {\n@@ -1954,6 +1958,15 @@ sub process_file {\n \t\t\t@initial_to = @to;\n \t\t}\n \t}\n+}\n+\n+# Prepares the email, prompts the user, sends it out\n+# Returns 0 if an edit was done and the function should be called again, or 1\n+# otherwise.\n+sub process_file {\n+\tmy ($t) = @_;\n+\n+        pre_process_file($t, $quiet);\n \n \tmy $message_was_sent = send_message();\n \tif ($message_was_sent == -1) {\n@@ -2002,7 +2015,7 @@ sub process_file {\n # Execute a command (e.g. $to_cmd) to get a list of email addresses\n # and return a results array\n sub recipients_cmd {\n-\tmy ($prefix, $what, $cmd, $file) = @_;\n+\tmy ($prefix, $what, $cmd, $file, $quiet) = @_;\n \n \tmy @addresses = ();\n \topen my $fh, \"-|\", \"$cmd \\Q$file\\E\"\n-- \n2.34.1\n"},{"id":"470082","messageId":"20230110211452.2568535-3-michael.strawbridge@amd.com","threadId":"59067","inReplyTo":"20230110211452.2568535-1-michael.strawbridge@amd.com","subject":"[PATCH v5 2/2] send-email: expose header information to git-send-email's sendemail-validate hook","fromName":"Strawbridge, Michael","fromEmail":"michael.strawbridge@amd.com","sentAt":"2023-01-10T21:16:28Z","receivedAt":"2023-01-10T21:16:36Z","isPatch":true,"sender":{"key":"michael.strawbridge@amd.com","avatar":null},"body":"To allow further flexibility in the git hook, the SMTP header\ninformation of the email that git-send-email intends to send, is now\npassed as a 2nd argument to the sendemail-validate hook.\n\nAs an example, this can be useful for acting upon keywords in the\nsubject or specific email addresses.\n\nCc: Luben Tuikov <luben.tuikov@amd.com>\nCc: Junio C Hamano <gitster@pobox.com>\nSigned-off-by: Michael Strawbridge <michael.strawbridge@amd.com>\n---\n Documentation/githooks.txt | 17 +++++++++++++----\n git-send-email.perl        | 31 +++++++++++++++++++++----------\n t/t9001-send-email.sh      | 29 +++++++++++++++++++++++++++--\n 3 files changed, 61 insertions(+), 16 deletions(-)\n\ndiff --git a/Documentation/githooks.txt b/Documentation/githooks.txt\nindex a16e62bc8c..2b5c6640cc 100644\n--- a/Documentation/githooks.txt\n+++ b/Documentation/githooks.txt\n@@ -583,10 +583,19 @@ processed by rebase.\n sendemail-validate\n ~~~~~~~~~~~~~~~~~~\n \n-This hook is invoked by linkgit:git-send-email[1].  It takes a single parameter,\n-the name of the file that holds the e-mail to be sent.  Exiting with a\n-non-zero status causes `git send-email` to abort before sending any\n-e-mails.\n+This hook is invoked by linkgit:git-send-email[1].\n+\n+It takes these command line arguments:\n+1. the name of the file that holds the e-mail to be sent.\n+2. the name of the file that holds the SMTP headers to be used.\n+\n+The hook doesn't need to support multiple header names (for example only Cc\n+is passed). However, it does need to understand that lines beginning with\n+whitespace belong to the previous header.  The header information follows\n+the same format as the confirmation given at the end of send-email.\n+\n+Exiting with a non-zero status causes `git send-email` to abort\n+before sending any e-mails.\n \n fsmonitor-watchman\n ~~~~~~~~~~~~~~~~~~\ndiff --git a/git-send-email.perl b/git-send-email.perl\nindex 810dd1f1ce..b2adca515e 100755\n--- a/git-send-email.perl\n+++ b/git-send-email.perl\n@@ -787,14 +787,6 @@ sub is_format_patch_arg {\n \n @files = handle_backup_files(@files);\n \n-if ($validate) {\n-\tforeach my $f (@files) {\n-\t\tunless (-p $f) {\n-\t\t\tvalidate_patch($f, $target_xfer_encoding);\n-\t\t}\n-\t}\n-}\n-\n if (@files) {\n \tunless ($quiet) {\n \t\tprint $_,\"\\n\" for (@files);\n@@ -1738,6 +1730,16 @@ sub send_message {\n \treturn 1;\n }\n \n+if ($validate) {\n+\tforeach my $f (@files) {\n+\t\tunless (-p $f) {\n+\t\t        pre_process_file($f, 1);\n+\n+\t\t\tvalidate_patch($f, $target_xfer_encoding);\n+\t\t}\n+\t}\n+}\n+\n $in_reply_to = $initial_in_reply_to;\n $references = $initial_in_reply_to || '';\n $message_num = 0;\n@@ -2101,11 +2103,20 @@ sub validate_patch {\n \t\t\tchdir($repo->wc_path() or $repo->repo_path())\n \t\t\t\tor die(\"chdir: $!\");\n \t\t\tlocal $ENV{\"GIT_DIR\"} = $repo->repo_path();\n+\n+\t\t\tmy ($recipients_ref, $to, $date, $gitversion, $cc, $ccline, $header) = gen_header();\n+\n+\t\t\trequire File::Temp;\n+\t\t\tmy ($header_filehandle, $header_filename) = File::Temp::tempfile(\n+                            \".gitsendemail.header.XXXXXX\", DIR => $repo->repo_path());\n+\t\t\tprint $header_filehandle $header;\n+\n \t\t\tmy @cmd = (\"git\", \"hook\", \"run\", \"--ignore-missing\",\n \t\t\t\t    $hook_name, \"--\");\n-\t\t\tmy @cmd_msg = (@cmd, \"<patch>\");\n-\t\t\tmy @cmd_run = (@cmd, $target);\n+\t\t\tmy @cmd_msg = (@cmd, \"<patch>\", \"<header>\");\n+\t\t\tmy @cmd_run = (@cmd, $target, $header_filename);\n \t\t\t$hook_error = system_or_msg(\\@cmd_run, undef, \"@cmd_msg\");\n+\t\t\tunlink($header_filehandle);\n \t\t\tchdir($cwd_save) or die(\"chdir: $!\");\n \t\t}\n \t\tif ($hook_error) {\ndiff --git a/t/t9001-send-email.sh b/t/t9001-send-email.sh\nindex 1130ef21b3..f02b1eba16 100755\n--- a/t/t9001-send-email.sh\n+++ b/t/t9001-send-email.sh\n@@ -540,7 +540,7 @@ test_expect_success $PREREQ \"--validate respects relative core.hooksPath path\" '\n \ttest_path_is_file my-hooks.ran &&\n \tcat >expect <<-EOF &&\n \tfatal: longline.patch: rejected by sendemail-validate hook\n-\tfatal: command '\"'\"'git hook run --ignore-missing sendemail-validate -- <patch>'\"'\"' died with exit code 1\n+\tfatal: command '\"'\"'git hook run --ignore-missing sendemail-validate -- <patch> <header>'\"'\"' died with exit code 1\n \twarning: no patches were sent\n \tEOF\n \ttest_cmp expect actual\n@@ -559,7 +559,32 @@ test_expect_success $PREREQ \"--validate respects absolute core.hooksPath path\" '\n \ttest_path_is_file my-hooks.ran &&\n \tcat >expect <<-EOF &&\n \tfatal: longline.patch: rejected by sendemail-validate hook\n-\tfatal: command '\"'\"'git hook run --ignore-missing sendemail-validate -- <patch>'\"'\"' died with exit code 1\n+\tfatal: command '\"'\"'git hook run --ignore-missing sendemail-validate -- <patch> <header>'\"'\"' died with exit code 1\n+\twarning: no patches were sent\n+\tEOF\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success $PREREQ \"--validate hook supports header argument\" '\n+\ttest_when_finished \"rm my-hooks.ran\" &&\n+\twrite_script my-hooks/sendemail-validate <<-\\EOF &&\n+\tfilesize=$(stat -c%s \"$2\")\n+\tif [ \"$filesize\" != \"0\" ]; then\n+\t>my-hooks.ran\n+\tfi\n+\texit 1\n+\tEOF\n+\ttest_config core.hooksPath \"my-hooks\" &&\n+\ttest_must_fail git send-email \\\n+\t\t--from=\"Example <nobody@example.com>\" \\\n+\t\t--to=nobody@example.com \\\n+\t\t--smtp-server=\"$(pwd)/fake.sendmail\" \\\n+\t\t--validate \\\n+\t\tlongline.patch 2>actual &&\n+\ttest_path_is_file my-hooks.ran &&\n+\tcat >expect <<-EOF &&\n+\tfatal: longline.patch: rejected by sendemail-validate hook\n+\tfatal: command '\"'\"'git hook run --ignore-missing sendemail-validate -- <patch> <header>'\"'\"' died with exit code 1\n \twarning: no patches were sent\n \tEOF\n \ttest_cmp expect actual\n-- \n2.34.1\n"},{"id":"470316","messageId":"xmqqmt6loqxi.fsf@gitster.g","threadId":"59067","inReplyTo":"20230110211452.2568535-3-michael.strawbridge@amd.com","subject":"Re: [PATCH v5 2/2] send-email: expose header information to git-send-email's sendemail-validate hook","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2023-01-14T01:17:29Z","receivedAt":"2023-01-14T01:17:35Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Strawbridge, Michael\" <Michael.Strawbridge@amd.com> writes:\n\n> +It takes these command line arguments:\n> +1. the name of the file that holds the e-mail to be sent.\n> +2. the name of the file that holds the SMTP headers to be used.\n> +\n> +The hook doesn't need to support multiple header names (for example only Cc\n> +is passed).\n\nI think you meant, by \"multiple header names\", \"header names spelled\nin different cases\".\n\nThat may be a correct statement, but is more or less a useless one\nthat does not help hook writers.  Different people spell these\nheaders in different capitalization (for example, your message came\nwith \"CC:\" to various people, not \"Cc:\"), so the hook MUST know\nwhich case the feature adds to its input, if it chooses not to\nsupport different cases like \"Cc:\", \"cc:\", and \"CC:\".  IOW, \"only Cc\nis passed\" is not something they need to hear as a mear example.\nThey need to be told what headers are given to them and in what\ncapitalization for all headers in the input to them.\n\n> However, it does need to understand that lines beginning with\n> +whitespace belong to the previous header.  The header information follows\n> +the same format as the confirmation given at the end of send-email.\n\nI suspect that many people (including me) disable the confirmation\nand to them, the above description would not help.\n\nIn general, documentation should not depend on the reader having an\naccess to an environment where they can readily run commands and see\ntheir output.\n\nThanks.\n"},{"id":"470347","messageId":"xmqqedrxm7bn.fsf@gitster.g","threadId":"59067","inReplyTo":"20230110211452.2568535-3-michael.strawbridge@amd.com","subject":"Re: [PATCH v5 2/2] send-email: expose header information to git-send-email's sendemail-validate hook","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2023-01-14T16:03:56Z","receivedAt":"2023-01-14T16:04:01Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Strawbridge, Michael\" <Michael.Strawbridge@amd.com> writes:\n\n> +test_expect_success $PREREQ \"--validate hook supports header argument\" '\n> +\ttest_when_finished \"rm my-hooks.ran\" &&\n> +\twrite_script my-hooks/sendemail-validate <<-\\EOF &&\n> +\tfilesize=$(stat -c%s \"$2\")\n\nThat \"stat -c\" is a GNU-ism, I think.  macOS CI jobs at GitHub do\nnot seem to like it.\n\n> +\tif [ \"$filesize\" != \"0\" ]; then\n\nAlso, please see Documentation/CodingGuidelines to learn the subset\nof shell script syntax and style we adopted for this project.\n\nThanks.\n"},{"id":"470348","messageId":"xmqqa62lm76t.fsf@gitster.g","threadId":"59067","inReplyTo":"xmqqedrxm7bn.fsf@gitster.g","subject":"Re: [PATCH v5 2/2] send-email: expose header information to git-send-email's sendemail-validate hook","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2023-01-14T16:06:50Z","receivedAt":"2023-01-14T16:06:54Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> \"Strawbridge, Michael\" <Michael.Strawbridge@amd.com> writes:\n>\n>> +test_expect_success $PREREQ \"--validate hook supports header argument\" '\n>> +\ttest_when_finished \"rm my-hooks.ran\" &&\n>> +\twrite_script my-hooks/sendemail-validate <<-\\EOF &&\n>> +\tfilesize=$(stat -c%s \"$2\")\n>\n> That \"stat -c\" is a GNU-ism, I think.  macOS CI jobs at GitHub do\n> not seem to like it.\n>\n>> +\tif [ \"$filesize\" != \"0\" ]; then\n>\n> Also, please see Documentation/CodingGuidelines to learn the subset\n> of shell script syntax and style we adopted for this project.\n\nSorry, forgot to say that if you are merely interested to react to\nthe fact that a file has non-empty contents,\n\n\tif test -s \"$2\"\n\tthen\n\t\t... file $2 is not empty ...\n\tfi &&\n\t...\n\nshould be a way to do so.\n\nThanks.\n\n\n\n\n"},{"id":"470374","messageId":"xmqqfsccii86.fsf@gitster.g","threadId":"59067","inReplyTo":"xmqqa62lm76t.fsf@gitster.g","subject":"Re: [PATCH v5 2/2] send-email: expose header information to git-send-email's sendemail-validate hook","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2023-01-15T03:34:17Z","receivedAt":"2023-01-15T03:34:22Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> Junio C Hamano <gitster@pobox.com> writes:\n>\n>> \"Strawbridge, Michael\" <Michael.Strawbridge@amd.com> writes:\n>>\n>>> +test_expect_success $PREREQ \"--validate hook supports header argument\" '\n>>> +\ttest_when_finished \"rm my-hooks.ran\" &&\n>>> +\twrite_script my-hooks/sendemail-validate <<-\\EOF &&\n>>> +\tfilesize=$(stat -c%s \"$2\")\n>>\n>> That \"stat -c\" is a GNU-ism, I think.  macOS CI jobs at GitHub do\n>> not seem to like it.\n>>\n>>> +\tif [ \"$filesize\" != \"0\" ]; then\n>>\n>> Also, please see Documentation/CodingGuidelines to learn the subset\n>> of shell script syntax and style we adopted for this project.\n\nI'll tentatively queue this as a fix-up on top of the topic, but is\nthis testing the right thing?  Should we inspect \"$2\" and verify\nthat it gives us what we expect, not just it being non-empty?\n\n t/t9001-send-email.sh | 7 ++++---\n 1 file changed, 4 insertions(+), 3 deletions(-)\n\ndiff --git c/t/t9001-send-email.sh w/t/t9001-send-email.sh\nindex f02b1eba16..b19997cbbc 100755\n--- c/t/t9001-send-email.sh\n+++ w/t/t9001-send-email.sh\n@@ -568,9 +568,10 @@ test_expect_success $PREREQ \"--validate respects absolute core.hooksPath path\" '\n test_expect_success $PREREQ \"--validate hook supports header argument\" '\n \ttest_when_finished \"rm my-hooks.ran\" &&\n \twrite_script my-hooks/sendemail-validate <<-\\EOF &&\n-\tfilesize=$(stat -c%s \"$2\")\n-\tif [ \"$filesize\" != \"0\" ]; then\n-\t>my-hooks.ran\n+\trm -f my-hooks.ran\n+\tif test -s \"$2\"\n+\tthen\n+\t\t>my-hooks.ran\n \tfi\n \texit 1\n \tEOF\n"},{"id":"470468","messageId":"20230117014917.49378-1-michael.strawbridge@amd.com","threadId":"59067","inReplyTo":"20230110211452.2568535-1-michael.strawbridge@amd.com","subject":"[PATCH v5 0/2] send-email: expose header information to git-send-email's sendemail-validate hook","fromName":"Strawbridge, Michael","fromEmail":"michael.strawbridge@amd.com","sentAt":"2023-01-17T01:49:31Z","receivedAt":"2023-01-17T01:49:39Z","isPatch":true,"sender":{"key":"michael.strawbridge@amd.com","avatar":null},"body":"Please ignore this thread.\n\nMichael Strawbridge\n\n-- \n2.34.1\n"},{"id":"470476","messageId":"f31f1480-d611-f4b4-0e7b-589574943eef@amd.com","threadId":"59067","inReplyTo":"xmqqfsccii86.fsf@gitster.g","subject":"Re: [PATCH v5 2/2] send-email: expose header information to git-send-email's sendemail-validate hook","fromName":"Luben Tuikov","fromEmail":"luben.tuikov@amd.com","sentAt":"2023-01-17T04:09:00Z","receivedAt":"2023-01-17T04:09:14Z","isPatch":true,"sender":{"key":"luben.tuikov@amd.com","avatar":null},"body":"On 2023-01-14 22:34, Junio C Hamano wrote:\n> Junio C Hamano <gitster@pobox.com> writes:\n> \n>> Junio C Hamano <gitster@pobox.com> writes:\n>>\n>>> \"Strawbridge, Michael\" <Michael.Strawbridge@amd.com> writes:\n>>>\n>>>> +test_expect_success $PREREQ \"--validate hook supports header argument\" '\n>>>> +\ttest_when_finished \"rm my-hooks.ran\" &&\n>>>> +\twrite_script my-hooks/sendemail-validate <<-\\EOF &&\n>>>> +\tfilesize=$(stat -c%s \"$2\")\n>>>\n>>> That \"stat -c\" is a GNU-ism, I think.  macOS CI jobs at GitHub do\n>>> not seem to like it.\n>>>\n>>>> +\tif [ \"$filesize\" != \"0\" ]; then\n>>>\n>>> Also, please see Documentation/CodingGuidelines to learn the subset\n>>> of shell script syntax and style we adopted for this project.\n> \n> I'll tentatively queue this as a fix-up on top of the topic, but is\n> this testing the right thing?  Should we inspect \"$2\" and verify\n> that it gives us what we expect, not just it being non-empty?\n\nHi Junio,\n\nThanks for reviewing this patch set.\n\nWe're generally not interested in \"what else\" is in the SMTP envelope\nand headers.\n\nThe extension this patch set provides is that if a hook-writer is\ninterested in some SMTP header, or the contents of that header, then\nthere is a way to provide the SMTP envelope and thus check the headers.\n\nCurrently, $1, is identical to git-format-patch's output, (for which there\nare other hooks to check that output.) This was a bit disappointing, as it\nis a git-send-email hook after all, and we're interested in the \"email\" part\nof this Git command and hook.\n\nThe idea is that hook writers would merely be grepping for a particular\nheader they're interested in--it could even be a custom header, \"X-something\"\nfor instance, and if present, they'll check the contents of that header and\nvalidate the patch, or perform some other action.\n\nSo, checking that the SMTP envelope and headers, $2, is not empty suffices\nfor what this patch set implements. We leave it up to the hook writers to\ninspect the SMTP envelope and headers for their particular hook purpose.\n-- \nRegards,\nLuben\n\n"},{"id":"470478","messageId":"xmqqmt6hbx6y.fsf@gitster.g","threadId":"59067","inReplyTo":"f31f1480-d611-f4b4-0e7b-589574943eef@amd.com","subject":"Re: [PATCH v5 2/2] send-email: expose header information to git-send-email's sendemail-validate hook","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2023-01-17T04:29:41Z","receivedAt":"2023-01-17T04:29:51Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Luben Tuikov <luben.tuikov@amd.com> writes:\n\n> We're generally not interested in \"what else\" is in the SMTP envelope\n> and headers.\n> ...\n> The idea is that hook writers would merely be grepping for a particular\n> header they're interested in--it could even be a custom header, \"X-something\"\n> for instance, and if present, they'll check the contents of that header and\n> validate the patch, or perform some other action.\n\nI am following you thus far, but ...\n\n> So, checking that the SMTP envelope and headers, $2, is not empty suffices\n> for what this patch set implements. We leave it up to the hook writers to\n> inspect the SMTP envelope and headers for their particular hook purpose.\n\n... I am lost here.  To make sure that the hook writers' grepping\nfor a particular contents in the file $2 does find what they are\ntrying to find, wouldn't we want to have a test that looks for a\n\"known\" header that should exist in the expected output (or even\nbetter, arrange the send-email invocation so that a custom header is\ninjected to the output of format-patch and grep for that \"known\"\nheader)?\n\nThanks.\n"},{"id":"470480","messageId":"ba987147-6b13-e1f8-e6b6-4efddcce6a37@amd.com","threadId":"59067","inReplyTo":"xmqqmt6hbx6y.fsf@gitster.g","subject":"Re: [PATCH v5 2/2] send-email: expose header information to git-send-email's sendemail-validate hook","fromName":"Luben Tuikov","fromEmail":"luben.tuikov@amd.com","sentAt":"2023-01-17T04:56:58Z","receivedAt":"2023-01-17T04:58:01Z","isPatch":true,"sender":{"key":"luben.tuikov@amd.com","avatar":null},"body":"On 2023-01-16 23:29, Junio C Hamano wrote:\n> Luben Tuikov <luben.tuikov@amd.com> writes:\n> \n>> We're generally not interested in \"what else\" is in the SMTP envelope\n>> and headers.\n>> ...\n>> The idea is that hook writers would merely be grepping for a particular\n>> header they're interested in--it could even be a custom header, \"X-something\"\n>> for instance, and if present, they'll check the contents of that header and\n>> validate the patch, or perform some other action.\n> \n> I am following you thus far, but ...\n> \n>> So, checking that the SMTP envelope and headers, $2, is not empty suffices\n>> for what this patch set implements. We leave it up to the hook writers to\n>> inspect the SMTP envelope and headers for their particular hook purpose.\n> \n> ... I am lost here.  To make sure that the hook writers' grepping\n> for a particular contents in the file $2 does find what they are\n> trying to find, wouldn't we want to have a test that looks for a\n> \"known\" header that should exist in the expected output (or even\n> better, arrange the send-email invocation so that a custom header is\n> injected to the output of format-patch and grep for that \"known\"\n> header)?\n\nYes, that's exactly how my Git is set up. (It's a bit more involved\nthan this, but essentially a custom header is added and a check performed.)\n\nI'll follow up on v6 2/2 patch review with this.\n-- \nRegards,\nLuben\n\n"},{"id":"470490","messageId":"230117.86wn5lxpl0.gmgdl@evledraar.gmail.com","threadId":"59067","inReplyTo":"20230110211452.2568535-2-michael.strawbridge@amd.com","subject":"Re: [PATCH v5 1/2] send-email: refactor header generation functions","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2023-01-17T13:20:58Z","receivedAt":"2023-01-17T13:23:17Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"\nOn Tue, Jan 10 2023, Strawbridge, Michael wrote:\n\n> Split process_file and send_message into easier to use functions.\n> Making SMTP header information more widely available.\n>\n> Cc: Luben Tuikov <luben.tuikov@amd.com>\n> Cc: Junio C Hamano <gitster@pobox.com>\n> Signed-off-by: Michael Strawbridge <michael.strawbridge@amd.com>\n> ---\n>  git-send-email.perl | 49 ++++++++++++++++++++++++++++-----------------\n>  1 file changed, 31 insertions(+), 18 deletions(-)\n>\n> diff --git a/git-send-email.perl b/git-send-email.perl\n> index 5861e99a6e..810dd1f1ce 100755\n> --- a/git-send-email.perl\n> +++ b/git-send-email.perl\n> @@ -1495,16 +1495,7 @@ sub file_name_is_absolute {\n>  \treturn File::Spec::Functions::file_name_is_absolute($path);\n>  }\n>  \n> -# Prepares the email, then asks the user what to do.\n> -#\n> -# If the user chooses to send the email, it's sent and 1 is returned.\n> -# If the user chooses not to send the email, 0 is returned.\n> -# If the user decides they want to make further edits, -1 is returned and the\n> -# caller is expected to call send_message again after the edits are performed.\n> -#\n> -# If an error occurs sending the email, this just dies.\n> -\n> -sub send_message {\n> +sub gen_header {\n>  \tmy @recipients = unique_email_list(@to);\n>  \t@cc = (grep { my $cc = extract_valid_address_or_die($_);\n>  \t\t      not grep { $cc eq $_ || $_ =~ /<\\Q${cc}\\E>$/ } @recipients\n> @@ -1546,6 +1537,22 @@ sub send_message {\n>  \tif (@xh) {\n>  \t\t$header .= join(\"\\n\", @xh) . \"\\n\";\n>  \t}\n> +\tmy $recipients_ref = \\@recipients;\n> +\treturn ($recipients_ref, $to, $date, $gitversion, $cc, $ccline, $header);\n> +}\n> +\n> +# Prepares the email, then asks the user what to do.\n> +#\n> +# If the user chooses to send the email, it's sent and 1 is returned.\n> +# If the user chooses not to send the email, 0 is returned.\n> +# If the user decides they want to make further edits, -1 is returned and the\n> +# caller is expected to call send_message again after the edits are performed.\n> +#\n> +# If an error occurs sending the email, this just dies.\n> +\n> +sub send_message {\n> +\tmy ($recipients_ref, $to, $date, $gitversion, $cc, $ccline, $header) = gen_header();\n\nThis makes the diff smaller, but if we're refactoring these functions to\nreturn arguments it's probably better to return a hash reference rather\nthan remembering all the parameter names.\n\nBut in this case it's probably fine...\n\n> +\tmy @recipients = @$recipients_ref;\n>  \n>  \tmy @sendmail_parameters = ('-i', @recipients);\n>  \tmy $raw_from = $sender;\n> @@ -1735,11 +1742,8 @@ sub send_message {\n>  $references = $initial_in_reply_to || '';\n>  $message_num = 0;\n>  \n> -# Prepares the email, prompts the user, sends it out\n> -# Returns 0 if an edit was done and the function should be called again, or 1\n> -# otherwise.\n> -sub process_file {\n> -\tmy ($t) = @_;\n> +sub pre_process_file {\n> +\tmy ($t, $quiet) = @_;\n\nThis, I think, is an anti-pattern in this file. We can just read the\n\"$quiet\" and other things that we set up when we parse the parameters as\nglobals, we don't need to pass them as named parameters.\n\nIt doesn't help readability to shadow that variable with another lexical\nhere below:\n\n> [...]\n> +}\n> +\n> +# Prepares the email, prompts the user, sends it out\n> +# Returns 0 if an edit was done and the function should be called again, or 1\n> +# otherwise.\n> +sub process_file {\n> +\tmy ($t) = @_;\n> +\n> +        pre_process_file($t, $quiet);\n>  \n>  \tmy $message_was_sent = send_message();\n>  \tif ($message_was_sent == -1) {\n> @@ -2002,7 +2015,7 @@ sub process_file {\n>  # Execute a command (e.g. $to_cmd) to get a list of email addresses\n>  # and return a results array\n>  sub recipients_cmd {\n> -\tmy ($prefix, $what, $cmd, $file) = @_;\n> +\tmy ($prefix, $what, $cmd, $file, $quiet) = @_;\n>  \n>  \tmy @addresses = ();\n>  \topen my $fh, \"-|\", \"$cmd \\Q$file\\E\"\n\n"},{"id":"470491","messageId":"230117.86sfg9xp98.gmgdl@evledraar.gmail.com","threadId":"59067","inReplyTo":"20230110211452.2568535-3-michael.strawbridge@amd.com","subject":"Re: [PATCH v5 2/2] send-email: expose header information to git-send-email's sendemail-validate hook","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2023-01-17T13:23:50Z","receivedAt":"2023-01-17T13:30:19Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"\nOn Tue, Jan 10 2023, Strawbridge, Michael wrote:\n\n> To allow further flexibility in the git hook, the SMTP header\n> information of the email that git-send-email intends to send, is now\n> passed as a 2nd argument to the sendemail-validate hook.\n>\n> As an example, this can be useful for acting upon keywords in the\n> subject or specific email addresses.\n\nOkey, but...\n\n> diff --git a/Documentation/githooks.txt b/Documentation/githooks.txt\n> index a16e62bc8c..2b5c6640cc 100644\n> --- a/Documentation/githooks.txt\n> +++ b/Documentation/githooks.txt\n> @@ -583,10 +583,19 @@ processed by rebase.\n>  sendemail-validate\n>  ~~~~~~~~~~~~~~~~~~\n>  \n> -This hook is invoked by linkgit:git-send-email[1].  It takes a single parameter,\n> -the name of the file that holds the e-mail to be sent.  Exiting with a\n> -non-zero status causes `git send-email` to abort before sending any\n> -e-mails.\n> +This hook is invoked by linkgit:git-send-email[1].\n> +\n> +It takes these command line arguments:\n> +1. the name of the file that holds the e-mail to be sent.\n> +2. the name of the file that holds the SMTP headers to be used.\n> +\n> +The hook doesn't need to support multiple header names (for example only Cc\n> +is passed). However, it does need to understand that lines beginning with\n> +whitespace belong to the previous header.  The header information follows\n> +the same format as the confirmation given at the end of send-email.\n> +\n> +Exiting with a non-zero status causes `git send-email` to abort\n> +before sending any e-mails.\n>  \n>  fsmonitor-watchman\n>  ~~~~~~~~~~~~~~~~~~\n> diff --git a/git-send-email.perl b/git-send-email.perl\n> index 810dd1f1ce..b2adca515e 100755\n> --- a/git-send-email.perl\n> +++ b/git-send-email.perl\n> @@ -787,14 +787,6 @@ sub is_format_patch_arg {\n>  \n>  @files = handle_backup_files(@files);\n>  \n> -if ($validate) {\n> -\tforeach my $f (@files) {\n> -\t\tunless (-p $f) {\n> -\t\t\tvalidate_patch($f, $target_xfer_encoding);\n> -\t\t}\n> -\t}\n> -}\n> -\n>  if (@files) {\n>  \tunless ($quiet) {\n>  \t\tprint $_,\"\\n\" for (@files);\n> @@ -1738,6 +1730,16 @@ sub send_message {\n>  \treturn 1;\n>  }\n>  \n> +if ($validate) {\n> +\tforeach my $f (@files) {\n> +\t\tunless (-p $f) {\n> +\t\t        pre_process_file($f, 1);\n> +\n> +\t\t\tvalidate_patch($f, $target_xfer_encoding);\n> +\t\t}\n> +\t}\n> +}\n\n...here we have the seemingly unrelated change of first doing the\nvalidation before this, and if we pass it we'll print the names of the\nfiles we're sending unless --quiet.\n\nNow we'll do it the other way around, maybe that's good, or maybe not,\nbut your updated docs don't say.\n\nAlso (and I didn't look at this all that carefully), why are you moving\nthe control logic to between the later function declarations?\n\nPerl isn't a language where you need to arrange your source in that way\n(unless a bareword is involved, or if this happens at BEGIN time or\nwhatever). The current structure is:\n\n\t<use & imports>\n\t<basic setup (getopts etc)>\n\t<main logic>\n\t<helper function>\n\nHere you're moving part of the main logic to in-between two helper\nfunction, why?\n\n>  $in_reply_to = $initial_in_reply_to;\n>  $references = $initial_in_reply_to || '';\n>  $message_num = 0;\n> @@ -2101,11 +2103,20 @@ sub validate_patch {\n>  \t\t\tchdir($repo->wc_path() or $repo->repo_path())\n>  \t\t\t\tor die(\"chdir: $!\");\n>  \t\t\tlocal $ENV{\"GIT_DIR\"} = $repo->repo_path();\n> +\n> +\t\t\tmy ($recipients_ref, $to, $date, $gitversion, $cc, $ccline, $header) = gen_header();\n> +\n> +\t\t\trequire File::Temp;\n> +\t\t\tmy ($header_filehandle, $header_filename) = File::Temp::tempfile(\n> +                            \".gitsendemail.header.XXXXXX\", DIR => $repo->repo_path());\n> +\t\t\tprint $header_filehandle $header;\n> +\n>  \t\t\tmy @cmd = (\"git\", \"hook\", \"run\", \"--ignore-missing\",\n>  \t\t\t\t    $hook_name, \"--\");\n> -\t\t\tmy @cmd_msg = (@cmd, \"<patch>\");\n> -\t\t\tmy @cmd_run = (@cmd, $target);\n> +\t\t\tmy @cmd_msg = (@cmd, \"<patch>\", \"<header>\");\n> +\t\t\tmy @cmd_run = (@cmd, $target, $header_filename);\n>  \t\t\t$hook_error = system_or_msg(\\@cmd_run, undef, \"@cmd_msg\");\n> +\t\t\tunlink($header_filehandle);\n>  \t\t\tchdir($cwd_save) or die(\"chdir: $!\");\n\nI know \"git hook run\" doesn't support input on stdin yet, but isn't this\njust working around it not supporting that? That seems like a much\nbetter & natural interface than what we're doing here.\n\nI have out-of-tree patches for that (or rather, a re-roll of Emily's\npatches to do that), if that landed in-tree could this use that\ninterface, do you think?\n\nI'd rather that we didn't forever codify a strange interface here due to\na temporary limitation in \"git hook\" and the hook API...\n"},{"id":"470497","messageId":"xmqqv8l59ot2.fsf@gitster.g","threadId":"59067","inReplyTo":"230117.86wn5lxpl0.gmgdl@evledraar.gmail.com","subject":"Re: [PATCH v5 1/2] send-email: refactor header generation functions","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2023-01-17T15:13:45Z","receivedAt":"2023-01-17T15:14:07Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:\n\n>> +sub send_message {\n>> +\tmy ($recipients_ref, $to, $date, $gitversion, $cc, $ccline, $header) = gen_header();\n>\n> This makes the diff smaller, but if we're refactoring these functions to\n> return arguments it's probably better to return a hash reference rather\n> than remembering all the parameter names.\n>\n> But in this case it's probably fine...\n> ...\n>> +sub pre_process_file {\n>> +\tmy ($t, $quiet) = @_;\n>\n> This, I think, is an anti-pattern in this file. We can just read the\n> \"$quiet\" and other things that we set up when we parse the parameters as\n> globals, we don't need to pass them as named parameters.\n>\n> It doesn't help readability to shadow that variable with another lexical\n> here below:\n> ...\n\nThanks as usual for a careful review, with concrete suggestions for\nimprovements.\n\n"},{"id":"470546","messageId":"20230117215811.78313-1-michael.strawbridge@amd.com","threadId":"59067","inReplyTo":"230117.86sfg9xp98.gmgdl@evledraar.gmail.com","subject":"[PATCH v5 2/2] send-email: expose header information to git-send-email's sendemail-validate hook","fromName":"Strawbridge, Michael","fromEmail":"michael.strawbridge@amd.com","sentAt":"2023-01-17T21:58:31Z","receivedAt":"2023-01-17T22:18:13Z","isPatch":true,"sender":{"key":"michael.strawbridge@amd.com","avatar":null},"body":"On Tue, Jan 17 2023, Ævar Arnfjörð Bjarmason wrote:\n>On Tue, Jan 10 2023, Strawbridge, Michael wrote:\n>\n>> To allow further flexibility in the git hook, the SMTP header\n>> information of the email that git-send-email intends to send, is now\n>> passed as a 2nd argument to the sendemail-validate hook.\n>>\n>> As an example, this can be useful for acting upon keywords in the\n>> subject or specific email addresses.\n>\n>Okey, but...\n>\n>> diff --git a/Documentation/githooks.txt b/Documentation/githooks.txt\n>> index a16e62bc8c..2b5c6640cc 100644\n>> --- a/Documentation/githooks.txt\n>> +++ b/Documentation/githooks.txt\n>> @@ -583,10 +583,19 @@ processed by rebase.\n>>  sendemail-validate\n>>  ~~~~~~~~~~~~~~~~~~\n>>  \n>> -This hook is invoked by linkgit:git-send-email[1].  It takes a single parameter,\n>> -the name of the file that holds the e-mail to be sent.  Exiting with a\n>> -non-zero status causes `git send-email` to abort before sending any\n>> -e-mails.\n>> +This hook is invoked by linkgit:git-send-email[1].\n>> +\n>> +It takes these command line arguments:\n>> +1. the name of the file that holds the e-mail to be sent.\n>> +2. the name of the file that holds the SMTP headers to be used.\n>> +\n>> +The hook doesn't need to support multiple header names (for example only Cc\n>> +is passed). However, it does need to understand that lines beginning with\n>> +whitespace belong to the previous header.  The header information follows\n>> +the same format as the confirmation given at the end of send-email.\n>> +\n>> +Exiting with a non-zero status causes `git send-email` to abort\n>> +before sending any e-mails.\n>>  \n>>  fsmonitor-watchman\n>>  ~~~~~~~~~~~~~~~~~~\n>> diff --git a/git-send-email.perl b/git-send-email.perl\n>> index 810dd1f1ce..b2adca515e 100755\n>> --- a/git-send-email.perl\n>> +++ b/git-send-email.perl\n>> @@ -787,14 +787,6 @@ sub is_format_patch_arg {\n>>  \n>>  @files = handle_backup_files(@files);\n>>  \n>> -if ($validate) {\n>> -\tforeach my $f (@files) {\n>> -\t\tunless (-p $f) {\n>> -\t\t\tvalidate_patch($f, $target_xfer_encoding);\n>> -\t\t}\n>> -\t}\n>> -}\n>> -\n>>  if (@files) {\n>>  \tunless ($quiet) {\n>>  \t\tprint $_,\"\\n\" for (@files);\n>> @@ -1738,6 +1730,16 @@ sub send_message {\n>>  \treturn 1;\n>>  }\n>>  \n>> +if ($validate) {\n>> +\tforeach my $f (@files) {\n>> +\t\tunless (-p $f) {\n>> +\t\t        pre_process_file($f, 1);\n>> +\n>> +\t\t\tvalidate_patch($f, $target_xfer_encoding);\n>> +\t\t}\n>> +\t}\n>> +}\n>\n>...here we have the seemingly unrelated change of first doing the\n>validation before this, and if we pass it we'll print the names of the\n>files we're sending unless --quiet.\n>\n>Now we'll do it the other way around, maybe that's good, or maybe not,\n>but your updated docs don't say.\n>\n>Also (and I didn't look at this all that carefully), why are you moving\n>the control logic to between the later function declarations?\n>\n>Perl isn't a language where you need to arrange your source in that way\n>(unless a bareword is involved, or if this happens at BEGIN time or\n>whatever). The current structure is:\n>\n>\t<use & imports>\n>\t<basic setup (getopts etc)>\n>\t<main logic>\n>\t<helper function>\n>\n>Here you're moving part of the main logic to in-between two helper\n>function, why?\n>\n\nIn general I understand your point.  However, I found in\ngit-send-email that code outside of functions is sprinkled in between\nfunction declarations in several areas.  Lines 790-797 and 1011-1058 are\nexamples of some of what I mean.  Also, the original process_file call is\nactually out of place (roughly line 2011-2015). Unfortunately some of this\nsprinkled code has an impact on the header variables and so I needed to\nmove the validation code lower, closer to the process_file section but\nbefore the intialization of in_reply_to, references, and message_num.\nI was attempting to reduce the number of code changes.\n\nYou do bring up a good point about printing of the names of files\nbefore validation causing a difference in output. I can attempt to move\nsome more of this code as well, if the change of output is deemed\nimportant enough.\n \n>>  $in_reply_to = $initial_in_reply_to;\n>>  $references = $initial_in_reply_to || '';\n>>  $message_num = 0;\n>> @@ -2101,11 +2103,20 @@ sub validate_patch {\n>>  \t\t\tchdir($repo->wc_path() or $repo->repo_path())\n>>  \t\t\t\tor die(\"chdir: $!\");\n>>  \t\t\tlocal $ENV{\"GIT_DIR\"} = $repo->repo_path();\n>> +\n>> +\t\t\tmy ($recipients_ref, $to, $date, $gitversion, $cc, $ccline, $header) = gen_header();\n>> +\n>> +\t\t\trequire File::Temp;\n>> +\t\t\tmy ($header_filehandle, $header_filename) = File::Temp::tempfile(\n>> +                            \".gitsendemail.header.XXXXXX\", DIR => $repo->repo_path());\n>> +\t\t\tprint $header_filehandle $header;\n>> +\n>>  \t\t\tmy @cmd = (\"git\", \"hook\", \"run\", \"--ignore-missing\",\n>>  \t\t\t\t    $hook_name, \"--\");\n>> -\t\t\tmy @cmd_msg = (@cmd, \"<patch>\");\n>> -\t\t\tmy @cmd_run = (@cmd, $target);\n>> +\t\t\tmy @cmd_msg = (@cmd, \"<patch>\", \"<header>\");\n>> +\t\t\tmy @cmd_run = (@cmd, $target, $header_filename);\n>>  \t\t\t$hook_error = system_or_msg(\\@cmd_run, undef, \"@cmd_msg\");\n>> +\t\t\tunlink($header_filehandle);\n>>  \t\t\tchdir($cwd_save) or die(\"chdir: $!\");\n>\n>I know \"git hook run\" doesn't support input on stdin yet, but isn't this\n>just working around it not supporting that? That seems like a much\n>better & natural interface than what we're doing here.\n>\n>I have out-of-tree patches for that (or rather, a re-roll of Emily's\n>patches to do that), if that landed in-tree could this use that\n>interface, do you think?\n>\n>I'd rather that we didn't forever codify a strange interface here due to\n>a temporary limitation in \"git hook\" and the hook API...\n\nI was trying to follow the convention that the original hook was using.\nI'm not against changing this if the out of tree patches you speak of\nare going to be rolled in soon.  However, I'd prefer not to delay this\npatch if these other patches are far off. Thanks.\n\n-- \n2.34.1\n"},{"id":"470555","messageId":"20230117213624.73926-1-michael.strawbridge@amd.com","threadId":"59067","inReplyTo":"230117.86wn5lxpl0.gmgdl@evledraar.gmail.com","subject":"[PATCH v5 1/2] send-email: refactor header generation functions","fromName":"Strawbridge, Michael","fromEmail":"michael.strawbridge@amd.com","sentAt":"2023-01-17T21:36:45Z","receivedAt":"2023-01-17T23:05:45Z","isPatch":true,"sender":{"key":"michael.strawbridge@amd.com","avatar":null},"body":"On Tue, Jan 17 2023, Ævar Arnfjörð Bjarmason wrote:\n>On Tue, Jan 10 2023, Strawbridge, Michael wrote:\n>\n>> Split process_file and send_message into easier to use functions.\n>> Making SMTP header information more widely available.\n>>\n>> Cc: Luben Tuikov <luben.tuikov@amd.com>\n>> Cc: Junio C Hamano <gitster@pobox.com>\n>> Signed-off-by: Michael Strawbridge <michael.strawbridge@amd.com>\n>> ---\n>>  git-send-email.perl | 49 ++++++++++++++++++++++++++++-----------------\n>>  1 file changed, 31 insertions(+), 18 deletions(-)\n>>\n>> diff --git a/git-send-email.perl b/git-send-email.perl\n>> index 5861e99a6e..810dd1f1ce 100755\n>> --- a/git-send-email.perl\n>> +++ b/git-send-email.perl\n>> @@ -1495,16 +1495,7 @@ sub file_name_is_absolute {\n>>  \treturn File::Spec::Functions::file_name_is_absolute($path);\n>>  }\n>>  \n>> -# Prepares the email, then asks the user what to do.\n>> -#\n>> -# If the user chooses to send the email, it's sent and 1 is returned.\n>> -# If the user chooses not to send the email, 0 is returned.\n>> -# If the user decides they want to make further edits, -1 is returned and the\n>> -# caller is expected to call send_message again after the edits are performed.\n>> -#\n>> -# If an error occurs sending the email, this just dies.\n>> -\n>> -sub send_message {\n>> +sub gen_header {\n>>  \tmy @recipients = unique_email_list(@to);\n>>  \t@cc = (grep { my $cc = extract_valid_address_or_die($_);\n>>  \t\t      not grep { $cc eq $_ || $_ =~ /<\\Q${cc}\\E>$/ } @recipients\n>> @@ -1546,6 +1537,22 @@ sub send_message {\n>>  \tif (@xh) {\n>>  \t\t$header .= join(\"\\n\", @xh) . \"\\n\";\n>>  \t}\n>> +\tmy $recipients_ref = \\@recipients;\n>> +\treturn ($recipients_ref, $to, $date, $gitversion, $cc, $ccline, $header);\n>> +}\n>> +\n>> +# Prepares the email, then asks the user what to do.\n>> +#\n>> +# If the user chooses to send the email, it's sent and 1 is returned.\n>> +# If the user chooses not to send the email, 0 is returned.\n>> +# If the user decides they want to make further edits, -1 is returned and the\n>> +# caller is expected to call send_message again after the edits are performed.\n>> +#\n>> +# If an error occurs sending the email, this just dies.\n>> +\n>> +sub send_message {\n>> +\tmy ($recipients_ref, $to, $date, $gitversion, $cc, $ccline, $header) = gen_header();\n>\n>This makes the diff smaller, but if we're refactoring these functions to\n>return arguments it's probably better to return a hash reference rather\n>than remembering all the parameter names.\n>\n>But in this case it's probably fine...\n>\nI hadn't known about passing a hash reference on perl.  Although after\nlooking into it, I'm not sure I will go that way this time.\n\n>> +\tmy @recipients = @$recipients_ref;\n>>  \n>>  \tmy @sendmail_parameters = ('-i', @recipients);\n>>  \tmy $raw_from = $sender;\n>> @@ -1735,11 +1742,8 @@ sub send_message {\n>>  $references = $initial_in_reply_to || '';\n>>  $message_num = 0;\n>>  \n>> -# Prepares the email, prompts the user, sends it out\n>> -# Returns 0 if an edit was done and the function should be called again, or 1\n>> -# otherwise.\n>> -sub process_file {\n>> -\tmy ($t) = @_;\n>> +sub pre_process_file {\n>> +\tmy ($t, $quiet) = @_;\n>\n>This, I think, is an anti-pattern in this file. We can just read the\n>\"$quiet\" and other things that we set up when we parse the parameters as\n>globals, we don't need to pass them as named parameters.\n>\n>It doesn't help readability to shadow that variable with another lexical\n>here below:\n>\nI am open to guidance here.  The reason I included quiet as an argument\nwas because I wanted to override the global quiet value for the call of\npre_process_file from the validation section (line 1736).  This is needed\notherwise the user gets spammed with double print statements.  Once in\nthe validation loop and another time in the actual sending message part.\n\nThe paths forward that I can currently see are:\n1) a) remain as it is\n   b) rename quiet in pre_process_file but keep the logic the same\n2) in the validation section, temporarily save the quiet value, alter it to\nindicate quieting of the print statements, and then put the quiet value back\n3) separate out the print statements inside pre_prcoess_file into a different\nfunction and only call that function in the send message code.\n\n>> [...]\n>> +}\n>> +\n>> +# Prepares the email, prompts the user, sends it out\n>> +# Returns 0 if an edit was done and the function should be called again, or 1\n>> +# otherwise.\n>> +sub process_file {\n>> +\tmy ($t) = @_;\n>> +\n>> +        pre_process_file($t, $quiet);\n>>  \n>>  \tmy $message_was_sent = send_message();\n>>  \tif ($message_was_sent == -1) {\n>> @@ -2002,7 +2015,7 @@ sub process_file {\n>>  # Execute a command (e.g. $to_cmd) to get a list of email addresses\n>>  # and return a results array\n>>  sub recipients_cmd {\n>> -\tmy ($prefix, $what, $cmd, $file) = @_;\n>> +\tmy ($prefix, $what, $cmd, $file, $quiet) = @_;\n>>  \n>>  \tmy @addresses = ();\n>>  \topen my $fh, \"-|\", \"$cmd \\Q$file\\E\"\n\nI appreciate your feedback!\n\n-- \n2.34.1\n"}]}