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