--- /dev/null
+Return-Path: <jani@nikula.org>\r
+X-Original-To: notmuch@notmuchmail.org\r
+Delivered-To: notmuch@notmuchmail.org\r
+Received: from localhost (localhost [127.0.0.1])\r
+ by olra.theworths.org (Postfix) with ESMTP id 26A37431FC3\r
+ for <notmuch@notmuchmail.org>; Fri, 9 Mar 2012 15:09:08 -0800 (PST)\r
+X-Virus-Scanned: Debian amavisd-new at olra.theworths.org\r
+X-Spam-Flag: NO\r
+X-Spam-Score: -0.7\r
+X-Spam-Level: \r
+X-Spam-Status: No, score=-0.7 tagged_above=-999 required=5\r
+ tests=[RCVD_IN_DNSWL_LOW=-0.7] autolearn=disabled\r
+Received: from olra.theworths.org ([127.0.0.1])\r
+ by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024)\r
+ with ESMTP id VjsFzxUkPuvS for <notmuch@notmuchmail.org>;\r
+ Fri, 9 Mar 2012 15:09:04 -0800 (PST)\r
+Received: from mail-lpp01m010-f53.google.com (mail-lpp01m010-f53.google.com\r
+ [209.85.215.53]) (using TLSv1 with cipher RC4-SHA (128/128 bits))\r
+ (No client certificate requested)\r
+ by olra.theworths.org (Postfix) with ESMTPS id DDDE5431FAE\r
+ for <notmuch@notmuchmail.org>; Fri, 9 Mar 2012 15:09:03 -0800 (PST)\r
+Received: by lahc1 with SMTP id c1so2275980lah.26\r
+ for <notmuch@notmuchmail.org>; Fri, 09 Mar 2012 15:09:02 -0800 (PST)\r
+X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;\r
+ d=google.com; s=20120113;\r
+ h=from:to:subject:in-reply-to:references:user-agent:date:message-id\r
+ :mime-version:content-type:x-gm-message-state;\r
+ bh=iGTAKEuykInJLscHrAgJXloAni6J/gmB/gjImATZpZc=;\r
+ b=nI70bU5msarKhwpXMzp6etG9VGc6ImnR3KqQEX+h8bFhoqGH9m1ilve/bC+dSmnWlo\r
+ QHXSIw3Vasu79zO1HXNQsJ/hY9usNeWPeFuoHuMh9vZspvqajdT3rmaOg+HPOGlARTPs\r
+ 9lkKF9dy0EA01Hzn5aDizucp7yFfH37ki3EfoU5Av6aw/iFFCWzGWOITig2hTlp29a8e\r
+ nHGkOe0Mq4q7J9y74E/2qjrs1lTqNuvpB4O/OAZnvAKPIKG+0LKUklUG4nLDtgc6u+kg\r
+ uLYhtR8Q7B1TyhIa5VfbGiAbdKIetlV2DATE3CBERcpJkDg1wwcHXDllkZ2WXq/QlXkO\r
+ Wlkg==\r
+Received: by 10.112.38.3 with SMTP id c3mr1445266lbk.94.1331334542180;\r
+ Fri, 09 Mar 2012 15:09:02 -0800 (PST)\r
+Received: from localhost (dsl-hkibrasgw4-fe50f800-253.dhcp.inet.fi.\r
+ [84.248.80.253])\r
+ by mx.google.com with ESMTPS id nh5sm5972532lab.5.2012.03.09.15.08.59\r
+ (version=SSLv3 cipher=OTHER); Fri, 09 Mar 2012 15:09:00 -0800 (PST)\r
+From: Jani Nikula <jani@nikula.org>\r
+To: Adam Wolfe Gordon <awg+notmuch@xvx.ca>, notmuch@notmuchmail.org\r
+Subject: Re: [PATCH v6 05/10] reply: Add a JSON reply format.\r
+In-Reply-To: <1329893199-21630-6-git-send-email-awg+notmuch@xvx.ca>\r
+References: <1329893199-21630-1-git-send-email-awg+notmuch@xvx.ca>\r
+ <1329893199-21630-6-git-send-email-awg+notmuch@xvx.ca>\r
+User-Agent: Notmuch/0.11.1+295~g780f284 (http://notmuchmail.org) Emacs/23.3.1\r
+ (i686-pc-linux-gnu)\r
+Date: Sat, 10 Mar 2012 01:08:58 +0200\r
+Message-ID: <87d38l8j91.fsf@nikula.org>\r
+MIME-Version: 1.0\r
+Content-Type: text/plain; charset=us-ascii\r
+X-Gm-Message-State:\r
+ ALoCoQkAIH0T9yfAEPf7yqPlYWQ2M4KDGiS0tBACl6rntLAEQgeHqpc+r6STfHpkD56mHE0tRA+Y\r
+X-BeenThere: notmuch@notmuchmail.org\r
+X-Mailman-Version: 2.1.13\r
+Precedence: list\r
+List-Id: "Use and development of the notmuch mail system."\r
+ <notmuch.notmuchmail.org>\r
+List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,\r
+ <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>\r
+List-Archive: <http://notmuchmail.org/pipermail/notmuch>\r
+List-Post: <mailto:notmuch@notmuchmail.org>\r
+List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>\r
+List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,\r
+ <mailto:notmuch-request@notmuchmail.org?subject=subscribe>\r
+X-List-Received-Date: Fri, 09 Mar 2012 23:09:08 -0000\r
+\r
+On Tue, 21 Feb 2012 23:46:34 -0700, Adam Wolfe Gordon <awg+notmuch@xvx.ca> wrote:\r
+> This new JSON format for replies includes headers generated for a\r
+> reply message as well as the headers of the original message. Using\r
+> this data, a client can intelligently create a reply. For example, the\r
+> emacs client will be able to create replies with quoted HTML parts by\r
+> parsing the HTML parts.\r
+> ---\r
+> notmuch-client.h | 10 ++++++++--\r
+> notmuch-reply.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++\r
+> notmuch-show.c | 30 ++++++++++++++++++++++--------\r
+> test/multipart | 1 -\r
+> 4 files changed, 79 insertions(+), 11 deletions(-)\r
+> \r
+> diff --git a/notmuch-client.h b/notmuch-client.h\r
+> index f4a62cc..ef4eaba 100644\r
+> --- a/notmuch-client.h\r
+> +++ b/notmuch-client.h\r
+> @@ -62,13 +62,13 @@\r
+> #define STRINGIFY(s) STRINGIFY_(s)\r
+> #define STRINGIFY_(s) #s\r
+> \r
+> -struct mime_node;\r
+> +typedef struct mime_node mime_node_t;\r
+> struct notmuch_show_params;\r
+> \r
+> typedef struct notmuch_show_format {\r
+> const char *message_set_start;\r
+> void (*part) (const void *ctx,\r
+> - struct mime_node *node, int indent,\r
+> + mime_node_t *node, int indent,\r
+> const struct notmuch_show_params *params);\r
+> const char *message_start;\r
+> void (*message) (const void *ctx,\r
+> @@ -191,6 +191,12 @@ show_message_body (notmuch_message_t *message,\r
+> notmuch_status_t\r
+> show_one_part (const char *filename, int part);\r
+> \r
+> +void\r
+> +format_part_json (const void *ctx, mime_node_t *node, notmuch_bool_t first);\r
+> +\r
+> +void\r
+> +format_headers_json (const void *ctx, GMimeMessage *message, notmuch_bool_t reply);\r
+> +\r
+> char *\r
+> json_quote_chararray (const void *ctx, const char *str, const size_t len);\r
+> \r
+> diff --git a/notmuch-reply.c b/notmuch-reply.c\r
+> index 177e6ca..017c6ae 100644\r
+> --- a/notmuch-reply.c\r
+> +++ b/notmuch-reply.c\r
+> @@ -601,6 +601,51 @@ notmuch_reply_format_default(void *ctx,\r
+> return 0;\r
+> }\r
+> \r
+> +static int\r
+> +notmuch_reply_format_json(void *ctx,\r
+> + notmuch_config_t *config,\r
+> + notmuch_query_t *query,\r
+> + notmuch_show_params_t *params,\r
+> + notmuch_bool_t reply_all)\r
+> +{\r
+> + GMimeMessage *reply;\r
+> + notmuch_messages_t *messages;\r
+> + notmuch_message_t *message;\r
+> + mime_node_t *node;\r
+> +\r
+> + if (notmuch_query_count_messages (query) != 1) {\r
+> + fprintf (stderr, "Error: search term did not match precisely one message.\n");\r
+> + return 1;\r
+> + }\r
+> +\r
+> + messages = notmuch_query_search_messages (query);\r
+> + message = notmuch_messages_get (messages);\r
+> + if (mime_node_open (ctx, message, params->cryptoctx, params->decrypt,\r
+> + &node) != NOTMUCH_STATUS_SUCCESS)\r
+> + return 1;\r
+> +\r
+> + reply = create_reply_message (ctx, config, message, reply_all);\r
+> + if (!reply)\r
+> + return 1;\r
+> +\r
+> + /* The headers of the reply message we've created */\r
+> + printf ("{\"reply-headers\": ");\r
+> + format_headers_json (ctx, reply, TRUE);\r
+> + g_object_unref (G_OBJECT (reply));\r
+> + reply = NULL;\r
+> +\r
+> + /* Start the original */\r
+> + printf (", \"original\": ");\r
+> +\r
+> + format_part_json (ctx, node, TRUE);\r
+> +\r
+> + /* End */\r
+> + printf ("}\n");\r
+> + notmuch_message_destroy (message);\r
+> +\r
+> + return 0;\r
+> +}\r
+> +\r
+> /* This format is currently tuned for a git send-email --notmuch hook */\r
+> static int\r
+> notmuch_reply_format_headers_only(void *ctx,\r
+> @@ -663,6 +708,7 @@ notmuch_reply_format_headers_only(void *ctx,\r
+> \r
+> enum {\r
+> FORMAT_DEFAULT,\r
+> + FORMAT_JSON,\r
+> FORMAT_HEADERS_ONLY,\r
+> };\r
+> \r
+> @@ -682,6 +728,7 @@ notmuch_reply_command (void *ctx, int argc, char *argv[])\r
+> notmuch_opt_desc_t options[] = {\r
+> { NOTMUCH_OPT_KEYWORD, &format, "format", 'f',\r
+> (notmuch_keyword_t []){ { "default", FORMAT_DEFAULT },\r
+> + { "json", FORMAT_JSON },\r
+> { "headers-only", FORMAT_HEADERS_ONLY },\r
+> { 0, 0 } } },\r
+> { NOTMUCH_OPT_KEYWORD, &reply_all, "reply-to", 'r',\r
+> @@ -700,6 +747,8 @@ notmuch_reply_command (void *ctx, int argc, char *argv[])\r
+> \r
+> if (format == FORMAT_HEADERS_ONLY)\r
+> reply_format_func = notmuch_reply_format_headers_only;\r
+> + else if (format == FORMAT_JSON)\r
+> + reply_format_func = notmuch_reply_format_json;\r
+> else\r
+> reply_format_func = notmuch_reply_format_default;\r
+> \r
+> diff --git a/notmuch-show.c b/notmuch-show.c\r
+> index 6a171a4..2126d78 100644\r
+> --- a/notmuch-show.c\r
+> +++ b/notmuch-show.c\r
+> @@ -290,8 +290,8 @@ format_headers_message_part_text (GMimeMessage *message)\r
+> printf ("Date: %s\n", g_mime_message_get_date_as_string (message));\r
+> }\r
+> \r
+> -static void\r
+> -format_headers_json (const void *ctx, GMimeMessage *message)\r
+> +void\r
+> +format_headers_json (const void *ctx, GMimeMessage *message, notmuch_bool_t reply)\r
+> {\r
+> void *local = talloc_new (ctx);\r
+> InternetAddressList *recipients;\r
+> @@ -315,9 +315,23 @@ format_headers_json (const void *ctx, GMimeMessage *message)\r
+> printf (", %s: %s",\r
+> json_quote_str (local, "Cc"),\r
+> json_quote_str (local, recipients_string));\r
+> - printf (", %s: %s}",\r
+> - json_quote_str (local, "Date"),\r
+> - json_quote_str (local, g_mime_message_get_date_as_string (message)));\r
+> +\r
+> + if (!reply)\r
+> + printf (", %s: %s",\r
+> + json_quote_str (local, "Date"),\r
+> + json_quote_str (local, g_mime_message_get_date_as_string (message)));\r
+> +\r
+> + if (reply) {\r
+\r
+Isn't that an "else"?\r
+\r
+Otherwise looks good.\r
+\r
+BR,\r
+Jani.\r
+\r
+\r
+> + printf (", %s: %s",\r
+> + json_quote_str (local, "In-reply-to"),\r
+> + json_quote_str (local, g_mime_object_get_header (GMIME_OBJECT (message), "In-reply-to")));\r
+> +\r
+> + printf (", %s: %s",\r
+> + json_quote_str (local, "References"),\r
+> + json_quote_str (local, g_mime_object_get_header (GMIME_OBJECT (message), "References")));\r
+> + }\r
+> +\r
+> + printf ("}");\r
+> \r
+> talloc_free (local);\r
+> }\r
+> @@ -652,7 +666,7 @@ format_part_text (const void *ctx, mime_node_t *node,\r
+> printf ("\f%s}\n", part_type);\r
+> }\r
+> \r
+> -static void\r
+> +void\r
+> format_part_json (const void *ctx, mime_node_t *node, notmuch_bool_t first)\r
+> {\r
+> /* Any changes to the JSON format should be reflected in the file\r
+> @@ -663,7 +677,7 @@ format_part_json (const void *ctx, mime_node_t *node, notmuch_bool_t first)\r
+> format_message_json (ctx, node->envelope_file);\r
+> \r
+> printf ("\"headers\": ");\r
+> - format_headers_json (ctx, GMIME_MESSAGE (node->part));\r
+> + format_headers_json (ctx, GMIME_MESSAGE (node->part), FALSE);\r
+> \r
+> printf (", \"body\": [");\r
+> format_part_json (ctx, mime_node_child (node, 0), first);\r
+> @@ -737,7 +751,7 @@ format_part_json (const void *ctx, mime_node_t *node, notmuch_bool_t first)\r
+> } else if (GMIME_IS_MESSAGE (node->part)) {\r
+> printf (", \"content\": [{");\r
+> printf ("\"headers\": ");\r
+> - format_headers_json (local, GMIME_MESSAGE (node->part));\r
+> + format_headers_json (local, GMIME_MESSAGE (node->part), FALSE);\r
+> \r
+> printf (", \"body\": [");\r
+> terminator = "]}]";\r
+> diff --git a/test/multipart b/test/multipart\r
+> index f102294..e7abcc2 100755\r
+> --- a/test/multipart\r
+> +++ b/test/multipart\r
+> @@ -590,7 +590,6 @@ EOF\r
+> test_expect_equal_file OUTPUT EXPECTED\r
+> \r
+> test_begin_subtest "'notmuch reply' to a multipart message with json format"\r
+> -test_subtest_known_broken\r
+> notmuch reply --format=json 'id:87liy5ap00.fsf@yoom.home.cworth.org' | notmuch_json_show_sanitize >OUTPUT\r
+> cat <<EOF >EXPECTED\r
+> {"reply-headers": {"Subject": "Re: Multipart message",\r
+> -- \r
+> 1.7.5.4\r
+> \r
+> _______________________________________________\r
+> notmuch mailing list\r
+> notmuch@notmuchmail.org\r
+> http://notmuchmail.org/mailman/listinfo/notmuch\r