{"thread":{"id":"7217","subject":"[PATCH 0/5] git-mailinfo fixes/features","startedAt":"2007-03-12T19:52:03Z","lastAt":"2007-03-13T02:34:16Z","messageCount":9,"participants":["Don Zickus","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":5},"messages":[{"id":"36950","messageId":"11737291282223-git-send-email-dzickus@redhat.com","threadId":"7217","inReplyTo":null,"subject":"[PATCH 0/5] git-mailinfo fixes/features","fromName":"Don Zickus","fromEmail":"dzickus@redhat.com","sentAt":"2007-03-12T19:52:03Z","receivedAt":"2007-03-12T19:52:03Z","isPatch":true,"sender":{"key":"dzickus@redhat.com","avatar":null},"body":"\nI am trying to get my own custom git-am to parse non-patches from my Inbox\nbetter.  Using git-mailinfo had a lot of limitations.  I rewrote and\nrestructured builtin-mailinfo.c to handle what I want to do better.  \n\nIn addition to a lot of fixes, I am looking to add a few small backwards\ncompatible features.  The following patches accomplish that.\n\nThis is an update to my previous set of patches.  These new fixes deal with\nsome of the issues Junio and Linus brought up.\n\nAny feedback would be great.\n\nCheers,\nDon\n"},{"id":"36951","messageId":"11737291282175-git-send-email-dzickus@redhat.com","threadId":"7217","inReplyTo":"11737291282223-git-send-email-dzickus@redhat.com","subject":"[PATCH 1/5] builtin-mailinfo.c infrastrcture changes","fromName":"Don Zickus","fromEmail":"dzickus@redhat.com","sentAt":"2007-03-12T19:52:04Z","receivedAt":"2007-03-12T19:52:04Z","isPatch":true,"sender":{"key":"dzickus@redhat.com","avatar":null},"body":"I am working on a project that required parsing through regular mboxes that\ndidn't necessarily have patches embedded in them.  I started by creating my\nown modified copy of git-am and working from there.  Very quickly, I noticed\ngit-mailinfo wasn't able to handle a big chunk of my email.\n\nAfter hacking up numerous solutions and running into more limitations, I\ndecided it was just easier to rewrite a big chunk of it.  The following\npatch has a bunch of fixes and features that I needed in order for me do\nwhat I wanted.\n\nNote: I'm didn't follow any email rfc papers but I don't think any of the\nchanges I did required much knowledge (besides the boundary stuff).\n\nList of major changes/fixes:\n- can't create empty patch files fix\n- empty patch files don't fail, this failure will come inside git-am\n- multipart boundaries are now handled\n- only output inbody headers if a patch exists otherwise assume those\nheaders are part of the reply and instead output the original headers\n- decode and filter base64 patches correctly\n- various other accidental fixes\n\nI believe I didn't break any existing functionality or compatibility (other\nthan what I describe above, which is really only the empty patch file).\n\nI tested this through various mailing list archives and everything seemed to\nparse correctly (a couple thousand emails).\n\nSigned-off-by: Don Zickus <dzickus@redhat.com>\n---\n builtin-mailinfo.c |  520 +++++++++++++++++++++++++++------------------------\n git-am.sh          |    4 +\n git-applymbox.sh   |    4 +\n git-quiltimport.sh |    4 +\n 4 files changed, 287 insertions(+), 245 deletions(-)\n\ndiff --git a/builtin-mailinfo.c b/builtin-mailinfo.c\nindex 766a37e..dacdf77 100644\n--- a/builtin-mailinfo.c\n+++ b/builtin-mailinfo.c\n@@ -11,19 +11,22 @@ static FILE *cmitmsg, *patchfile, *fin, *fout;\n static int keep_subject;\n static const char *metainfo_charset;\n static char line[1000];\n-static char date[1000];\n static char name[1000];\n static char email[1000];\n-static char subject[1000];\n \n static enum  {\n \tTE_DONTCARE, TE_QP, TE_BASE64,\n } transfer_encoding;\n-static char charset[256];\n+static enum  {\n+\tTYPE_TEXT, TYPE_OTHER,\n+} message_type;\n \n-static char multipart_boundary[1000];\n-static int multipart_boundary_len;\n+static char charset[256];\n static int patch_lines;\n+static char **p_hdr_data, **s_hdr_data;\n+\n+#define MAX_HDR_PARSED 10\n+#define MAX_BOUNDARIES 5\n \n static char *sanity_check(char *name, char *email)\n {\n@@ -137,15 +140,13 @@ static int handle_from(char *in_line)\n \treturn 1;\n }\n \n-static int handle_date(char *line)\n+static int handle_header(char *line, char *data, int ofs)\n {\n-\tstrcpy(date, line);\n-\treturn 0;\n-}\n+\tif (!line || !data)\n+\t\treturn 1;\n+\n+\tstrcpy(data, line+ofs);\n \n-static int handle_subject(char *line)\n-{\n-\tstrcpy(subject, line);\n \treturn 0;\n }\n \n@@ -177,17 +178,35 @@ static int slurp_attr(const char *line, const char *name, char *attr)\n \treturn 1;\n }\n \n-static int handle_subcontent_type(char *line)\n+struct content_type {\n+\tchar *boundary;\n+\tint boundary_len;\n+};\n+\n+static struct content_type content[MAX_BOUNDARIES];\n+\n+static struct content_type *content_top = content;\n+\n+static int handle_content_type(char *line)\n {\n-\t/* We do not want to mess with boundary.  Note that we do not\n-\t * handle nested multipart.\n+\tchar boundary[256];\n+\n+\t/* the only time this return less than zero is when \n+\t   /line/ does not contain \"text/\"\n \t */\n-\tif (strcasestr(line, \"boundary=\")) {\n-\t\tfprintf(stderr, \"Not handling nested multipart message.\\n\");\n-\t\texit(1);\n+\tif (strcasestr(line, \"text/\") == NULL)\n+\t\t message_type = TYPE_OTHER;\n+\tif (slurp_attr(line, \"boundary=\", boundary + 2)) {\n+\t\tmemcpy(boundary, \"--\", 2);\n+\t\tif (content_top++ >= &content[MAX_BOUNDARIES]) {\n+\t\t\tfprintf(stderr, \"Too many boundaries to handle\\n\");\n+\t\t\texit(1);\n+\t\t}\n+\t\tcontent_top->boundary_len = strlen(boundary);\n+\t\tcontent_top->boundary = xmalloc(content_top->boundary_len+1);\n+\t\tstrcpy(content_top->boundary, boundary);\n \t}\n-\tslurp_attr(line, \"charset=\", charset);\n-\tif (*charset) {\n+\tif (slurp_attr(line, \"charset=\", charset)) {\n \t\tint i, c;\n \t\tfor (i = 0; (c = charset[i]) != 0; i++)\n \t\t\tcharset[i] = tolower(c);\n@@ -195,17 +214,6 @@ static int handle_subcontent_type(char *line)\n \treturn 0;\n }\n \n-static int handle_content_type(char *line)\n-{\n-\t*multipart_boundary = 0;\n-\tif (slurp_attr(line, \"boundary=\", multipart_boundary + 2)) {\n-\t\tmemcpy(multipart_boundary, \"--\", 2);\n-\t\tmultipart_boundary_len = strlen(multipart_boundary);\n-\t}\n-\tslurp_attr(line, \"charset=\", charset);\n-\treturn 0;\n-}\n-\n static int handle_content_transfer_encoding(char *line)\n {\n \tif (strcasestr(line, \"base64\"))\n@@ -219,7 +227,7 @@ static int handle_content_transfer_encoding(char *line)\n \n static int is_multipart_boundary(const char *line)\n {\n-\treturn (!memcmp(line, multipart_boundary, multipart_boundary_len));\n+\treturn (!memcmp(line, content_top->boundary, content_top->boundary_len));\n }\n \n static int eatspace(char *line)\n@@ -230,62 +238,6 @@ static int eatspace(char *line)\n \treturn len;\n }\n \n-#define SEEN_FROM 01\n-#define SEEN_DATE 02\n-#define SEEN_SUBJECT 04\n-#define SEEN_BOGUS_UNIX_FROM 010\n-#define SEEN_PREFIX  020\n-\n-/* First lines of body can have From:, Date:, and Subject: or empty */\n-static void handle_inbody_header(int *seen, char *line)\n-{\n-\tif (*seen & SEEN_PREFIX)\n-\t\treturn;\n-\tif (isspace(*line)) {\n-\t\tchar *cp;\n-\t\tfor (cp = line + 1; *cp; cp++) {\n-\t\t\tif (!isspace(*cp))\n-\t\t\t\tbreak;\n-\t\t}\n-\t\tif (!*cp)\n-\t\t\treturn;\n-\t}\n-\tif (!memcmp(\">From\", line, 5) && isspace(line[5])) {\n-\t\tif (!(*seen & SEEN_BOGUS_UNIX_FROM)) {\n-\t\t\t*seen |= SEEN_BOGUS_UNIX_FROM;\n-\t\t\treturn;\n-\t\t}\n-\t}\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;\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;\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;\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;\n-\t\t}\n-\t}\n-\t*seen |= SEEN_PREFIX;\n-}\n-\n static char *cleanup_subject(char *subject)\n {\n \tif (keep_subject)\n@@ -341,57 +293,62 @@ static void cleanup_space(char *buf)\n }\n \n static void decode_header(char *it);\n-typedef int (*header_fn_t)(char *);\n-struct header_def {\n-\tconst char *name;\n-\theader_fn_t func;\n-\tint namelen;\n+static char *header[MAX_HDR_PARSED] = {\n+\t\"From\",\"Subject\",\"Date\",\n };\n \n-static void check_header(char *line, struct header_def *header)\n+static int check_header(char *line, char **hdr_data)\n {\n \tint i;\n \n-\tif (header[0].namelen <= 0) {\n-\t\tfor (i = 0; header[i].name; i++)\n-\t\t\theader[i].namelen = strlen(header[i].name);\n-\t}\n-\tfor (i = 0; header[i].name; i++) {\n-\t\tint len = header[i].namelen;\n-\t\tif (!strncasecmp(line, header[i].name, len) &&\n+\t/* search for the interesting parts */\n+\tfor (i = 0; header[i]; i++) {\n+\t\tint len = strlen(header[i]);\n+\t\tif (!hdr_data[i] &&\n+\t\t    !strncasecmp(line, header[i], 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(line + len + 2);\n-\t\t\theader[i].func(line + len + 2);\n-\t\t\tbreak;\n+\t\t\thdr_data[i] = xmalloc(1000 * sizeof(char));\n+\t\t\tif (! handle_header(line, hdr_data[i], len + 2)) {\n+\t\t\t\treturn 1;\n+\t\t\t}\n \t\t}\n \t}\n-}\n \n-static void check_subheader_line(char *line)\n-{\n-\tstatic struct header_def header[] = {\n-\t\t{ \"Content-Type\", handle_subcontent_type },\n-\t\t{ \"Content-Transfer-Encoding\",\n-\t\t  handle_content_transfer_encoding },\n-\t\t{ NULL },\n-\t};\n-\tcheck_header(line, header);\n-}\n-static void check_header_line(char *line)\n-{\n-\tstatic struct header_def header[] = {\n-\t\t{ \"From\", handle_from },\n-\t\t{ \"Date\", handle_date },\n-\t\t{ \"Subject\", handle_subject },\n-\t\t{ \"Content-Type\", handle_content_type },\n-\t\t{ \"Content-Transfer-Encoding\",\n-\t\t  handle_content_transfer_encoding },\n-\t\t{ NULL },\n-\t};\n-\tcheck_header(line, header);\n+\t/* Content stuff */\n+\tif (!strncasecmp(line, \"Content-Type\", 12) &&\n+\t\tline[12] == ':' && isspace(line[12 + 1])) {\n+\t\tdecode_header(line + 12 + 2);\n+\t\tif (! handle_content_type(line)) {\n+\t\t\treturn 1;\n+\t\t}\n+\t}\n+\tif (!strncasecmp(line, \"Content-Transfer-Encoding\", 25) &&\n+\t\tline[25] == ':' && isspace(line[25 + 1])) {\n+\t\tdecode_header(line + 25 + 2);\n+\t\tif (! handle_content_transfer_encoding(line)) {\n+\t\t\treturn 1;\n+\t\t}\n+\t}\n+\n+\t/* for inbody stuff */\n+\tif (!memcmp(\">From\", line, 5) && isspace(line[5]))\n+\t\treturn 1;\n+\tif (!memcmp(\"[PATCH]\", line, 7) && isspace(line[7])) {\n+\t\tfor (i=0; header[i]; i++) {\n+\t\t\tif (!memcmp(\"Subject: \", header[i], 9)) {\n+\t\t\t\tif (! handle_header(line, hdr_data[i], 0)) {\n+\t\t\t\t\treturn 1;\n+\t\t\t\t}\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\t/* no match */\n+\treturn 0;\n }\n \n static int is_rfc2822_header(char *line)\n@@ -647,147 +604,222 @@ static void decode_transfer_encoding(char *line)\n \t}\n }\n \n-static void handle_info(void)\n+static int handle_filter(char *line);\n+\n+static int find_boundary(void)\n {\n-\tchar *sub;\n+\twhile(fgets(line, sizeof(line), fin) != NULL) {\n+\t\tif (is_multipart_boundary(line))\n+\t\t\treturn 1;\n+\t}\n+\treturn 0;\n+}\n+\n+static int handle_boundary(void)\n+{\n+again:\n+\tif (!memcmp(line+content_top->boundary_len, \"--\", 2)) {\n+\t\t/* we hit an end boundary */\n+\t\t/* pop the current boundary off the stack */\n+\t\tfree(content_top->boundary);\n+\t\t\n+\t\t/* technically won't happen as is_multipart_boundary()\n+\t\t   will fail first.  But just in case..\n+\t\t */\n+\t\tif (content_top-- < content) {\n+\t\t\tfprintf(stderr, \"Detected mismatched boundaries, \"\n+\t\t\t\t\t\"can't recover\\n\");\n+\t\t\texit(1);\n+\t\t}\n+\t\thandle_filter(\"\\n\");\n+\n+\t\t/* skip to the next boundary */\n+\t\tif (!find_boundary())\n+\t\t\treturn 0;\n+\t\tgoto again;\n+\t}\n \n-\tsub = cleanup_subject(subject);\n-\tcleanup_space(name);\n-\tcleanup_space(date);\n-\tcleanup_space(email);\n-\tcleanup_space(sub);\n+\t/* set some defaults */\n+\ttransfer_encoding = TE_DONTCARE;\n+\tcharset[0] = 0;\n+\tmessage_type = TYPE_TEXT;\n \n-\tfprintf(fout, \"Author: %s\\nEmail: %s\\nSubject: %s\\nDate: %s\\n\\n\",\n-\t       name, email, sub, date);\n+\t/* slurp in this section's info */\n+\twhile (read_one_header_line(line, sizeof(line), fin))\n+\t\tcheck_header(line, p_hdr_data);\n+\n+\t/* eat the blank line after section info */\n+\treturn (fgets(line, sizeof(line), fin) != NULL);\n }\n \n-/* We are inside message body and have read line[] already.\n- * Spit out the commit log.\n- */\n-static int handle_commit_msg(int *seen)\n+static int handle_commit_msg(char *line)\n {\n+\tstatic int still_looking=1;\n+\n \tif (!cmitmsg)\n \t\treturn 0;\n-\tdo {\n-\t\tif (!memcmp(\"diff -\", line, 6) ||\n-\t\t    !memcmp(\"---\", line, 3) ||\n-\t\t    !memcmp(\"Index: \", line, 7))\n-\t\t\tbreak;\n-\t\tif ((multipart_boundary[0] && is_multipart_boundary(line))) {\n-\t\t\t/* We come here when the first part had only\n-\t\t\t * the commit message without any patch.  We\n-\t\t\t * pretend we have not seen this line yet, and\n-\t\t\t * go back to the loop.\n-\t\t\t */\n-\t\t\treturn 1;\n-\t\t}\n \n-\t\t/* Unwrap transfer encoding and optionally\n-\t\t * normalize the log message to UTF-8.\n-\t\t */\n-\t\tdecode_transfer_encoding(line);\n-\t\tif (metainfo_charset)\n-\t\t\tconvert_to_utf8(line, charset);\n+\tif (still_looking) {\n+\t\tchar *cp=line;\n+\t\tif (isspace(*line)) {\n+\t\t\tfor (cp = line + 1; *cp; cp++) {\n+\t\t\t\tif (!isspace(*cp))\n+\t\t\t\t\tbreak;\n+\t\t\t}\n+\t\t\tif (!*cp)\n+\t\t\t\treturn 0;\n+\t\t}\n+\t\tif ((still_looking = check_header(cp, s_hdr_data)) != 0)\n+\t\t\treturn 0;\n+\t}\n \n-\t\thandle_inbody_header(seen, line);\n-\t\tif (!(*seen & SEEN_PREFIX))\n-\t\t\tcontinue;\n+\tif (!memcmp(\"diff -\", line, 6) ||\n+\t    !memcmp(\"---\", line, 3) ||\n+\t    !memcmp(\"Index: \", line, 7)) {\n+\t\tfclose(cmitmsg);\n+\t\tcmitmsg = NULL;\n+\t\treturn 1;\n+\t}\n \n-\t\tfputs(line, cmitmsg);\n-\t} while (fgets(line, sizeof(line), fin) != NULL);\n-\tfclose(cmitmsg);\n-\tcmitmsg = NULL;\n+\tfputs(line, cmitmsg);\n \treturn 0;\n }\n \n-/* We have done the commit message and have the first\n- * line of the patch in line[].\n- */\n-static void handle_patch(void)\n+static int handle_patch(char *line)\n {\n-\tdo {\n-\t\tif (multipart_boundary[0] && is_multipart_boundary(line))\n-\t\t\tbreak;\n-\t\t/* Only unwrap transfer encoding but otherwise do not\n-\t\t * do anything.  We do *NOT* want UTF-8 conversion\n-\t\t * here; we are dealing with the user payload.\n-\t\t */\n-\t\tdecode_transfer_encoding(line);\n-\t\tfputs(line, patchfile);\n-\t\tpatch_lines++;\n-\t} while (fgets(line, sizeof(line), fin) != NULL);\n+\tfputs(line, patchfile);\n+\tpatch_lines++;\n+\treturn 0;\n }\n \n-/* multipart boundary and transfer encoding are set up for us, and we\n- * are at the end of the sub header.  do equivalent of handle_body up\n- * to the next boundary without closing patchfile --- we will expect\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(int *seen)\n+static int handle_filter(char *line)\n {\n-\tint n = 0;\n+\tstatic int filter=0;\n \n-\twhile (fgets(line, sizeof(line), fin) != NULL) {\n-\tagain:\n-\t\tn++;\n-\t\tif (is_multipart_boundary(line))\n+\t/* filter tells us which part we left off on\n+\t * a non-zero return indicates we hit a filter point\n+\t */\n+\tswitch (filter) {\n+\tcase 0:\n+\t\tif (!handle_commit_msg(line))\n \t\t\tbreak;\n-\t\tif (handle_commit_msg(seen))\n-\t\t\tgoto again;\n-\t\thandle_patch();\n-\t\tbreak;\n+\t\tfilter++;\n+\tcase 1:\n+\t\tif (!handle_patch(line))\n+\t\t\tbreak;\n+\t\tfilter++;\n+\tdefault:\n+\t\treturn 1;\n \t}\n-\tif (n == 0)\n-\t\treturn -1;\n+\n \treturn 0;\n }\n \n-static void handle_multipart_body(void)\n+static void handle_body(void)\n {\n-\tint seen = 0;\n-\tint part_num = 0;\n+\tint rc=0;\n+\tstatic char newline[2000];\n+\tstatic char *np=newline;\n \n \t/* Skip up to the first boundary */\n-\twhile (fgets(line, sizeof(line), fin) != NULL)\n-\t\tif (is_multipart_boundary(line)) {\n-\t\t\tpart_num = 1;\n+\tif (content_top->boundary) {\n+\t\tif (!find_boundary())\n+\t\t\treturn;\n+\t}\n+\n+\tdo {\n+\t\t/* process any boundary lines */\n+\t\tif (content_top->boundary && is_multipart_boundary(line)) {\n+\t\t\t/* flush any leftover */\n+\t\t\tif ((transfer_encoding == TE_BASE64)  &&\n+\t\t\t    (np != newline)) {\n+\t\t\t\thandle_filter(newline);\n+\t\t\t}\n+\t\t\tif (!handle_boundary())\n+\t\t\t\treturn;\n+\t\t}\n+\n+\t\t/* Unwrap transfer encoding and optionally\n+\t\t * normalize the log message to UTF-8.\n+\t\t */\n+\t\tdecode_transfer_encoding(line);\n+\t\tif (metainfo_charset)\n+\t\t\tconvert_to_utf8(line, charset);\n+\n+\t\tswitch (transfer_encoding) {\n+\t\tcase TE_BASE64:\n+\t\t{\n+\t\t\tchar *op=line;\n+\n+\t\t\t/* binary data most likely doesn't have newlines */\n+\t\t\tif (message_type != TYPE_TEXT) {\n+\t\t\t\trc=handle_filter(line);\n+\t\t\t\tbreak;\n+\t\t\t}\n+\n+\t\t\t/* this is a decoded line that may contain\n+\t\t\t * multiple new lines.  Pass only one chunk\n+\t\t\t * at a time to handle_filter()\n+\t\t\t */\n+\n+\t\t\tdo {\n+\t\t\t\twhile (*op != '\\n' && *op != 0)\n+\t\t\t\t\t*np++ = *op++;\n+\t\t\t\t*np = *op;\n+\t\t\t\tif (*np != 0) {\n+\t\t\t\t\t/* should be sitting on a new line */\n+\t\t\t\t\t*(++np) = 0;\n+\t\t\t\t\top++;\n+\t\t\t\t\trc=handle_filter(newline);\n+\t\t\t\t\tnp=newline;\n+\t\t\t\t}\n+\t\t\t} while (*op != 0);\n+\t\t\t/* the partial chunk is saved in newline and\n+\t\t\t * will be appended by the next iteration of fgets\n+\t\t\t */\n \t\t\tbreak;\n \t\t}\n-\tif (!part_num)\n-\t\treturn;\n-\t/* We are on boundary line.  Start slurping the subhead. */\n-\twhile (1) {\n-\t\tint hdr = read_one_header_line(line, sizeof(line), fin);\n-\t\tif (!hdr) {\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-\t\t\tcharset[0] = 0;\n+\t\tdefault:\n+\t\t\trc=handle_filter(line);\n \t\t}\n-\t\telse\n-\t\t\tcheck_subheader_line(line);\n-\t}\n-\tfclose(patchfile);\n-\tif (!patch_lines) {\n-\t\tfprintf(stderr, \"No patch found\\n\");\n-\t\texit(1);\n-\t}\n+\t\tif (rc)\n+\t\t\t/* nothing left to filter */\n+\t\t\tbreak;\n+\t} while (fgets(line, sizeof(line), fin));\n+\n+\treturn;\n }\n \n-/* Non multipart message */\n-static void handle_body(void)\n+static void handle_info(void)\n {\n-\tint seen = 0;\n-\n-\thandle_commit_msg(&seen);\n-\thandle_patch();\n-\tfclose(patchfile);\n-\tif (!patch_lines) {\n-\t\tfprintf(stderr, \"No patch found\\n\");\n-\t\texit(1);\n+\tchar *sub;\n+\tchar *hdr;\n+\tint i;\n+\n+\tfor (i=0; header[i]; i++) {\n+\n+\t\t/* only print inbody headers if we output a patch file */\n+\t\tif (patch_lines && s_hdr_data[i])\n+\t\t\thdr=s_hdr_data[i];\n+\t\telse if (p_hdr_data[i])\n+\t\t\thdr=p_hdr_data[i];\n+\t\telse\n+\t\t\tcontinue;\n+\n+\t\tif (!memcmp(header[i], \"Subject\", 7)) {\n+\t\t\tsub = cleanup_subject(hdr);\n+\t\t\tcleanup_space(sub);\n+\t\t\tfprintf(fout, \"Subject: %s\\n\", sub);\n+\t\t} else if (!memcmp(header[i], \"From\", 4)) {\n+\t\t\thandle_from(hdr);\n+\t\t\tfprintf(fout, \"Author: %s\\n\", name);\n+\t\t\tfprintf(fout, \"Email: %s\\n\", email);\n+\t\t} else {\n+\t\t\tcleanup_space(hdr);\n+\t\t\tfprintf(fout, \"%s: %s\\n\", header[i], hdr);\n+\t\t}\n \t}\n+\tfprintf(fout, \"\\n\");\n }\n \n int mailinfo(FILE *in, FILE *out, int ks, const char *encoding,\n@@ -809,18 +841,16 @@ int mailinfo(FILE *in, FILE *out, int ks, const char *encoding,\n \t\tfclose(cmitmsg);\n \t\treturn -1;\n \t}\n-\twhile (1) {\n-\t\tint hdr = read_one_header_line(line, sizeof(line), fin);\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\thandle_info();\n-\t\t\tbreak;\n-\t\t}\n-\t\tcheck_header_line(line);\n-\t}\n+\n+\tp_hdr_data = xcalloc(MAX_HDR_PARSED, sizeof(char *));\n+\ts_hdr_data = xcalloc(MAX_HDR_PARSED, sizeof(char *));\n+\n+\t/* process the email header */\n+\twhile (read_one_header_line(line, sizeof(line), fin))\n+\t\tcheck_header(line, p_hdr_data);\n+\n+\thandle_body();\n+\thandle_info();\n \n \treturn 0;\n }\ndiff --git a/git-am.sh b/git-am.sh\nindex 2c73d11..847a44f 100755\n--- a/git-am.sh\n+++ b/git-am.sh\n@@ -290,6 +290,10 @@ do\n \t\tgit-mailinfo $keep $utf8 \"$dotest/msg\" \"$dotest/patch\" \\\n \t\t\t<\"$dotest/$msgnum\" >\"$dotest/info\" ||\n \t\t\tstop_here $this\n+\t\ttest -s $dotest/patch || { \n+\t\t\techo \"Patch is empty.  Was is split wrong?\"\n+\t\t\tstop_here $this\n+\t\t}\n \t\tgit-stripspace < \"$dotest/msg\" > \"$dotest/msg-clean\"\n \t\t;;\n \tesac\ndiff --git a/git-applymbox.sh b/git-applymbox.sh\nindex 1f68599..2cbdc7e 100755\n--- a/git-applymbox.sh\n+++ b/git-applymbox.sh\n@@ -77,6 +77,10 @@ do\n     *)\n \t    git-mailinfo $keep_subject $utf8 \\\n \t\t.dotest/msg .dotest/patch <$i >.dotest/info || exit 1\n+\t    test -s $dotest/patch || {\n+\t\techo \"Patch is empty.  Was is split wrong?\"\n+\t\tstop_here $this\n+\t    }\n \t    git-stripspace < .dotest/msg > .dotest/msg-clean\n \t    ;;\n     esac\ndiff --git a/git-quiltimport.sh b/git-quiltimport.sh\nindex 671a5ff..08ac9bb 100755\n--- a/git-quiltimport.sh\n+++ b/git-quiltimport.sh\n@@ -73,6 +73,10 @@ mkdir $tmp_dir || exit 2\n for patch_name in $(cat \"$QUILT_PATCHES/series\" | grep -v '^#'); do\n \techo $patch_name\n \t(cat $QUILT_PATCHES/$patch_name | git-mailinfo \"$tmp_msg\" \"$tmp_patch\" > \"$tmp_info\") || exit 3\n+\ttest -s $dotest/patch || {\n+\t\techo \"Patch is empty.  Was is split wrong?\"\n+\t\tstop_here $this\n+\t}\n \n \t# Parse the author information\n \texport GIT_AUTHOR_NAME=$(sed -ne 's/Author: //p' \"$tmp_info\")\n-- \n1.5.0.2.211.g2ca9-dirty\n"},{"id":"36953","messageId":"11737291281648-git-send-email-dzickus@redhat.com","threadId":"7217","inReplyTo":"11737291282223-git-send-email-dzickus@redhat.com","subject":"[PATCH 2/5] add the ability to select more email header fields to output","fromName":"Don Zickus","fromEmail":"dzickus@redhat.com","sentAt":"2007-03-12T19:52:05Z","receivedAt":"2007-03-12T19:52:05Z","isPatch":true,"sender":{"key":"dzickus@redhat.com","avatar":null},"body":"This is useful when scripts need more than just the basic email headers to\nparse.  By specifying the \"-x=\" option, one can search and output any header\nfield they want.\n\nSigned-off-by: Don Zickus <dzickus@redhat.com>\n---\n builtin-mailinfo.c |   10 ++++++++--\n 1 files changed, 8 insertions(+), 2 deletions(-)\n\ndiff --git a/builtin-mailinfo.c b/builtin-mailinfo.c\nindex dacdf77..dd0f563 100644\n--- a/builtin-mailinfo.c\n+++ b/builtin-mailinfo.c\n@@ -856,11 +856,12 @@ int mailinfo(FILE *in, FILE *out, int ks, const char *encoding,\n }\n \n static const char mailinfo_usage[] =\n-\t\"git-mailinfo [-k] [-u | --encoding=<encoding>] msg patch <mail >info\";\n+\t\"git-mailinfo [-k] [-u | --encoding=<encoding>] [-x=<field>] msg patch <mail >info\";\n \n int cmd_mailinfo(int argc, const char **argv, const char *prefix)\n {\n \tconst char *def_charset;\n+\tint top;\n \n \t/* NEEDSWORK: might want to do the optional .git/ directory\n \t * discovery\n@@ -870,6 +871,8 @@ int cmd_mailinfo(int argc, const char **argv, const char *prefix)\n \tdef_charset = (git_commit_encoding ? git_commit_encoding : \"utf-8\");\n \tmetainfo_charset = def_charset;\n \n+\tfor (top=0; header[top]; top++){ ; }\n+\n \twhile (1 < argc && argv[1][0] == '-') {\n \t\tif (!strcmp(argv[1], \"-k\"))\n \t\t\tkeep_subject = 1;\n@@ -879,7 +882,10 @@ int cmd_mailinfo(int argc, const char **argv, const char *prefix)\n \t\t\tmetainfo_charset = NULL;\n \t\telse if (!prefixcmp(argv[1], \"--encoding=\"))\n \t\t\tmetainfo_charset = argv[1] + 11;\n-\t\telse\n+\t\telse if (!prefixcmp(argv[1], \"-x=\")) {\n+\t\t\theader[top] = xmalloc(256*sizeof(char));\n+\t\t\tstrncpy(header[top++], argv[1]+3, 256);\n+\t\t} else\n \t\t\tusage(mailinfo_usage);\n \t\targc--; argv++;\n \t}\n-- \n1.5.0.2.211.g2ca9-dirty\n"},{"id":"36956","messageId":"1173729128920-git-send-email-dzickus@redhat.com","threadId":"7217","inReplyTo":"11737291282223-git-send-email-dzickus@redhat.com","subject":"[PATCH 3/5] restrict the patch filtering","fromName":"Don Zickus","fromEmail":"dzickus@redhat.com","sentAt":"2007-03-12T19:52:06Z","receivedAt":"2007-03-12T19:52:06Z","isPatch":true,"sender":{"key":"dzickus@redhat.com","avatar":null},"body":"I have come across many emails that use long strings of '-'s as separators\nfor ideas.  This patch below limits the separator to only 3 '-', with the\nintent that long string of '-'s will stay in the commit msg and not in the\npatch file.\n\nSigned-off-by: Don Zickus <dzickus@redhat.com>\nAcked-by: Linus Torvalds <torvalds@linux-foundation.org>\n\n---\nI purposedly separated this patch out because I wasn't sure if anyone would\nhave objections to it.  I tested it on numerous emails with and with patches\nand didn't see any issues.\n---\n builtin-mailinfo.c |   37 ++++++++++++++++++++++++++++++++++---\n 1 files changed, 34 insertions(+), 3 deletions(-)\n\ndiff --git a/builtin-mailinfo.c b/builtin-mailinfo.c\nindex dd0f563..a8d5b60 100644\n--- a/builtin-mailinfo.c\n+++ b/builtin-mailinfo.c\n@@ -652,6 +652,39 @@ again:\n \treturn (fgets(line, sizeof(line), fin) != NULL);\n }\n \n+static inline int patchbreak(const char *line)\n+{\n+\t/* Beginning of a \"diff -\" header? */\n+\tif (!memcmp(\"diff -\", line, 6))\n+\t\treturn 1;\n+\n+\t/* CVS \"Index: \" line? */\n+\tif (!memcmp(\"Index: \", line, 7))\n+\t\treturn 1;\n+\n+\t/*\n+\t * \"--- <filename>\" starts patches without headers\n+\t * \"---<sp>*\" is a manual separator\n+\t */\n+\tif (!memcmp(\"---\", line, 3)) {\n+\t\tline += 3;\n+\t\t/* space followed by a filename? */\n+\t\tif (line[0] == ' ' && !isspace(line[1]))\n+\t\t\treturn 1;\n+\t\t/* Just whitespace? */\n+\t\tfor (;;) {\n+\t\t\tunsigned char c = *line++;\n+\t\t\tif (c == '\\n')\n+\t\t\t\treturn 1;\n+\t\t\tif (!isspace(c))\n+\t\t\t\tbreak;\n+\t\t}\n+\t\treturn 0;\n+\t}\n+\treturn 0;\n+}\n+\n+\n static int handle_commit_msg(char *line)\n {\n \tstatic int still_looking=1;\n@@ -673,9 +706,7 @@ static int handle_commit_msg(char *line)\n \t\t\treturn 0;\n \t}\n \n-\tif (!memcmp(\"diff -\", line, 6) ||\n-\t    !memcmp(\"---\", line, 3) ||\n-\t    !memcmp(\"Index: \", line, 7)) {\n+\tif (patchbreak(line)) {\n \t\tfclose(cmitmsg);\n \t\tcmitmsg = NULL;\n \t\treturn 1;\n-- \n1.5.0.2.211.g2ca9-dirty\n"},{"id":"36952","messageId":"1173729128427-git-send-email-dzickus@redhat.com","threadId":"7217","inReplyTo":"11737291282223-git-send-email-dzickus@redhat.com","subject":"[PATCH 4/5] Add a couple more test cases to the suite.","fromName":"Don Zickus","fromEmail":"dzickus@redhat.com","sentAt":"2007-03-12T19:52:07Z","receivedAt":"2007-03-12T19:52:07Z","isPatch":true,"sender":{"key":"dzickus@redhat.com","avatar":null},"body":"They handle cases where there is no attached patch.\n\nSigned-off-by: Don Zickus <dzickus@redhat.com>\n---\n t/t5100-mailinfo.sh |    2 +-\n t/t5100/info0007    |    5 +++++\n t/t5100/info0008    |    5 +++++\n t/t5100/msg0007     |    2 ++\n t/t5100/msg0008     |    4 ++++\n t/t5100/sample.mbox |   18 ++++++++++++++++++\n 6 files changed, 35 insertions(+), 1 deletions(-)\n create mode 100644 t/t5100/info0007\n create mode 100644 t/t5100/info0008\n create mode 100644 t/t5100/msg0007\n create mode 100644 t/t5100/msg0008\n create mode 100644 t/t5100/patch0007\n create mode 100644 t/t5100/patch0008\n\ndiff --git a/t/t5100-mailinfo.sh b/t/t5100-mailinfo.sh\nindex 4d2b781..ca96918 100755\n--- a/t/t5100-mailinfo.sh\n+++ b/t/t5100-mailinfo.sh\n@@ -11,7 +11,7 @@ test_expect_success 'split sample box' \\\n \t'git-mailsplit -o. ../t5100/sample.mbox >last &&\n \tlast=`cat last` &&\n \techo total is $last &&\n-\ttest `cat last` = 6'\n+\ttest `cat last` = 8'\n \n for mail in `echo 00*`\n do\ndiff --git a/t/t5100/info0007 b/t/t5100/info0007\nnew file mode 100644\nindex 0000000..49bb0fe\n--- /dev/null\n+++ b/t/t5100/info0007\n@@ -0,0 +1,5 @@\n+Author: A U Thor\n+Email: a.u.thor@example.com\n+Subject: another patch\n+Date: Fri, 9 Jun 2006 00:44:16 -0700\n+\ndiff --git a/t/t5100/info0008 b/t/t5100/info0008\nnew file mode 100644\nindex 0000000..e8a2951\n--- /dev/null\n+++ b/t/t5100/info0008\n@@ -0,0 +1,5 @@\n+Author: Junio C Hamano\n+Email: junio@kernel.org\n+Subject: another patch\n+Date: Fri, 9 Jun 2006 00:44:16 -0700\n+\ndiff --git a/t/t5100/msg0007 b/t/t5100/msg0007\nnew file mode 100644\nindex 0000000..71b23c0\n--- /dev/null\n+++ b/t/t5100/msg0007\n@@ -0,0 +1,2 @@\n+Here is an empty patch from A U Thor.\n+\ndiff --git a/t/t5100/msg0008 b/t/t5100/msg0008\nnew file mode 100644\nindex 0000000..a80ecb9\n--- /dev/null\n+++ b/t/t5100/msg0008\n@@ -0,0 +1,4 @@\n+>Here is an empty patch from A U Thor.\n+\n+Hey you forgot the patch!\n+\ndiff --git a/t/t5100/patch0007 b/t/t5100/patch0007\nnew file mode 100644\nindex 0000000..e69de29\ndiff --git a/t/t5100/patch0008 b/t/t5100/patch0008\nnew file mode 100644\nindex 0000000..e69de29\ndiff --git a/t/t5100/sample.mbox b/t/t5100/sample.mbox\nindex 86bfc27..b80c981 100644\n--- a/t/t5100/sample.mbox\n+++ b/t/t5100/sample.mbox\n@@ -386,3 +386,21 @@ index 9123cdc..918dcf8 100644\n -- \n 1.4.0.g6f2b\n \n+From nobody Mon Sep 17 00:00:00 2001\n+From: A U Thor <a.u.thor@example.com>\n+Date: Fri, 9 Jun 2006 00:44:16 -0700\n+Subject: [PATCH] another patch\n+\n+Here is an empty patch from A U Thor.\n+\n+From nobody Mon Sep 17 00:00:00 2001\n+From: Junio C Hamano <junio@kernel.org>\n+Date: Fri, 9 Jun 2006 00:44:16 -0700\n+Subject: re: [PATCH] another patch\n+\n+From: A U Thor <a.u.thor@example.com>\n+Subject: [PATCH] another patch\n+>Here is an empty patch from A U Thor.\n+\n+Hey you forgot the patch!\n+\n-- \n1.5.0.2.211.g2ca9-dirty\n"},{"id":"36954","messageId":"11737291281424-git-send-email-dzickus@redhat.com","threadId":"7217","inReplyTo":"11737291282223-git-send-email-dzickus@redhat.com","subject":"[PATCH 5/5] fix a utf8 issue in t5100/patch005","fromName":"Don Zickus","fromEmail":"dzickus@redhat.com","sentAt":"2007-03-12T19:52:08Z","receivedAt":"2007-03-12T19:52:08Z","isPatch":true,"sender":{"key":"dzickus@redhat.com","avatar":null},"body":"This issue popped up when testing my changes.  I believe the patch is the\nintended output that git-mailinfo should provide.\n\nSigned-off-by: Don Zickus <dzickus@redhat.com>\n---\n t/t5100/patch0005 |    2 +-\n 1 files changed, 1 insertions(+), 1 deletions(-)\n\ndiff --git a/t/t5100/patch0005 b/t/t5100/patch0005\nindex 7d24b24..e7d6f66 100644\n--- a/t/t5100/patch0005\n+++ b/t/t5100/patch0005\n@@ -61,7 +61,7 @@ diff --git a/git-cvsimport-script b/git-cvsimport-script\n  \t\tpush(@old,$fn);\n \n -- \n-David Kågedal\n+David KÃ¥gedal\n -\n To unsubscribe from this list: send the line \"unsubscribe git\" in\n the body of a message to majordomo@vger.kernel.org\n-- \n1.5.0.2.211.g2ca9-dirty\n"},{"id":"36980","messageId":"7vveh6nes9.fsf@assigned-by-dhcp.cox.net","threadId":"7217","inReplyTo":"11737291281648-git-send-email-dzickus@redhat.com","subject":"Re: [PATCH 2/5] add the ability to select more email header fields to output","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2007-03-13T00:55:02Z","receivedAt":"2007-03-13T00:55:02Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Don Zickus <dzickus@redhat.com> writes:\n\n> This is useful when scripts need more than just the basic email headers to\n> parse.  By specifying the \"-x=\" option, one can search and output any header\n> field they want.\n\nIt probably is useful, but that is rather difficult to judge,\nunless you have a specific use in the scripts (am/applymox).\n\n> @@ -870,6 +871,8 @@ int cmd_mailinfo(int argc, const char **argv, const char *prefix)\n>  \tdef_charset = (git_commit_encoding ? git_commit_encoding : \"utf-8\");\n>  \tmetainfo_charset = def_charset;\n>  \n> +\tfor (top=0; header[top]; top++){ ; }\n> +\n>  \twhile (1 < argc && argv[1][0] == '-') {\n>  \t\tif (!strcmp(argv[1], \"-k\"))\n>  \t\t\tkeep_subject = 1;\n> @@ -879,7 +882,10 @@ int cmd_mailinfo(int argc, const char **argv, const char *prefix)\n>  \t\t\tmetainfo_charset = NULL;\n>  \t\telse if (!prefixcmp(argv[1], \"--encoding=\"))\n>  \t\t\tmetainfo_charset = argv[1] + 11;\n> -\t\telse\n> +\t\telse if (!prefixcmp(argv[1], \"-x=\")) {\n> +\t\t\theader[top] = xmalloc(256*sizeof(char));\n> +\t\t\tstrncpy(header[top++], argv[1]+3, 256);\n\nReturn \"-ETOOMANYEXTRAHEADERSHEADERS\" when top overflows,\nperhaps?\n\nYou seem to omit SP around '=' in initializers (the first part\nof for loop and \"typename var=init\" at the beginning of block)\nbut not in an assignment expression used as a freestanding\nstatement.  Is this recommended by some coding style I am not\naware of, or it it just your habit?  It is somewhat irritating\nto my eyes, although they might be syntactically different class\nand you might be using one from the other consistently (but in\n[1/5] some SP around '=' in assignments are omitted, and there\ndoes not seem to be any such consistency).\n\nAnd a micronit on [1/5] in the series.  I do not think \"less\nthan zero\" comment applies to what is being done, and I do not\nthink it needs to be explained what the code is doing by\nchecking return value from strcasestr() with NULL.\n\n+\tchar boundary[256];\n+\n+\t/* the only time this return less than zero is when \n+\t   /line/ does not contain \"text/\"\n \t */\n-\tif (strcasestr(line, \"boundary=\")) {\n-\t\tfprintf(stderr, \"Not handling nested multipart message.\\n\");\n-\t\texit(1);\n+\tif (strcasestr(line, \"text/\") == NULL)\n+\t\t message_type = TYPE_OTHER;\n\nI think 3, 4, and 5 are good changes too.  Will apply with the\nabovementioned micronit fixups and let's cook them in 'next'.\n"},{"id":"36983","messageId":"68948ca0703121821h72f6c08ak9f38cae40240ac59@mail.gmail.com","threadId":"7217","inReplyTo":"7vveh6nes9.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH 2/5] add the ability to select more email header fields to output","fromName":"Don Zickus","fromEmail":"dzickus@gmail.com","sentAt":"2007-03-13T01:21:25Z","receivedAt":"2007-03-13T01:21:25Z","isPatch":true,"sender":{"key":"dzickus@gmail.com","avatar":"https://gravatar.com/avatar/fbc96d0d5584c05dec11867b861650fe9f5d7d0ddec2655a1f90542fe07d9769?d=mp&s=160"},"body":"On 3/12/07, Junio C Hamano <junkio@cox.net> wrote:\n> Don Zickus <dzickus@redhat.com> writes:\n>\n> > This is useful when scripts need more than just the basic email headers to\n> > parse.  By specifying the \"-x=\" option, one can search and output any header\n> > field they want.\n>\n> It probably is useful, but that is rather difficult to judge,\n> unless you have a specific use in the scripts (am/applymox).\n\nI have my own custom clone of git-am I am using to extract the\nMessage-id, In-Reply-To, and References fields.  For awhile I had the\nfields hardcoded in my version of git-mailinfo.  But instead of\nmaintaining it, I was hoping I could push it upstream.  One less thing\nto maintain on my own.  :-)\n\n>\n> > @@ -870,6 +871,8 @@ int cmd_mailinfo(int argc, const char **argv, const char *prefix)\n> >       def_charset = (git_commit_encoding ? git_commit_encoding : \"utf-8\");\n> >       metainfo_charset = def_charset;\n> >\n> > +     for (top=0; header[top]; top++){ ; }\n> > +\n> >       while (1 < argc && argv[1][0] == '-') {\n> >               if (!strcmp(argv[1], \"-k\"))\n> >                       keep_subject = 1;\n> > @@ -879,7 +882,10 @@ int cmd_mailinfo(int argc, const char **argv, const char *prefix)\n> >                       metainfo_charset = NULL;\n> >               else if (!prefixcmp(argv[1], \"--encoding=\"))\n> >                       metainfo_charset = argv[1] + 11;\n> > -             else\n> > +             else if (!prefixcmp(argv[1], \"-x=\")) {\n> > +                     header[top] = xmalloc(256*sizeof(char));\n> > +                     strncpy(header[top++], argv[1]+3, 256);\n>\n> Return \"-ETOOMANYEXTRAHEADERSHEADERS\" when top overflows,\n> perhaps?\n\nyup.  i'll fix that.\n\n>\n> You seem to omit SP around '=' in initializers (the first part\n> of for loop and \"typename var=init\" at the beginning of block)\n> but not in an assignment expression used as a freestanding\n> statement.  Is this recommended by some coding style I am not\n> aware of, or it it just your habit?  It is somewhat irritating\n\nmainly habit.  I don't have a preference.  I'll clean up what I find and repost.\n\n> to my eyes, although they might be syntactically different class\n> and you might be using one from the other consistently (but in\n> [1/5] some SP around '=' in assignments are omitted, and there\n> does not seem to be any such consistency).\n>\n> And a micronit on [1/5] in the series.  I do not think \"less\n> than zero\" comment applies to what is being done, and I do not\n> think it needs to be explained what the code is doing by\n> checking return value from strcasestr() with NULL.\n>\n> +       char boundary[256];\n> +\n> +       /* the only time this return less than zero is when\n> +          /line/ does not contain \"text/\"\n>          */\n> -       if (strcasestr(line, \"boundary=\")) {\n> -               fprintf(stderr, \"Not handling nested multipart message.\\n\");\n> -               exit(1);\n> +       if (strcasestr(line, \"text/\") == NULL)\n> +                message_type = TYPE_OTHER;\n>\n\noops.  left over comment from old code.  I'll clean that up.\n\nCheers,\nDon\n"},{"id":"36984","messageId":"7vodmxoorb.fsf@assigned-by-dhcp.cox.net","threadId":"7217","inReplyTo":"68948ca0703121821h72f6c08ak9f38cae40240ac59@mail.gmail.com","subject":"Re: [PATCH 2/5] add the ability to select more email header fields to output","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2007-03-13T02:34:16Z","receivedAt":"2007-03-13T02:34:16Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Don Zickus\" <dzickus@gmail.com> writes:\n\n> On 3/12/07, Junio C Hamano <junkio@cox.net> wrote:\n>> Don Zickus <dzickus@redhat.com> writes:\n>>\n>> > This is useful when scripts need more than just the basic email headers to\n>> > parse.  By specifying the \"-x=\" option, one can search and output any header\n>> > field they want.\n>>\n>> It probably is useful, but that is rather difficult to judge,\n>> unless you have a specific use in the scripts (am/applymox).\n>\n> I have my own custom clone of git-am I am using to extract the\n> Message-id, In-Reply-To, and References fields.  For awhile I had the\n> fields hardcoded in my version of git-mailinfo.  But instead of\n> maintaining it, I was hoping I could push it upstream.  One less thing\n> to maintain on my own.  :-)\n\nFair enough.\n\n> oops.  left over comment from old code.  I'll clean that up.\n\nI've applied 1, 3, 4 and 5 for now, but have't pushed the\nresults out (I have other patches to tend first).\n"}]}