Re: [PATCH v6 05/10] reply: Add a JSON reply format.
authorJani Nikula <jani@nikula.org>
Fri, 9 Mar 2012 23:08:58 +0000 (01:08 +0200)
committerW. Trevor King <wking@tremily.us>
Fri, 7 Nov 2014 17:45:21 +0000 (09:45 -0800)
ef/9283536a26dac38f03f15f2502c72578d97063 [new file with mode: 0644]

diff --git a/ef/9283536a26dac38f03f15f2502c72578d97063 b/ef/9283536a26dac38f03f15f2502c72578d97063
new file mode 100644 (file)
index 0000000..64cdbb8
--- /dev/null
@@ -0,0 +1,292 @@
+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