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