{"thread":{"id":"4267","subject":"[PATCH 0/6] Detect non email patches in git-mailinfo","startedAt":"2006-05-23T19:42:45Z","lastAt":"2006-05-26T08:16:24Z","messageCount":10,"participants":["Eric W. Biederman","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":6},"messages":[{"id":"20566","messageId":"m18xosjznu.fsf@ebiederm.dsl.xmission.com","threadId":"4267","inReplyTo":null,"subject":"[PATCH 0/6] Detect non email patches in git-mailinfo","fromName":"Eric W. Biederman","fromEmail":"ebiederm@xmission.com","sentAt":"2006-05-23T19:42:45Z","receivedAt":"2006-05-23T19:42:45Z","isPatch":true,"sender":{"key":"ebiederm@xmission.com","avatar":"https://avatars.githubusercontent.com/u/7477136?v=4"},"body":"\nAfter looking at a number of additional quit patches I noticed\na small problem with using the current git-mailinfo.  On patches\nwith out any leading headers git-mailinfo can get confused and\nloose a bit of information.\n\nSo far I have only seen this in the quilt from Andi Kleen but\nit is fairly straight forward to fix.\n\nWhat follows is a small patch series that one small step at\na time refactors (and I think simplifies) git-mailinfo \nso that it can detect and cope with a file without any\nemail headers.\n\nEric\n"},{"id":"20567","messageId":"m14pzgjzlg.fsf@ebiederm.dsl.xmission.com","threadId":"4267","inReplyTo":"m18xosjznu.fsf@ebiederm.dsl.xmission.com","subject":"[PATCH 1/6] Make read_one_header_line return a flag not a length.","fromName":"Eric W. Biederman","fromEmail":"ebiederm@xmission.com","sentAt":"2006-05-23T19:44:11Z","receivedAt":"2006-05-23T19:44:11Z","isPatch":true,"sender":{"key":"ebiederm@xmission.com","avatar":"https://avatars.githubusercontent.com/u/7477136?v=4"},"body":"\nCurrently we only use the return value from read_one_header line\nto tell if the line we have read is a header or not.  So make\nit a flag.  This paves the way for better email detection.\n\nSigned-off-by: Eric W. Biederman <ebiederm@xmission.com>\n\n\n---\n\n mailinfo.c |   22 +++++++++++-----------\n 1 files changed, 11 insertions(+), 11 deletions(-)\n\n40f4ca44ec851e435ce9453c682c71b9c67063b9\ndiff --git a/mailinfo.c b/mailinfo.c\nindex b276519..83a2986 100644\n--- a/mailinfo.c\n+++ b/mailinfo.c\n@@ -331,7 +331,7 @@ struct header_def {\n \tint namelen;\n };\n \n-static void check_header(char *line, int len, struct header_def *header)\n+static void check_header(char *line, struct header_def *header)\n {\n \tint i;\n \n@@ -349,7 +349,7 @@ static void check_header(char *line, int\n \t}\n }\n \n-static void check_subheader_line(char *line, int len)\n+static void check_subheader_line(char *line)\n {\n \tstatic struct header_def header[] = {\n \t\t{ \"Content-Type\", handle_subcontent_type },\n@@ -357,9 +357,9 @@ static void check_subheader_line(char *l\n \t\t  handle_content_transfer_encoding },\n \t\t{ NULL },\n \t};\n-\tcheck_header(line, len, header);\n+\tcheck_header(line, header);\n }\n-static void check_header_line(char *line, int len)\n+static void check_header_line(char *line)\n {\n \tstatic struct header_def header[] = {\n \t\t{ \"From\", handle_from },\n@@ -370,7 +370,7 @@ static void check_header_line(char *line\n \t\t  handle_content_transfer_encoding },\n \t\t{ NULL },\n \t};\n-\tcheck_header(line, len, header);\n+\tcheck_header(line, header);\n }\n \n static int read_one_header_line(char *line, int sz, FILE *in)\n@@ -709,8 +709,8 @@ static void handle_multipart_body(void)\n \t\treturn;\n \t/* We are on boundary line.  Start slurping the subhead. */\n \twhile (1) {\n-\t\tint len = read_one_header_line(line, sizeof(line), stdin);\n-\t\tif (!len) {\n+\t\tint hdr = read_one_header_line(line, sizeof(line), stdin);\n+\t\tif (!hdr) {\n \t\t\tif (handle_multipart_one_part() < 0)\n \t\t\t\treturn;\n \t\t\t/* Reset per part headers */\n@@ -718,7 +718,7 @@ static void handle_multipart_body(void)\n \t\t\tcharset[0] = 0;\n \t\t}\n \t\telse\n-\t\t\tcheck_subheader_line(line, len);\n+\t\t\tcheck_subheader_line(line);\n \t}\n \tfclose(patchfile);\n \tif (!patch_lines) {\n@@ -787,15 +787,15 @@ int main(int argc, char **argv)\n \t\texit(1);\n \t}\n \twhile (1) {\n-\t\tint len = read_one_header_line(line, sizeof(line), stdin);\n-\t\tif (!len) {\n+\t\tint hdr = read_one_header_line(line, sizeof(line), stdin);\n+\t\tif (!hdr) {\n \t\t\tif (multipart_boundary[0])\n \t\t\t\thandle_multipart_body();\n \t\t\telse\n \t\t\t\thandle_body();\n \t\t\tbreak;\n \t\t}\n-\t\tcheck_header_line(line, len);\n+\t\tcheck_header_line(line);\n \t}\n \treturn 0;\n }\n-- \n1.3.2.g5041c-dirty\n"},{"id":"20568","messageId":"m1zmh8ikym.fsf_-_@ebiederm.dsl.xmission.com","threadId":"4267","inReplyTo":"m14pzgjzlg.fsf@ebiederm.dsl.xmission.com","subject":"[PATCH 2/6] Move B and Q decoding into check header.","fromName":"Eric W. Biederman","fromEmail":"ebiederm@xmission.com","sentAt":"2006-05-23T19:45:37Z","receivedAt":"2006-05-23T19:45:37Z","isPatch":true,"sender":{"key":"ebiederm@xmission.com","avatar":"https://avatars.githubusercontent.com/u/7477136?v=4"},"body":"\nB and Q decoding is not appropriate for in body headers, so move\nit up to where we explicitly know we have a real email header.\n\nSigned-off-by: Eric W. Biederman <ebiederm@xmission.com>\n\n\n---\n\n mailinfo.c |   12 +++++-------\n 1 files changed, 5 insertions(+), 7 deletions(-)\n\n3cccc5a0728a981cc6f4ea72e81513fd902e29a2\ndiff --git a/mailinfo.c b/mailinfo.c\nindex 83a2986..bee7b20 100644\n--- a/mailinfo.c\n+++ b/mailinfo.c\n@@ -324,6 +324,7 @@ static void cleanup_space(char *buf)\n \t}\n }\n \n+static void decode_header_bq(char *it);\n typedef int (*header_fn_t)(char *);\n struct header_def {\n \tconst char *name;\n@@ -343,6 +344,10 @@ static void check_header(char *line, str\n \t\tint len = header[i].namelen;\n \t\tif (!strncasecmp(line, header[i].name, len) &&\n \t\t    line[len] == ':' && isspace(line[len + 1])) {\n+\t\t\t/* Unwrap inline B and Q encoding, and optionally\n+\t\t\t * normalize the meta information to utf8.\n+\t\t\t */\n+\t\t\tdecode_header_bq(line + len + 2);\n \t\t\theader[i].func(line + len + 2);\n \t\t\tbreak;\n \t\t}\n@@ -597,13 +602,6 @@ static void handle_info(void)\n \tcleanup_space(email);\n \tcleanup_space(sub);\n \n-\t/* Unwrap inline B and Q encoding, and optionally\n-\t * normalize the meta information to utf8.\n-\t */\n-\tdecode_header_bq(name);\n-\tdecode_header_bq(date);\n-\tdecode_header_bq(email);\n-\tdecode_header_bq(sub);\n \tprintf(\"Author: %s\\nEmail: %s\\nSubject: %s\\nDate: %s\\n\\n\",\n \t       name, email, sub, date);\n }\n-- \n1.3.2.g5041c-dirty\n"},{"id":"20569","messageId":"m1verwikvj.fsf_-_@ebiederm.dsl.xmission.com","threadId":"4267","inReplyTo":"m1zmh8ikym.fsf_-_@ebiederm.dsl.xmission.com","subject":"[PATCH 3/6] Refactor commit messge handling.","fromName":"Eric W. Biederman","fromEmail":"ebiederm@xmission.com","sentAt":"2006-05-23T19:47:28Z","receivedAt":"2006-05-23T19:47:28Z","isPatch":true,"sender":{"key":"ebiederm@xmission.com","avatar":"https://avatars.githubusercontent.com/u/7477136?v=4"},"body":"\n- Move handle_info into main so it is called once\n  after everything has been parsed.  This allows the removal\n  of a static variable and removes two duplicate calls.\n\n- Move parsing of inbody headers into handle_commit.\n  This means we parse the in-body headers after we have decoded\n  the character set, and it removes code duplication between\n  handle_multipart_one_part and handle_body.\n\n- Change the flag indicating that we have seen an in body\n  prefix header into another bit in seen.\n  This is a little more general and allows the possibility of parsing\n  in body headers after the body message has begun.\n\nSigned-off-by: Eric W. Biederman <ebiederm@xmission.com>\n\n\n---\n\n mailinfo.c |   58 ++++++++++++++++++++++------------------------------------\n 1 files changed, 22 insertions(+), 36 deletions(-)\n\n3f6fe4d5e86c3d8d1fad75bfeb71f398966813d4\ndiff --git a/mailinfo.c b/mailinfo.c\nindex bee7b20..3fa9505 100644\n--- a/mailinfo.c\n+++ b/mailinfo.c\n@@ -237,38 +237,41 @@ static int eatspace(char *line)\n #define SEEN_FROM 01\n #define SEEN_DATE 02\n #define SEEN_SUBJECT 04\n+#define SEEN_PREFIX  0x08\n \n /* First lines of body can have From:, Date:, and Subject: */\n-static int handle_inbody_header(int *seen, char *line)\n+static void handle_inbody_header(int *seen, char *line)\n {\n+\tif (*seen & SEEN_PREFIX)\n+\t\treturn;\n \tif (!memcmp(\"From:\", line, 5) && isspace(line[5])) {\n \t\tif (!(*seen & SEEN_FROM) && handle_from(line+6)) {\n \t\t\t*seen |= SEEN_FROM;\n-\t\t\treturn 1;\n+\t\t\treturn;\n \t\t}\n \t}\n \tif (!memcmp(\"Date:\", line, 5) && isspace(line[5])) {\n \t\tif (!(*seen & SEEN_DATE)) {\n \t\t\thandle_date(line+6);\n \t\t\t*seen |= SEEN_DATE;\n-\t\t\treturn 1;\n+\t\t\treturn;\n \t\t}\n \t}\n \tif (!memcmp(\"Subject:\", line, 8) && isspace(line[8])) {\n \t\tif (!(*seen & SEEN_SUBJECT)) {\n \t\t\thandle_subject(line+9);\n \t\t\t*seen |= SEEN_SUBJECT;\n-\t\t\treturn 1;\n+\t\t\treturn;\n \t\t}\n \t}\n \tif (!memcmp(\"[PATCH]\", line, 7) && isspace(line[7])) {\n \t\tif (!(*seen & SEEN_SUBJECT)) {\n \t\t\thandle_subject(line);\n \t\t\t*seen |= SEEN_SUBJECT;\n-\t\t\treturn 1;\n+\t\t\treturn;\n \t\t}\n \t}\n-\treturn 0;\n+\t*seen |= SEEN_PREFIX;\n }\n \n static char *cleanup_subject(char *subject)\n@@ -590,12 +593,7 @@ static void decode_transfer_encoding(cha\n static void handle_info(void)\n {\n \tchar *sub;\n-\tstatic int done_info = 0;\n-\n-\tif (done_info)\n-\t\treturn;\n \n-\tdone_info = 1;\n \tsub = cleanup_subject(subject);\n \tcleanup_space(name);\n \tcleanup_space(date);\n@@ -609,7 +607,7 @@ static void handle_info(void)\n /* We are inside message body and have read line[] already.\n  * Spit out the commit log.\n  */\n-static int handle_commit_msg(void)\n+static int handle_commit_msg(int *seen)\n {\n \tif (!cmitmsg)\n \t\treturn 0;\n@@ -633,6 +631,11 @@ static int handle_commit_msg(void)\n \t\tdecode_transfer_encoding(line);\n \t\tif (metainfo_charset)\n \t\t\tconvert_to_utf8(line, charset);\n+\n+\t\thandle_inbody_header(seen, line);\n+\t\tif (!(*seen & SEEN_PREFIX))\n+\t\t\tcontinue;\n+\n \t\tfputs(line, cmitmsg);\n \t} while (fgets(line, sizeof(line), stdin) != NULL);\n \tfclose(cmitmsg);\n@@ -664,26 +667,16 @@ static void handle_patch(void)\n  * that the first part to contain commit message and a patch, and\n  * handle other parts as pure patches.\n  */\n-static int handle_multipart_one_part(void)\n+static int handle_multipart_one_part(int *seen)\n {\n-\tint seen = 0;\n \tint n = 0;\n-\tint len;\n \n \twhile (fgets(line, sizeof(line), stdin) != NULL) {\n \tagain:\n-\t\tlen = eatspace(line);\n \t\tn++;\n-\t\tif (!len)\n-\t\t\tcontinue;\n \t\tif (is_multipart_boundary(line))\n \t\t\tbreak;\n-\t\tif (0 <= seen && handle_inbody_header(&seen, line))\n-\t\t\tcontinue;\n-\t\tseen = -1; /* no more inbody headers */\n-\t\tline[len] = '\\n';\n-\t\thandle_info();\n-\t\tif (handle_commit_msg())\n+\t\tif (handle_commit_msg(seen))\n \t\t\tgoto again;\n \t\thandle_patch();\n \t\tbreak;\n@@ -695,6 +688,7 @@ static int handle_multipart_one_part(voi\n \n static void handle_multipart_body(void)\n {\n+\tint seen = 0;\n \tint part_num = 0;\n \n \t/* Skip up to the first boundary */\n@@ -709,7 +703,7 @@ static void handle_multipart_body(void)\n \twhile (1) {\n \t\tint hdr = read_one_header_line(line, sizeof(line), stdin);\n \t\tif (!hdr) {\n-\t\t\tif (handle_multipart_one_part() < 0)\n+\t\t\tif (handle_multipart_one_part(&seen) < 0)\n \t\t\t\treturn;\n \t\t\t/* Reset per part headers */\n \t\t\ttransfer_encoding = TE_DONTCARE;\n@@ -730,18 +724,9 @@ static void handle_body(void)\n {\n \tint seen = 0;\n \n-\twhile (fgets(line, sizeof(line), stdin) != NULL) {\n-\t\tint len = eatspace(line);\n-\t\tif (!len)\n-\t\t\tcontinue;\n-\t\tif (0 <= seen && handle_inbody_header(&seen, line))\n-\t\t\tcontinue;\n-\t\tseen = -1; /* no more inbody headers */\n-\t\tline[len] = '\\n';\n-\t\thandle_info();\n-\t\thandle_commit_msg();\n+\tif (fgets(line, sizeof(line), stdin) != NULL) {\n+\t\thandle_commit_msg(&seen);\n \t\thandle_patch();\n-\t\tbreak;\n \t}\n \tfclose(patchfile);\n \tif (!patch_lines) {\n@@ -791,6 +776,7 @@ int main(int argc, char **argv)\n \t\t\t\thandle_multipart_body();\n \t\t\telse\n \t\t\t\thandle_body();\n+\t\t\thandle_info();\n \t\t\tbreak;\n \t\t}\n \t\tcheck_header_line(line);\n-- \n1.3.2.g5041c-dirty\n"},{"id":"20570","messageId":"m1r72kiksz.fsf_-_@ebiederm.dsl.xmission.com","threadId":"4267","inReplyTo":"m1verwikvj.fsf_-_@ebiederm.dsl.xmission.com","subject":"[PATCH 4/6] In handle_body only read a line if we don't already have one.","fromName":"Eric W. Biederman","fromEmail":"ebiederm@xmission.com","sentAt":"2006-05-23T19:49:00Z","receivedAt":"2006-05-23T19:49:00Z","isPatch":true,"sender":{"key":"ebiederm@xmission.com","avatar":"https://avatars.githubusercontent.com/u/7477136?v=4"},"body":"\nThis prepares for detecting non-email patches that don't have\nmail headers.  In which case we have already read the first\nline so handle_body should not ignore it.\n\nSigned-off-by: Eric W. Biederman <ebiederm@xmission.com>\n\n\n---\n\n mailinfo.c |    2 +-\n 1 files changed, 1 insertions(+), 1 deletions(-)\n\n3ad0c255a351d771c7f301d4a4e9bfb6fdcbde5f\ndiff --git a/mailinfo.c b/mailinfo.c\nindex 3fa9505..99989c2 100644\n--- a/mailinfo.c\n+++ b/mailinfo.c\n@@ -724,7 +724,7 @@ static void handle_body(void)\n {\n \tint seen = 0;\n \n-\tif (fgets(line, sizeof(line), stdin) != NULL) {\n+\tif (line[0] || fgets(line, sizeof(line), stdin) != NULL) {\n \t\thandle_commit_msg(&seen);\n \t\thandle_patch();\n \t}\n-- \n1.3.2.g5041c-dirty\n"},{"id":"20571","messageId":"m1mzd8iklr.fsf_-_@ebiederm.dsl.xmission.com","threadId":"4267","inReplyTo":"m1r72kiksz.fsf_-_@ebiederm.dsl.xmission.com","subject":"[PATCH 5/6] More accurately detect header lines in read_one_header_line","fromName":"Eric W. Biederman","fromEmail":"ebiederm@xmission.com","sentAt":"2006-05-23T19:53:20Z","receivedAt":"2006-05-23T19:53:20Z","isPatch":true,"sender":{"key":"ebiederm@xmission.com","avatar":"https://avatars.githubusercontent.com/u/7477136?v=4"},"body":"\nOnly count lines of the form '^.*: ' and '^From ' as email\nheader lines. \n\nSigned-off-by: Eric W. Biederman <ebiederm@xmission.com>\n\n\n---\n\n mailinfo.c |   25 +++++++++++++++++--------\n 1 files changed, 17 insertions(+), 8 deletions(-)\n\nb955444f0bfb4ee9a5cd31686dd7eeec0750e235\ndiff --git a/mailinfo.c b/mailinfo.c\nindex 99989c2..c642ff4 100644\n--- a/mailinfo.c\n+++ b/mailinfo.c\n@@ -385,20 +385,29 @@ static int read_one_header_line(char *li\n {\n \tint ofs = 0;\n \twhile (ofs < sz) {\n+\t\tconst char *colon;\n \t\tint peek, len;\n \t\tif (fgets(line + ofs, sz - ofs, in) == NULL)\n-\t\t\treturn ofs;\n+\t\t\tbreak;\n \t\tlen = eatspace(line + ofs);\n \t\tif (len == 0)\n-\t\t\treturn ofs;\n-\t\tpeek = fgetc(in); ungetc(peek, in);\n-\t\tif (peek == ' ' || peek == '\\t') {\n-\t\t\t/* Yuck, 2822 header \"folding\" */\n-\t\t\tofs += len;\n-\t\t\tcontinue;\n+\t\t\tbreak;\n+\t\tcolon = strchr(line, ':');\n+\t\tif (!colon || !isspace(colon[1])) {\n+\t\t\t/* Readd the newline */\n+\t\t\tline[ofs + len] = '\\n';\n+\t\t\tline[ofs + len + 1] = '\\0';\n+\t\t\tbreak;\n \t\t}\n-\t\treturn ofs + len;\n+\t\tofs += len;\n+\t\t/* Yuck, 2822 header \"folding\" */\n+\t\tpeek = fgetc(in); ungetc(peek, in);\n+\t\tif (peek != ' ' && peek != '\\t')\n+\t\t\tbreak;\n \t}\n+\t/* Count mbox From headers as headers */\n+\tif (!ofs && !memcmp(line, \"From \", 5))\n+\t\tofs = 1;\n \treturn ofs;\n }\n \n-- \n1.3.2.g5041c-dirty\n"},{"id":"20572","messageId":"m1irnwikcz.fsf_-_@ebiederm.dsl.xmission.com","threadId":"4267","inReplyTo":"m1mzd8iklr.fsf_-_@ebiederm.dsl.xmission.com","subject":"[PATCH 6/6] Allow in body headers beyond the in body header prefix.","fromName":"Eric W. Biederman","fromEmail":"ebiederm@xmission.com","sentAt":"2006-05-23T19:58:36Z","receivedAt":"2006-05-23T19:58:36Z","isPatch":true,"sender":{"key":"ebiederm@xmission.com","avatar":"https://avatars.githubusercontent.com/u/7477136?v=4"},"body":"\n- handle_from is fixed to not mangle it's input line.\n\n- Then handle_inbody_header is allowed to look in\n  the body of a commit message for additional headers\n  that we haven't already seen.\n\nThis allows patches with all of the right information in\nunfortunate places to be imported.\n\nSigned-off-by: Eric W. Biederman <ebiederm@xmission.com>\n\n\n---\n\n mailinfo.c |    9 +++++----\n 1 files changed, 5 insertions(+), 4 deletions(-)\n\neca59d2fd60af47170cdbfdebf3384465f0e7635\ndiff --git a/mailinfo.c b/mailinfo.c\nindex c642ff4..99374b3 100644\n--- a/mailinfo.c\n+++ b/mailinfo.c\n@@ -72,11 +72,14 @@ static int bogus_from(char *line)\n \treturn 1;\n }\n \n-static int handle_from(char *line)\n+static int handle_from(char *in_line)\n {\n-\tchar *at = strchr(line, '@');\n+\tchar line[1000];\n+\tchar *at;\n \tchar *dst;\n \n+\tstrcpy(line, in_line);\n+\tat = strchr(line, '@');\n \tif (!at)\n \t\treturn bogus_from(line);\n \n@@ -242,8 +245,6 @@ #define SEEN_PREFIX  0x08\n /* First lines of body can have From:, Date:, and Subject: */\n static void handle_inbody_header(int *seen, char *line)\n {\n-\tif (*seen & SEEN_PREFIX)\n-\t\treturn;\n \tif (!memcmp(\"From:\", line, 5) && isspace(line[5])) {\n \t\tif (!(*seen & SEEN_FROM) && handle_from(line+6)) {\n \t\t\t*seen |= SEEN_FROM;\n-- \n1.3.2.g5041c-dirty\n"},{"id":"20592","messageId":"7vlkss1f32.fsf@assigned-by-dhcp.cox.net","threadId":"4267","inReplyTo":"m18xosjznu.fsf@ebiederm.dsl.xmission.com","subject":"Re: [PATCH 0/6] Detect non email patches in git-mailinfo","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-05-23T23:44:33Z","receivedAt":"2006-05-23T23:44:33Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Thanks.  Merged to \"next\", this probably would graduate to\n\"master\" by the end of the week if not earlier.\n"},{"id":"20743","messageId":"7vy7wpnt0t.fsf@assigned-by-dhcp.cox.net","threadId":"4267","inReplyTo":"m1mzd8iklr.fsf_-_@ebiederm.dsl.xmission.com","subject":"Re: [PATCH 5/6] More accurately detect header lines in read_one_header_line","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-05-26T07:29:22Z","receivedAt":"2006-05-26T07:29:22Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"ebiederm@xmission.com (Eric W. Biederman) writes:\n\n> Only count lines of the form '^.*: ' and '^From ' as email\n> header lines. \n\nI am having trouble with this patch.\n\n> diff --git a/mailinfo.c b/mailinfo.c\n> index 99989c2..c642ff4 100644\n> --- a/mailinfo.c\n> +++ b/mailinfo.c\n> @@ -385,20 +385,29 @@ static int read_one_header_line(char *li\n>  {\n>  \tint ofs = 0;\n>  \twhile (ofs < sz) {\n> +\t\tconst char *colon;\n>  \t\tint peek, len;\n>  \t\tif (fgets(line + ofs, sz - ofs, in) == NULL)\n> +\t\t\tbreak;\n>  \t\tlen = eatspace(line + ofs);\n>  \t\tif (len == 0)\n> +\t\t\tbreak;\n> +\t\tcolon = strchr(line, ':');\n> +\t\tif (!colon || !isspace(colon[1])) {\n> +\t\t\t/* Readd the newline */\n> +\t\t\tline[ofs + len] = '\\n';\n> +\t\t\tline[ofs + len + 1] = '\\0';\n> +\t\t\tbreak;\n>  \t\t}\n\nBecause eatspace() eats the trailing space, although your commit\nmessage say lines matching \"^.*: \" are headers, this does not\nmatch the criteria:\n\n        X-Spam-Checker-Version: SpamAssassin 3.1.1 (2006-03-10) on \n                gitster.siamese.dyndns.org\n->      X-Spam-Level: \n        X-Spam-Status: No, score=-2.6 required=5.0 tests=BAYES_00\n        \tautolearn=ham version=3.1.1\n\nNotice that the field body for this unstructured header\nX-Spam-Level (an optional field) consists of a single\nwhitespace.  It will be gone because of eatspace() when your\ncheck sees the line, so the header parsing stops prematurely.\n\nWas there a particular reason you needed this change?  That is,\ndid you have to parse mail-looking input that does not have a\nblank line between runs of headers and the body of the message?\n\nIf so, I'd at least like to remove the || !isspace(colon[1])\nfrom the test.  After all, I do not think RFC2822 requires a\nwhitespace after the colon there.\n"},{"id":"20744","messageId":"m1d5e1ciav.fsf@ebiederm.dsl.xmission.com","threadId":"4267","inReplyTo":"7vr72hns7h.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH 5/6] More accurately detect header lines in read_one_header_line","fromName":"Eric W. Biederman","fromEmail":"ebiederm@xmission.com","sentAt":"2006-05-26T08:16:24Z","receivedAt":"2006-05-26T08:16:24Z","isPatch":true,"sender":{"key":"ebiederm@xmission.com","avatar":"https://avatars.githubusercontent.com/u/7477136?v=4"},"body":"Junio C Hamano <junkio@cox.net> writes:\n\n> Junio C Hamano <junkio@cox.net> writes:\n>\n>> Was there a particular reason you needed this change?  That is,\n>> did you have to parse mail-looking input that does not have a\n>> blank line between runs of headers and the body of the message?\n\nYes.  I had patches that had a subject line followed by a blank line,\nand the problem was that the old check thought the subject was a\nheader line, despite not even having a colon in it.\n\n>> If so, I'd at least like to remove the || !isspace(colon[1])\n>> from the test.  After all, I do not think RFC2822 requires a\n>> whitespace after the colon there.\n>\n> In other words, something like this (tested):\n\nLooks good to me, sorry for missing that one.\n\nEric\n"}]}