Re: Flat search and threaded views
[notmuch-archives.git] / 3f / 2bbfa0281e2bb99e7606866dd703963cffeeff
1 Return-Path: <jani@nikula.org>\r
2 X-Original-To: notmuch@notmuchmail.org\r
3 Delivered-To: notmuch@notmuchmail.org\r
4 Received: from localhost (localhost [127.0.0.1])\r
5  by arlo.cworth.org (Postfix) with ESMTP id 91C8F6DE034D\r
6  for <notmuch@notmuchmail.org>; Sat, 18 Jun 2016 14:33:09 -0700 (PDT)\r
7 X-Virus-Scanned: Debian amavisd-new at cworth.org\r
8 X-Amavis-Alert: BAD HEADER SECTION, Duplicate header field: "References"\r
9 X-Spam-Flag: NO\r
10 X-Spam-Score: -0.563\r
11 X-Spam-Level: \r
12 X-Spam-Status: No, score=-0.563 tagged_above=-999 required=5 tests=[AWL=0.157,\r
13   DKIM_SIGNED=0.1, DKIM_VALID=-0.1, RCVD_IN_DNSWL_LOW=-0.7,\r
14  RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01] autolearn=disabled\r
15 Received: from arlo.cworth.org ([127.0.0.1])\r
16  by localhost (arlo.cworth.org [127.0.0.1]) (amavisd-new, port 10024)\r
17  with ESMTP id B5KL1YfQwBXU for <notmuch@notmuchmail.org>;\r
18  Sat, 18 Jun 2016 14:33:01 -0700 (PDT)\r
19 Received: from mail-wm0-f67.google.com (mail-wm0-f67.google.com\r
20  [74.125.82.67]) by arlo.cworth.org (Postfix) with ESMTPS id 005FA6DE00DF for\r
21  <notmuch@notmuchmail.org>; Sat, 18 Jun 2016 14:33:00 -0700 (PDT)\r
22 Received: by mail-wm0-f67.google.com with SMTP id c82so2550855wme.3\r
23  for <notmuch@notmuchmail.org>; Sat, 18 Jun 2016 14:33:00 -0700 (PDT)\r
24 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;\r
25  d=nikula-org.20150623.gappssmtp.com; s=20150623;\r
26  h=from:to:cc:subject:date:message-id:in-reply-to:references\r
27  :in-reply-to:references;\r
28  bh=0gTT1Cs2x5flbIL5lOKo8lgQoRdqG9bi3NSycpTh6/I=;\r
29  b=j9HBsAfAVrT8C/54OyYk7Ku7rQccosUyqQd9q53bpKhWhCrbXEE80dPwvYvyGCQuhV\r
30  sc0puSwUt7UkS/11+3ASnnvyvscCMkpAP0VEw85bLoBUP8CHQRqoxRqV0uD68TnnJ3/P\r
31  GWoOJOJHF73sKq63YFP+bl5pYM//f698C4PyIjg+3oOPkwJ+CnkS1pNowL2SZTMk3OAh\r
32  Sd6CY/F99lpL+yY19WtopjzmgEJl5eASO2sYi3kcJnJ9tkwfYONCQYpDeGdkZEWgF18a\r
33  KDiUGspWhx2yAusbROWhwLcLteDNfiLWVILOzOHblX8MiRMuXo1mMhQQ+EDsqTKMy1SN\r
34  ikHA==\r
35 X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;\r
36  d=1e100.net; s=20130820;\r
37  h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to\r
38  :references:in-reply-to:references;\r
39  bh=0gTT1Cs2x5flbIL5lOKo8lgQoRdqG9bi3NSycpTh6/I=;\r
40  b=aUdlSkvBWNApBYdzGMqzqVGqeYkt3KAtV8b5IZwi2c9W7tmVlG7lSy8r87gBbBk5OG\r
41  Qrp0A9TODdH8EDkqScdSIwioHmP9FF9W7wEluipnX9I8X3QL+Pbih+jncCKRFxJhVgrD\r
42  Vmguo/He/jHuPOU3POk7zDv92YAOqglipJ5OL0sGIdUDMxxsqC/J6X41cTZuiLLes/wk\r
43  AtQlzRww2pwLijGwngacJjJ27WjDWtv3p25PN+tJr9ETRpgIIjZY5W2wJqvVrJC/YDNH\r
44  qpc8G3BqDmPuHnwdelXmTKQ9AFAHCJcbN4rLq0nObQFG95P4Yb/lsU2L0++3mSXSxjbC\r
45  Xkwg==\r
46 X-Gm-Message-State:\r
47  ALyK8tLhcSZxh4e9pcmNntkPJJ0vAWeYSDuwzBzLq1lRIcZFrx/amniscLYsnOBnOtKQ8w==\r
48 X-Received: by 10.28.135.137 with SMTP id j131mr4251433wmd.47.1466285579405;\r
49  Sat, 18 Jun 2016 14:32:59 -0700 (PDT)\r
50 Received: from localhost (mobile-access-bcee4e-81.dhcp.inet.fi.\r
51  [188.238.78.81])\r
52  by smtp.gmail.com with ESMTPSA id j4sm54730882wjg.20.2016.06.18.14.32.58\r
53  (version=TLSv1/SSLv3 cipher=OTHER);\r
54  Sat, 18 Jun 2016 14:32:58 -0700 (PDT)\r
55 From: Jani Nikula <jani@nikula.org>\r
56 To: notmuch@notmuchmail.org\r
57 Cc: jani@nikula.org,\r
58         Daniel Kahn Gillmor <dkg@fifthhorseman.net>\r
59 Subject: [PATCH 1/7] cli/reply: push notmuch reply format abstraction lower in\r
60  the stack\r
61 Date: Sun, 19 Jun 2016 00:31:27 +0300\r
62 Message-Id:\r
63  <c3a26221dc40ec3e685680435361909a95abcb0f.1466284726.git.jani@nikula.org>\r
64 X-Mailer: git-send-email 2.1.4\r
65 In-Reply-To: <cover.1466284726.git.jani@nikula.org>\r
66 References: <cover.1466284726.git.jani@nikula.org>\r
67 In-Reply-To: <cover.1466284726.git.jani@nikula.org>\r
68 References: <cover.1466284726.git.jani@nikula.org>\r
69 X-BeenThere: notmuch@notmuchmail.org\r
70 X-Mailman-Version: 2.1.20\r
71 Precedence: list\r
72 List-Id: "Use and development of the notmuch mail system."\r
73  <notmuch.notmuchmail.org>\r
74 List-Unsubscribe: <https://notmuchmail.org/mailman/options/notmuch>,\r
75  <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>\r
76 List-Archive: <http://notmuchmail.org/pipermail/notmuch/>\r
77 List-Post: <mailto:notmuch@notmuchmail.org>\r
78 List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>\r
79 List-Subscribe: <https://notmuchmail.org/mailman/listinfo/notmuch>,\r
80  <mailto:notmuch-request@notmuchmail.org?subject=subscribe>\r
81 X-List-Received-Date: Sat, 18 Jun 2016 21:33:09 -0000\r
82 \r
83 There's quite a bit of duplication, and some consequent deviation,\r
84 between the various notmuch reply format code paths. Perform the query\r
85 and message iteration in common code, and make the format specific\r
86 functions operate on single messages.\r
87 \r
88 There should be no functional changes.\r
89 ---\r
90  notmuch-reply.c | 216 ++++++++++++++++++++++++++------------------------------\r
91  1 file changed, 101 insertions(+), 115 deletions(-)\r
92 \r
93 diff --git a/notmuch-reply.c b/notmuch-reply.c\r
94 index 49513732e620..847e306f94d2 100644\r
95 --- a/notmuch-reply.c\r
96 +++ b/notmuch-reply.c\r
97 @@ -598,82 +598,42 @@ create_reply_message(void *ctx,\r
98  static int\r
99  notmuch_reply_format_default(void *ctx,\r
100                              notmuch_config_t *config,\r
101 -                            notmuch_query_t *query,\r
102 +                            notmuch_message_t *message,\r
103                              notmuch_show_params_t *params,\r
104                              notmuch_bool_t reply_all,\r
105                              unused (sprinter_t *sp))\r
106  {\r
107      GMimeMessage *reply;\r
108 -    notmuch_messages_t *messages;\r
109 -    notmuch_message_t *message;\r
110      mime_node_t *root;\r
111 -    notmuch_status_t status;\r
112  \r
113 -    status = notmuch_query_search_messages_st (query, &messages);\r
114 -    if (print_status_query ("notmuch reply", query, status))\r
115 +    reply = create_reply_message (ctx, config, message, reply_all);\r
116 +    if (!reply)\r
117         return 1;\r
118  \r
119 -    for (;\r
120 -        notmuch_messages_valid (messages);\r
121 -        notmuch_messages_move_to_next (messages))\r
122 -    {\r
123 -       message = notmuch_messages_get (messages);\r
124 +    show_reply_headers (reply);\r
125  \r
126 -       reply = create_reply_message (ctx, config, message, reply_all);\r
127 -\r
128 -       /* If reply creation failed, we're out of memory, so don't\r
129 -        * bother trying any more messages.\r
130 -        */\r
131 -       if (!reply) {\r
132 -           notmuch_message_destroy (message);\r
133 -           return 1;\r
134 -       }\r
135 -\r
136 -       show_reply_headers (reply);\r
137 -\r
138 -       g_object_unref (G_OBJECT (reply));\r
139 -       reply = NULL;\r
140 -\r
141 -       if (mime_node_open (ctx, message, &(params->crypto), &root) == NOTMUCH_STATUS_SUCCESS) {\r
142 -           format_part_reply (root);\r
143 -           talloc_free (root);\r
144 -       }\r
145 +    g_object_unref (G_OBJECT (reply));\r
146  \r
147 -       notmuch_message_destroy (message);\r
148 +    if (mime_node_open (ctx, message, &params->crypto, &root) == NOTMUCH_STATUS_SUCCESS) {\r
149 +       format_part_reply (root);\r
150 +       talloc_free (root);\r
151      }\r
152 +\r
153      return 0;\r
154  }\r
155  \r
156  static int\r
157  notmuch_reply_format_sprinter(void *ctx,\r
158                               notmuch_config_t *config,\r
159 -                             notmuch_query_t *query,\r
160 +                             notmuch_message_t *message,\r
161                               notmuch_show_params_t *params,\r
162                               notmuch_bool_t reply_all,\r
163                               sprinter_t *sp)\r
164  {\r
165      GMimeMessage *reply;\r
166 -    notmuch_messages_t *messages;\r
167 -    notmuch_message_t *message;\r
168      mime_node_t *node;\r
169 -    unsigned count;\r
170 -    notmuch_status_t status;\r
171 -\r
172 -    status = notmuch_query_count_messages_st (query, &count);\r
173 -    if (print_status_query ("notmuch reply", query, status))\r
174 -       return 1;\r
175 -\r
176 -    if (count != 1) {\r
177 -       fprintf (stderr, "Error: search term did not match precisely one message (matched %d messages).\n", count);\r
178 -       return 1;\r
179 -    }\r
180  \r
181 -    status = notmuch_query_search_messages_st (query, &messages);\r
182 -    if (print_status_query ("notmuch reply", query, status))\r
183 -       return 1;\r
184 -\r
185 -    message = notmuch_messages_get (messages);\r
186 -    if (mime_node_open (ctx, message, &(params->crypto), &node) != NOTMUCH_STATUS_SUCCESS)\r
187 +    if (mime_node_open (ctx, message, &params->crypto, &node) != NOTMUCH_STATUS_SUCCESS)\r
188         return 1;\r
189  \r
190      reply = create_reply_message (ctx, config, message, reply_all);\r
191 @@ -686,7 +646,6 @@ notmuch_reply_format_sprinter(void *ctx,\r
192      sp->map_key (sp, "reply-headers");\r
193      format_headers_sprinter (sp, reply, TRUE);\r
194      g_object_unref (G_OBJECT (reply));\r
195 -    reply = NULL;\r
196  \r
197      /* Start the original */\r
198      sp->map_key (sp, "original");\r
199 @@ -694,7 +653,6 @@ notmuch_reply_format_sprinter(void *ctx,\r
200  \r
201      /* End */\r
202      sp->end (sp);\r
203 -    notmuch_message_destroy (message);\r
204  \r
205      return 0;\r
206  }\r
207 @@ -703,65 +661,48 @@ notmuch_reply_format_sprinter(void *ctx,\r
208  static int\r
209  notmuch_reply_format_headers_only(void *ctx,\r
210                                   notmuch_config_t *config,\r
211 -                                 notmuch_query_t *query,\r
212 +                                 notmuch_message_t *message,\r
213                                   unused (notmuch_show_params_t *params),\r
214                                   notmuch_bool_t reply_all,\r
215                                   unused (sprinter_t *sp))\r
216  {\r
217      GMimeMessage *reply;\r
218 -    notmuch_messages_t *messages;\r
219 -    notmuch_message_t *message;\r
220      const char *in_reply_to, *orig_references, *references;\r
221      char *reply_headers;\r
222 -    notmuch_status_t status;\r
223  \r
224 -    status = notmuch_query_search_messages_st (query, &messages);\r
225 -    if (print_status_query ("notmuch reply", query, status))\r
226 +    /* The 0 means we do not want headers in a "pretty" order. */\r
227 +    reply = g_mime_message_new (0);\r
228 +    if (reply == NULL) {\r
229 +       fprintf (stderr, "Out of memory\n");\r
230         return 1;\r
231 +    }\r
232  \r
233 -    for (;\r
234 -        notmuch_messages_valid (messages);\r
235 -        notmuch_messages_move_to_next (messages))\r
236 -    {\r
237 -       message = notmuch_messages_get (messages);\r
238 -\r
239 -       /* The 0 means we do not want headers in a "pretty" order. */\r
240 -       reply = g_mime_message_new (0);\r
241 -       if (reply == NULL) {\r
242 -           fprintf (stderr, "Out of memory\n");\r
243 -           return 1;\r
244 -       }\r
245 -\r
246 -       in_reply_to = talloc_asprintf (ctx, "<%s>",\r
247 -                            notmuch_message_get_message_id (message));\r
248 -\r
249 -        g_mime_object_set_header (GMIME_OBJECT (reply),\r
250 -                                 "In-Reply-To", in_reply_to);\r
251 +    in_reply_to = talloc_asprintf (ctx, "<%s>",\r
252 +                                  notmuch_message_get_message_id (message));\r
253  \r
254 +    g_mime_object_set_header (GMIME_OBJECT (reply), "In-Reply-To", in_reply_to);\r
255  \r
256 -       orig_references = notmuch_message_get_header (message, "references");\r
257 +    orig_references = notmuch_message_get_header (message, "references");\r
258  \r
259 -       /* We print In-Reply-To followed by References because git format-patch treats them\r
260 -         * specially.  Git does not interpret the other headers specially\r
261 -        */\r
262 -       references = talloc_asprintf (ctx, "%s%s%s",\r
263 -                                     orig_references ? orig_references : "",\r
264 -                                     orig_references ? " " : "",\r
265 -                                     in_reply_to);\r
266 -       g_mime_object_set_header (GMIME_OBJECT (reply),\r
267 -                                 "References", references);\r
268 +    /*\r
269 +     * We print In-Reply-To followed by References because git\r
270 +     * format-patch treats them specially. Git does not interpret the\r
271 +     * other headers specially.\r
272 +     */\r
273 +    references = talloc_asprintf (ctx, "%s%s%s",\r
274 +                                 orig_references ? orig_references : "",\r
275 +                                 orig_references ? " " : "",\r
276 +                                 in_reply_to);\r
277 +    g_mime_object_set_header (GMIME_OBJECT (reply), "References", references);\r
278  \r
279 -       (void)add_recipients_from_message (reply, config, message, reply_all);\r
280 +    (void)add_recipients_from_message (reply, config, message, reply_all);\r
281  \r
282 -       reply_headers = g_mime_object_to_string (GMIME_OBJECT (reply));\r
283 -       printf ("%s", reply_headers);\r
284 -       free (reply_headers);\r
285 +    reply_headers = g_mime_object_to_string (GMIME_OBJECT (reply));\r
286 +    printf ("%s", reply_headers);\r
287 +    free (reply_headers);\r
288  \r
289 -       g_object_unref (G_OBJECT (reply));\r
290 -       reply = NULL;\r
291 +    g_object_unref (G_OBJECT (reply));\r
292  \r
293 -       notmuch_message_destroy (message);\r
294 -    }\r
295      return 0;\r
296  }\r
297  \r
298 @@ -772,6 +713,70 @@ enum {\r
299      FORMAT_HEADERS_ONLY,\r
300  };\r
301  \r
302 +static int do_reply(notmuch_config_t *config,\r
303 +                   notmuch_query_t *query,\r
304 +                   notmuch_show_params_t *params,\r
305 +                   int format,\r
306 +                   notmuch_bool_t reply_all)\r
307 +{\r
308 +    notmuch_messages_t *messages;\r
309 +    notmuch_message_t *message;\r
310 +    notmuch_status_t status;\r
311 +    struct sprinter *sp = NULL;\r
312 +    int ret = 0;\r
313 +    int (*reply_format_func) (void *ctx,\r
314 +                             notmuch_config_t *config,\r
315 +                             notmuch_message_t *message,\r
316 +                             notmuch_show_params_t *params,\r
317 +                             notmuch_bool_t reply_all,\r
318 +                             struct sprinter *sp);\r
319 +\r
320 +    if (format == FORMAT_JSON || format == FORMAT_SEXP) {\r
321 +       unsigned count;\r
322 +\r
323 +       status = notmuch_query_count_messages_st (query, &count);\r
324 +       if (print_status_query ("notmuch reply", query, status))\r
325 +           return 1;\r
326 +\r
327 +       if (count != 1) {\r
328 +           fprintf (stderr, "Error: search term did not match precisely one message (matched %d messages).\n", count);\r
329 +           return 1;\r
330 +       }\r
331 +    }\r
332 +\r
333 +    if (format == FORMAT_HEADERS_ONLY) {\r
334 +       reply_format_func = notmuch_reply_format_headers_only;\r
335 +    } else if (format == FORMAT_JSON) {\r
336 +       reply_format_func = notmuch_reply_format_sprinter;\r
337 +       sp = sprinter_json_create (config, stdout);\r
338 +    } else if (format == FORMAT_SEXP) {\r
339 +       reply_format_func = notmuch_reply_format_sprinter;\r
340 +       sp = sprinter_sexp_create (config, stdout);\r
341 +    } else {\r
342 +       reply_format_func = notmuch_reply_format_default;\r
343 +    }\r
344 +\r
345 +    status = notmuch_query_search_messages_st (query, &messages);\r
346 +    if (print_status_query ("notmuch reply", query, status))\r
347 +       return 1;\r
348 +\r
349 +    for (;\r
350 +        notmuch_messages_valid (messages);\r
351 +        notmuch_messages_move_to_next (messages))\r
352 +    {\r
353 +       message = notmuch_messages_get (messages);\r
354 +\r
355 +       ret = reply_format_func(config, config, message, params, reply_all, sp);\r
356 +\r
357 +       notmuch_message_destroy (message);\r
358 +\r
359 +       if (ret)\r
360 +           break;\r
361 +    }\r
362 +\r
363 +    return ret;\r
364 +}\r
365 +\r
366  int\r
367  notmuch_reply_command (notmuch_config_t *config, int argc, char *argv[])\r
368  {\r
369 @@ -779,12 +784,6 @@ notmuch_reply_command (notmuch_config_t *config, int argc, char *argv[])\r
370      notmuch_query_t *query;\r
371      char *query_string;\r
372      int opt_index;\r
373 -    int (*reply_format_func) (void *ctx,\r
374 -                             notmuch_config_t *config,\r
375 -                             notmuch_query_t *query,\r
376 -                             notmuch_show_params_t *params,\r
377 -                             notmuch_bool_t reply_all,\r
378 -                             struct sprinter *sp);\r
379      notmuch_show_params_t params = {\r
380         .part = -1,\r
381         .crypto = {\r
382 @@ -795,7 +794,6 @@ notmuch_reply_command (notmuch_config_t *config, int argc, char *argv[])\r
383      };\r
384      int format = FORMAT_DEFAULT;\r
385      int reply_all = TRUE;\r
386 -    struct sprinter *sp = NULL;\r
387  \r
388      notmuch_opt_desc_t options[] = {\r
389         { NOTMUCH_OPT_KEYWORD, &format, "format", 'f',\r
390 @@ -820,18 +818,6 @@ notmuch_reply_command (notmuch_config_t *config, int argc, char *argv[])\r
391  \r
392      notmuch_process_shared_options (argv[0]);\r
393  \r
394 -    if (format == FORMAT_HEADERS_ONLY) {\r
395 -       reply_format_func = notmuch_reply_format_headers_only;\r
396 -    } else if (format == FORMAT_JSON) {\r
397 -       reply_format_func = notmuch_reply_format_sprinter;\r
398 -       sp = sprinter_json_create (config, stdout);\r
399 -    } else if (format == FORMAT_SEXP) {\r
400 -       reply_format_func = notmuch_reply_format_sprinter;\r
401 -       sp = sprinter_sexp_create (config, stdout);\r
402 -    } else {\r
403 -       reply_format_func = notmuch_reply_format_default;\r
404 -    }\r
405 -\r
406      notmuch_exit_if_unsupported_format ();\r
407  \r
408      query_string = query_string_from_args (config, argc-opt_index, argv+opt_index);\r
409 @@ -859,7 +845,7 @@ notmuch_reply_command (notmuch_config_t *config, int argc, char *argv[])\r
410         return EXIT_FAILURE;\r
411      }\r
412  \r
413 -    if (reply_format_func (config, config, query, &params, reply_all, sp) != 0)\r
414 +    if (do_reply (config, query, &params, format, reply_all) != 0)\r
415         return EXIT_FAILURE;\r
416  \r
417      notmuch_crypto_cleanup (&params.crypto);\r
418 -- \r
419 2.1.4\r
420 \r