{"thread":{"id":"12196","subject":"[PATCH 3/4] Combine To: and Cc: headers","startedAt":"2008-02-19T07:40:33Z","lastAt":"2008-02-19T07:40:33Z","messageCount":1,"participants":["Daniel Barkalow"],"isPatch":true,"patchVersion":1,"patchTotal":4},"messages":[{"id":"69243","messageId":"alpine.LNX.1.00.0802190239500.5816@iabervon.org","threadId":"12196","inReplyTo":null,"subject":"[PATCH 3/4] Combine To: and Cc: headers","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2008-02-19T07:40:33Z","receivedAt":"2008-02-19T07:40:33Z","isPatch":true,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"RFC 2822 only permits a single To: header and a single Cc: header, so\nwe need to turn multiple values of each of these into a list. This\nwill be particularly significant with a command-line option to add Cc:\nheaders, where the user can't make sure to configure valid header sets\nin any easy way.\n\nSigned-off-by: Daniel Barkalow <barkalow@iabervon.org>\n---\n builtin-log.c           |   78 ++++++++++++++++++++++++++++++++++++++--------\n t/t4014-format-patch.sh |    2 +-\n 2 files changed, 65 insertions(+), 15 deletions(-)\n\ndiff --git a/builtin-log.c b/builtin-log.c\nindex 73b6d53..ae62668 100644\n--- a/builtin-log.c\n+++ b/builtin-log.c\n@@ -411,28 +411,47 @@ static int istitlechar(char c)\n \t\t(c >= '0' && c <= '9') || c == '.' || c == '_';\n }\n \n-static char *extra_headers = NULL;\n-static int extra_headers_size = 0;\n static const char *fmt_patch_suffix = \".patch\";\n static int numbered = 0;\n static int auto_number = 0;\n \n+static char **extra_hdr;\n+static int extra_hdr_nr;\n+static int extra_hdr_alloc;\n+\n+static char **extra_to;\n+static int extra_to_nr;\n+static int extra_to_alloc;\n+\n+static char **extra_cc;\n+static int extra_cc_nr;\n+static int extra_cc_alloc;\n+\n+static void add_header(const char *value)\n+{\n+\tint len = strlen(value);\n+\twhile (value[len - 1] == '\\n')\n+\t\tlen--;\n+\tif (!strncasecmp(value, \"to: \", 4)) {\n+\t\tALLOC_GROW(extra_to, extra_to_nr + 1, extra_to_alloc);\n+\t\textra_to[extra_to_nr++] = xstrndup(value + 4, len - 4);\n+\t\treturn;\n+\t}\n+\tif (!strncasecmp(value, \"cc: \", 4)) {\n+\t\tALLOC_GROW(extra_cc, extra_cc_nr + 1, extra_cc_alloc);\n+\t\textra_cc[extra_cc_nr++] = xstrndup(value + 4, len - 4);\n+\t\treturn;\n+\t}\n+\tALLOC_GROW(extra_hdr, extra_hdr_nr + 1, extra_hdr_alloc);\n+\textra_hdr[extra_hdr_nr++] = xstrndup(value, len);\n+}\n+\n static int git_format_config(const char *var, const char *value)\n {\n \tif (!strcmp(var, \"format.headers\")) {\n-\t\tint len;\n-\n \t\tif (!value)\n \t\t\tdie(\"format.headers without value\");\n-\t\tlen = strlen(value);\n-\t\twhile (value[len - 1] == '\\n')\n-\t\t\tlen--;\n-\t\textra_headers_size += len + 2;\n-\t\textra_headers = xrealloc(extra_headers, extra_headers_size);\n-\t\textra_headers[extra_headers_size - len - 2] = 0;\n-\t\tstrcat(extra_headers, value);\n-\t\textra_headers[extra_headers_size - 2] = '\\n';\n-\t\textra_headers[extra_headers_size - 1] = 0;\n+\t\tadd_header(value);\n \t\treturn 0;\n \t}\n \tif (!strcmp(var, \"format.suffix\")) {\n@@ -712,6 +731,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)\n \tconst char *in_reply_to = NULL;\n \tstruct patch_ids ids;\n \tchar *add_signoff = NULL;\n+\tstruct strbuf buf;\n \n \tgit_config(git_format_config);\n \tinit_revisions(&rev, prefix);\n@@ -724,7 +744,6 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)\n \tDIFF_OPT_SET(&rev.diffopt, RECURSIVE);\n \n \trev.subject_prefix = fmt_patch_subject_prefix;\n-\trev.extra_headers = extra_headers;\n \n \t/*\n \t * Parse the arguments before setup_revisions(), or something\n@@ -815,6 +834,37 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)\n \t}\n \targc = j;\n \n+\tstrbuf_init(&buf, 0);\n+\n+\tfor (i = 0; i < extra_hdr_nr; i++) {\n+\t\tstrbuf_addstr(&buf, extra_hdr[i]);\n+\t\tstrbuf_addch(&buf, '\\n');\n+\t}\n+\n+\tif (extra_to_nr)\n+\t\tstrbuf_addstr(&buf, \"To: \");\n+\tfor (i = 0; i < extra_to_nr; i++) {\n+\t\tif (i)\n+\t\t\tstrbuf_addstr(&buf, \"    \");\n+\t\tstrbuf_addstr(&buf, extra_to[i]);\n+\t\tif (i + 1 < extra_to_nr)\n+\t\t\tstrbuf_addch(&buf, ',');\n+\t\tstrbuf_addch(&buf, '\\n');\n+\t}\n+\n+\tif (extra_cc_nr)\n+\t\tstrbuf_addstr(&buf, \"Cc: \");\n+\tfor (i = 0; i < extra_cc_nr; i++) {\n+\t\tif (i)\n+\t\t\tstrbuf_addstr(&buf, \"    \");\n+\t\tstrbuf_addstr(&buf, extra_cc[i]);\n+\t\tif (i + 1 < extra_cc_nr)\n+\t\t\tstrbuf_addch(&buf, ',');\n+\t\tstrbuf_addch(&buf, '\\n');\n+\t}\n+\n+\trev.extra_headers = strbuf_detach(&buf, 0);\n+\n \tif (start_number < 0)\n \t\tstart_number = 1;\n \tif (numbered && keep_subject)\ndiff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\nindex 755fe6d..43d8841 100755\n--- a/t/t4014-format-patch.sh\n+++ b/t/t4014-format-patch.sh\n@@ -112,7 +112,7 @@ test_expect_success 'extra headers without newlines' '\n \t\n '\n \n-test_expect_failure 'extra headers with multiple To:s' '\n+test_expect_success 'extra headers with multiple To:s' '\n \n \tgit config --replace-all format.headers \"To: R. E. Cipient <rcipient@example.com>\" &&\n \tgit config --add format.headers \"To: S. E. Cipient <scipient@example.com>\" &&\n-- \n1.5.4.1.192.g8ea3a\n"}]}