Re: notmuch and "mute" -- useful to anyone?
[notmuch-archives.git] / 24 / b99a25d7cadef251eec094926cf4bd5e0b5add
1 Return-Path: <bremner@tesseract.cs.unb.ca>\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 olra.theworths.org (Postfix) with ESMTP id 2BA62431FDA\r
6         for <notmuch@notmuchmail.org>; Fri, 27 Mar 2015 15:13:22 -0700 (PDT)\r
7 X-Virus-Scanned: Debian amavisd-new at olra.theworths.org\r
8 X-Spam-Flag: NO\r
9 X-Spam-Score: 2.438\r
10 X-Spam-Level: **\r
11 X-Spam-Status: No, score=2.438 tagged_above=-999 required=5\r
12         tests=[DNS_FROM_AHBL_RHSBL=2.438] autolearn=disabled\r
13 Received: from olra.theworths.org ([127.0.0.1])\r
14         by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024)\r
15         with ESMTP id 3lF5hEF9fxYZ for <notmuch@notmuchmail.org>;\r
16         Fri, 27 Mar 2015 15:13:20 -0700 (PDT)\r
17 Received: from mx.xen14.node3324.gplhost.com (gitolite.debian.net\r
18         [87.98.215.224])\r
19         (using TLSv1 with cipher DHE-RSA-AES128-SHA (128/128 bits))\r
20         (No client certificate requested)\r
21         by olra.theworths.org (Postfix) with ESMTPS id F2561431FC9\r
22         for <notmuch@notmuchmail.org>; Fri, 27 Mar 2015 15:13:19 -0700 (PDT)\r
23 Received: from remotemail by mx.xen14.node3324.gplhost.com with local (Exim\r
24         4.80) (envelope-from <bremner@tesseract.cs.unb.ca>)\r
25         id 1YbcUV-0000EQ-ME; Fri, 27 Mar 2015 22:12:35 +0000\r
26 Received: (nullmailer pid 1813 invoked by uid 1000); Fri, 27 Mar 2015\r
27         22:12:15 -0000\r
28 From: David Bremner <david@tethera.net>\r
29 To: notmuch@notmuchmail.org\r
30 Subject: [Patch v6 4/8] lib: add "verbose" versions of\r
31         notmuch_database_{open,create}\r
32 Date: Fri, 27 Mar 2015 23:11:56 +0100\r
33 Message-Id: <1427494320-1483-5-git-send-email-david@tethera.net>\r
34 X-Mailer: git-send-email 2.1.4\r
35 In-Reply-To: <1427494320-1483-1-git-send-email-david@tethera.net>\r
36 References: <1427494320-1483-1-git-send-email-david@tethera.net>\r
37 X-BeenThere: notmuch@notmuchmail.org\r
38 X-Mailman-Version: 2.1.13\r
39 Precedence: list\r
40 List-Id: "Use and development of the notmuch mail system."\r
41         <notmuch.notmuchmail.org>\r
42 List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,\r
43         <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>\r
44 List-Archive: <http://notmuchmail.org/pipermail/notmuch>\r
45 List-Post: <mailto:notmuch@notmuchmail.org>\r
46 List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>\r
47 List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,\r
48         <mailto:notmuch-request@notmuchmail.org?subject=subscribe>\r
49 X-List-Received-Date: Fri, 27 Mar 2015 22:13:22 -0000\r
50 \r
51 The compatibility wrapper ensures that clients calling\r
52 notmuch_database_open will receive consistent output for now.\r
53 \r
54 The changes to notmuch-{new,search} and test/symbol-test are just to\r
55 make the test suite pass.\r
56 \r
57 The use of IGNORE_RESULT is justified by two things. 1) I don't know\r
58 what else to do.  2) asprintf guarantees the output string is NULL if\r
59 an error occurs, so at least we are not passing garbage back.\r
60 ---\r
61  lib/database.cc     | 109 ++++++++++++++++++++++++++++++++++++++--------------\r
62  lib/notmuch.h       |  21 ++++++++++\r
63  notmuch-new.c       |  11 +++++-\r
64  notmuch-search.c    |  13 ++++++-\r
65  test/symbol-test.cc |   9 ++++-\r
66  5 files changed, 130 insertions(+), 33 deletions(-)\r
67 \r
68 diff --git a/lib/database.cc b/lib/database.cc\r
69 index 3974e2e..5d973b9 100644\r
70 --- a/lib/database.cc\r
71 +++ b/lib/database.cc\r
72 @@ -608,29 +608,50 @@ parse_references (void *ctx,\r
73  notmuch_status_t\r
74  notmuch_database_create (const char *path, notmuch_database_t **database)\r
75  {\r
76 +    char *status_string = NULL;\r
77 +    notmuch_status_t status;\r
78 +\r
79 +    status = notmuch_database_create_verbose (path, database,\r
80 +                                             &status_string);\r
81 +\r
82 +    if (status_string) {\r
83 +       fputs (status_string, stderr);\r
84 +       free (status_string);\r
85 +    }\r
86 +\r
87 +    return status;\r
88 +}\r
89 +\r
90 +notmuch_status_t\r
91 +notmuch_database_create_verbose (const char *path,\r
92 +                                notmuch_database_t **database,\r
93 +                                char **status_string)\r
94 +{\r
95      notmuch_status_t status = NOTMUCH_STATUS_SUCCESS;\r
96      notmuch_database_t *notmuch = NULL;\r
97      char *notmuch_path = NULL;\r
98 +    char *message = NULL;\r
99      struct stat st;\r
100      int err;\r
101  \r
102      if (path == NULL) {\r
103 -       fprintf (stderr, "Error: Cannot create a database for a NULL path.\n");\r
104 +       message = strdup ("Error: Cannot create a database for a NULL path.\n");\r
105         status = NOTMUCH_STATUS_NULL_POINTER;\r
106         goto DONE;\r
107      }\r
108  \r
109      err = stat (path, &st);\r
110      if (err) {\r
111 -       fprintf (stderr, "Error: Cannot create database at %s: %s.\n",\r
112 -                path, strerror (errno));\r
113 +       IGNORE_RESULT (asprintf (&message, "Error: Cannot create database at %s: %s.\n",\r
114 +                               path, strerror (errno)));\r
115         status = NOTMUCH_STATUS_FILE_ERROR;\r
116         goto DONE;\r
117      }\r
118  \r
119      if (! S_ISDIR (st.st_mode)) {\r
120 -       fprintf (stderr, "Error: Cannot create database at %s: Not a directory.\n",\r
121 -                path);\r
122 +       IGNORE_RESULT (asprintf (&message, "Error: Cannot create database at %s: "\r
123 +                                "Not a directory.\n",\r
124 +                                path));\r
125         status = NOTMUCH_STATUS_FILE_ERROR;\r
126         goto DONE;\r
127      }\r
128 @@ -640,15 +661,15 @@ notmuch_database_create (const char *path, notmuch_database_t **database)\r
129      err = mkdir (notmuch_path, 0755);\r
130  \r
131      if (err) {\r
132 -       fprintf (stderr, "Error: Cannot create directory %s: %s.\n",\r
133 -                notmuch_path, strerror (errno));\r
134 +       IGNORE_RESULT (asprintf (&message, "Error: Cannot create directory %s: %s.\n",\r
135 +                                notmuch_path, strerror (errno)));\r
136         status = NOTMUCH_STATUS_FILE_ERROR;\r
137         goto DONE;\r
138      }\r
139  \r
140 -    status = notmuch_database_open (path,\r
141 -                                   NOTMUCH_DATABASE_MODE_READ_WRITE,\r
142 -                                   &notmuch);\r
143 +    status = notmuch_database_open_verbose (path,\r
144 +                                           NOTMUCH_DATABASE_MODE_READ_WRITE,\r
145 +                                           &notmuch, &message);\r
146      if (status)\r
147         goto DONE;\r
148  \r
149 @@ -667,6 +688,9 @@ notmuch_database_create (const char *path, notmuch_database_t **database)\r
150      if (notmuch_path)\r
151         talloc_free (notmuch_path);\r
152  \r
153 +    if (status_string && message)\r
154 +       *status_string = message;\r
155 +\r
156      if (database)\r
157         *database = notmuch;\r
158      else\r
159 @@ -767,37 +791,58 @@ notmuch_database_open (const char *path,\r
160                        notmuch_database_mode_t mode,\r
161                        notmuch_database_t **database)\r
162  {\r
163 +    char *status_string = NULL;\r
164 +    notmuch_status_t status;\r
165 +\r
166 +    status = notmuch_database_open_verbose (path, mode, database,\r
167 +                                          &status_string);\r
168 +\r
169 +    if (status_string) {\r
170 +       fputs (status_string, stderr);\r
171 +       free (status_string);\r
172 +    }\r
173 +\r
174 +    return status;\r
175 +}\r
176 +\r
177 +notmuch_status_t\r
178 +notmuch_database_open_verbose (const char *path,\r
179 +                              notmuch_database_mode_t mode,\r
180 +                              notmuch_database_t **database,\r
181 +                              char **status_string)\r
182 +{\r
183      notmuch_status_t status = NOTMUCH_STATUS_SUCCESS;\r
184      void *local = talloc_new (NULL);\r
185      notmuch_database_t *notmuch = NULL;\r
186      char *notmuch_path, *xapian_path, *incompat_features;\r
187 +    char *message = NULL;\r
188      struct stat st;\r
189      int err;\r
190      unsigned int i, version;\r
191      static int initialized = 0;\r
192  \r
193      if (path == NULL) {\r
194 -       fprintf (stderr, "Error: Cannot open a database for a NULL path.\n");\r
195 +       message = strdup ("Error: Cannot open a database for a NULL path.\n");\r
196         status = NOTMUCH_STATUS_NULL_POINTER;\r
197         goto DONE;\r
198      }\r
199  \r
200      if (! (notmuch_path = talloc_asprintf (local, "%s/%s", path, ".notmuch"))) {\r
201 -       fprintf (stderr, "Out of memory\n");\r
202 +       message = strdup ("Out of memory\n");\r
203         status = NOTMUCH_STATUS_OUT_OF_MEMORY;\r
204         goto DONE;\r
205      }\r
206  \r
207      err = stat (notmuch_path, &st);\r
208      if (err) {\r
209 -       fprintf (stderr, "Error opening database at %s: %s\n",\r
210 -                notmuch_path, strerror (errno));\r
211 +       IGNORE_RESULT (asprintf (&message, "Error opening database at %s: %s\n",\r
212 +                                notmuch_path, strerror (errno)));\r
213         status = NOTMUCH_STATUS_FILE_ERROR;\r
214         goto DONE;\r
215      }\r
216  \r
217      if (! (xapian_path = talloc_asprintf (local, "%s/%s", notmuch_path, "xapian"))) {\r
218 -       fprintf (stderr, "Out of memory\n");\r
219 +       message = strdup ("Out of memory\n");\r
220         status = NOTMUCH_STATUS_OUT_OF_MEMORY;\r
221         goto DONE;\r
222      }\r
223 @@ -837,11 +882,11 @@ notmuch_database_open (const char *path,\r
224          * means a dramatically incompatible change. */\r
225         version = notmuch_database_get_version (notmuch);\r
226         if (version > NOTMUCH_DATABASE_VERSION) {\r
227 -           fprintf (stderr,\r
228 -                    "Error: Notmuch database at %s\n"\r
229 -                    "       has a newer database format version (%u) than supported by this\n"\r
230 -                    "       version of notmuch (%u).\n",\r
231 -                    notmuch_path, version, NOTMUCH_DATABASE_VERSION);\r
232 +           IGNORE_RESULT (asprintf (&message,\r
233 +                     "Error: Notmuch database at %s\n"\r
234 +                     "       has a newer database format version (%u) than supported by this\n"\r
235 +                     "       version of notmuch (%u).\n",\r
236 +                                    notmuch_path, version, NOTMUCH_DATABASE_VERSION));\r
237             notmuch->mode = NOTMUCH_DATABASE_MODE_READ_ONLY;\r
238             notmuch_database_destroy (notmuch);\r
239             notmuch = NULL;\r
240 @@ -856,11 +901,11 @@ notmuch_database_open (const char *path,\r
241             version, mode == NOTMUCH_DATABASE_MODE_READ_WRITE ? 'w' : 'r',\r
242             &incompat_features);\r
243         if (incompat_features) {\r
244 -           fprintf (stderr,\r
245 -                    "Error: Notmuch database at %s\n"\r
246 -                    "       requires features (%s)\n"\r
247 -                    "       not supported by this version of notmuch.\n",\r
248 -                    notmuch_path, incompat_features);\r
249 +           IGNORE_RESULT (asprintf (&message,\r
250 +               "Error: Notmuch database at %s\n"\r
251 +               "       requires features (%s)\n"\r
252 +               "       not supported by this version of notmuch.\n",\r
253 +                                    notmuch_path, incompat_features));\r
254             notmuch->mode = NOTMUCH_DATABASE_MODE_READ_ONLY;\r
255             notmuch_database_destroy (notmuch);\r
256             notmuch = NULL;\r
257 @@ -906,8 +951,8 @@ notmuch_database_open (const char *path,\r
258             notmuch->query_parser->add_prefix (prefix->name, prefix->prefix);\r
259         }\r
260      } catch (const Xapian::Error &error) {\r
261 -       fprintf (stderr, "A Xapian exception occurred opening database: %s\n",\r
262 -                error.get_msg().c_str());\r
263 +       IGNORE_RESULT (asprintf (&message, "A Xapian exception occurred opening database: %s\n",\r
264 +                                error.get_msg().c_str()));\r
265         notmuch_database_destroy (notmuch);\r
266         notmuch = NULL;\r
267         status = NOTMUCH_STATUS_XAPIAN_EXCEPTION;\r
268 @@ -916,6 +961,9 @@ notmuch_database_open (const char *path,\r
269    DONE:\r
270      talloc_free (local);\r
271  \r
272 +    if (status_string && message)\r
273 +       *status_string = message;\r
274 +\r
275      if (database)\r
276         *database = notmuch;\r
277      else\r
278 @@ -1039,13 +1087,18 @@ notmuch_database_compact (const char *path,\r
279      notmuch_database_t *notmuch = NULL;\r
280      struct stat statbuf;\r
281      notmuch_bool_t keep_backup;\r
282 +    char *message = NULL;\r
283  \r
284      local = talloc_new (NULL);\r
285      if (! local)\r
286         return NOTMUCH_STATUS_OUT_OF_MEMORY;\r
287  \r
288 -    ret = notmuch_database_open (path, NOTMUCH_DATABASE_MODE_READ_WRITE, &notmuch);\r
289 +    ret = notmuch_database_open_verbose (path,\r
290 +                                        NOTMUCH_DATABASE_MODE_READ_WRITE,\r
291 +                                        &notmuch,\r
292 +                                        &message);\r
293      if (ret) {\r
294 +       if (status_cb) status_cb (message, closure);\r
295         goto DONE;\r
296      }\r
297  \r
298 diff --git a/lib/notmuch.h b/lib/notmuch.h\r
299 index f066245..c671d82 100644\r
300 --- a/lib/notmuch.h\r
301 +++ b/lib/notmuch.h\r
302 @@ -230,6 +230,16 @@ notmuch_status_t\r
303  notmuch_database_create (const char *path, notmuch_database_t **database);\r
304  \r
305  /**\r
306 + * Like notmuch_database_create, except optionally return an error\r
307 + * message. This message is allocated by malloc and should be freed by\r
308 + * the caller.\r
309 + */\r
310 +notmuch_status_t\r
311 +notmuch_database_create_verbose (const char *path,\r
312 +                                notmuch_database_t **database,\r
313 +                                char **error_message);\r
314 +\r
315 +/**\r
316   * Database open mode for notmuch_database_open.\r
317   */\r
318  typedef enum {\r
319 @@ -279,6 +289,17 @@ notmuch_status_t\r
320  notmuch_database_open (const char *path,\r
321                        notmuch_database_mode_t mode,\r
322                        notmuch_database_t **database);\r
323 +/**\r
324 + * Like notmuch_database_open, except optionally return an error\r
325 + * message. This message is allocated by malloc and should be freed by\r
326 + * the caller.\r
327 + */\r
328 +\r
329 +notmuch_status_t\r
330 +notmuch_database_open_verbose (const char *path,\r
331 +                              notmuch_database_mode_t mode,\r
332 +                              notmuch_database_t **database,\r
333 +                              char **error_message);\r
334  \r
335  /**\r
336   * Commit changes and close the given notmuch database.\r
337 diff --git a/notmuch-new.c b/notmuch-new.c\r
338 index ddf42c1..e6c283e 100644\r
339 --- a/notmuch-new.c\r
340 +++ b/notmuch-new.c\r
341 @@ -985,9 +985,16 @@ notmuch_new_command (notmuch_config_t *config, int argc, char *argv[])\r
342             return EXIT_FAILURE;\r
343         add_files_state.total_files = count;\r
344      } else {\r
345 -       if (notmuch_database_open (db_path, NOTMUCH_DATABASE_MODE_READ_WRITE,\r
346 -                                  &notmuch))\r
347 +       char *status_string = NULL;\r
348 +       if (notmuch_database_open_verbose (db_path, NOTMUCH_DATABASE_MODE_READ_WRITE,\r
349 +                                          &notmuch, &status_string)) {\r
350 +           if (status_string) {\r
351 +               fputs (status_string, stderr);\r
352 +               free (status_string);\r
353 +           }\r
354 +\r
355             return EXIT_FAILURE;\r
356 +       }\r
357  \r
358         if (notmuch_database_needs_upgrade (notmuch)) {\r
359             time_t now = time (NULL);\r
360 diff --git a/notmuch-search.c b/notmuch-search.c\r
361 index a591d45..b81ac01 100644\r
362 --- a/notmuch-search.c\r
363 +++ b/notmuch-search.c\r
364 @@ -545,6 +545,7 @@ _notmuch_search_prepare (search_context_t *ctx, notmuch_config_t *config, int ar\r
365  {\r
366      char *query_str;\r
367      unsigned int i;\r
368 +    char *status_string = NULL;\r
369  \r
370      switch (ctx->format_sel) {\r
371      case NOTMUCH_FORMAT_TEXT:\r
372 @@ -570,9 +571,17 @@ _notmuch_search_prepare (search_context_t *ctx, notmuch_config_t *config, int ar\r
373  \r
374      notmuch_exit_if_unsupported_format ();\r
375  \r
376 -    if (notmuch_database_open (notmuch_config_get_database_path (config),\r
377 -                              NOTMUCH_DATABASE_MODE_READ_ONLY, &ctx->notmuch))\r
378 +    if (notmuch_database_open_verbose (\r
379 +           notmuch_config_get_database_path (config),\r
380 +           NOTMUCH_DATABASE_MODE_READ_ONLY, &ctx->notmuch, &status_string)) {\r
381 +\r
382 +       if (status_string) {\r
383 +           fputs (status_string, stderr);\r
384 +           free (status_string);\r
385 +       }\r
386 +\r
387         return EXIT_FAILURE;\r
388 +    }\r
389  \r
390      query_str = query_string_from_args (ctx->notmuch, argc, argv);\r
391      if (query_str == NULL) {\r
392 diff --git a/test/symbol-test.cc b/test/symbol-test.cc\r
393 index 3e96c03..d979f83 100644\r
394 --- a/test/symbol-test.cc\r
395 +++ b/test/symbol-test.cc\r
396 @@ -1,11 +1,18 @@\r
397  #include <stdio.h>\r
398 +#include <stdlib.h>\r
399  #include <xapian.h>\r
400  #include <notmuch.h>\r
401  \r
402  \r
403  int main() {\r
404    notmuch_database_t *notmuch;\r
405 -  notmuch_database_open("fakedb", NOTMUCH_DATABASE_MODE_READ_ONLY, &notmuch);\r
406 +  char *message = NULL;\r
407 +\r
408 +  if (notmuch_database_open_verbose  ("fakedb", NOTMUCH_DATABASE_MODE_READ_ONLY, &notmuch, &message))\r
409 +      if (message) {\r
410 +         fputs (message, stderr);\r
411 +         free (message);\r
412 +      }\r
413  \r
414    try {\r
415      (void) new Xapian::WritableDatabase("./nonexistant", Xapian::DB_OPEN);\r
416 -- \r
417 2.1.4\r
418 \r