Re: [PATCH 0/4] Allow specifying alternate names for addresses in other_email
[notmuch-archives.git] / 97 / 57f3b4739ea3b6500bd57d7d9968248502e45b
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 olra.theworths.org (Postfix) with ESMTP id 3C43D431FB6\r
6         for <notmuch@notmuchmail.org>; Sat, 23 Aug 2014 09:02:50 -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: -0.7\r
10 X-Spam-Level: \r
11 X-Spam-Status: No, score=-0.7 tagged_above=-999 required=5\r
12         tests=[RCVD_IN_DNSWL_LOW=-0.7] 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 bPYCnr-aBRuP for <notmuch@notmuchmail.org>;\r
16         Sat, 23 Aug 2014 09:02:43 -0700 (PDT)\r
17 Received: from mail-wi0-f171.google.com (mail-wi0-f171.google.com\r
18         [209.85.212.171]) (using TLSv1 with cipher RC4-SHA (128/128 bits))\r
19         (No client certificate requested)\r
20         by olra.theworths.org (Postfix) with ESMTPS id A3418431FAF\r
21         for <notmuch@notmuchmail.org>; Sat, 23 Aug 2014 09:02:42 -0700 (PDT)\r
22 Received: by mail-wi0-f171.google.com with SMTP id hi2so844068wib.16\r
23         for <notmuch@notmuchmail.org>; Sat, 23 Aug 2014 09:02:41 -0700 (PDT)\r
24 X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;\r
25         d=1e100.net; s=20130820;\r
26         h=x-gm-message-state:from:to:subject:in-reply-to:references\r
27         :user-agent:date:message-id:mime-version:content-type;\r
28         bh=UE6h6AnDwL0D9gvGPUnAfS5fKTsOKdPfacIwzt7V7KQ=;\r
29         b=bzetmBlRlQOizY3PhWhAoo3cE+VP6iv+c+q2bn4CVIYwAXAYHpYueHY96rRRHC3qMQ\r
30         3El5ND4wAkUXGBCR8I3vbIhXccGeoXiskKsx/yttIoCQkzljuZQficEf/3gOmZ1r1h17\r
31         W0xB28/GA8DPF3LlC4E9HwuSLYHjxcj89fYbqBqei0lshMUQ5kfWWzvg2eu3OclK9RGI\r
32         JnS0tyM1VsOZKHK1otA3ujlNbHOQ+NHYIrzTXfByXa8czh1vlXkROoVp+sNavLVNqusL\r
33         HZbjilh5rssqaMux0tJB3nJXU1/LbDG2dVr32gDkpvcqJXAHct4KJj0ZWUkUCEVWVhhn\r
34         5mYA==\r
35 X-Gm-Message-State:\r
36  ALoCoQnXOVuCL3NVkQr9Oi1AaSAVu6EDqFqIxXBXFKLbjPSirI0noI/6Tun+6U6tXGxn8ZDARVBk\r
37 X-Received: by 10.180.21.101 with SMTP id u5mr4647284wie.68.1408809761398;\r
38         Sat, 23 Aug 2014 09:02:41 -0700 (PDT)\r
39 Received: from localhost (dsl-hkibrasgw2-58c374-75.dhcp.inet.fi.\r
40         [88.195.116.75]) by mx.google.com with ESMTPSA id\r
41         y10sm10563955wie.18.2014.08.23.09.02.39 for <multiple recipients>\r
42         (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128);\r
43         Sat, 23 Aug 2014 09:02:40 -0700 (PDT)\r
44 From: Jani Nikula <jani@nikula.org>\r
45 To: Austin Clements <amdragon@MIT.EDU>, notmuch@notmuchmail.org\r
46 Subject: Re: [PATCH v3 04/13] lib: Database version 3: Introduce\r
47         fine-grained    "features"\r
48 In-Reply-To: <1406859003-11561-5-git-send-email-amdragon@mit.edu>\r
49 References: <1406859003-11561-1-git-send-email-amdragon@mit.edu>\r
50         <1406859003-11561-5-git-send-email-amdragon@mit.edu>\r
51 User-Agent: Notmuch/0.18.1+65~g9f0f30f (http://notmuchmail.org) Emacs/24.3.1\r
52         (x86_64-pc-linux-gnu)\r
53 Date: Sat, 23 Aug 2014 19:02:39 +0300\r
54 Message-ID: <87r407jisg.fsf@nikula.org>\r
55 MIME-Version: 1.0\r
56 Content-Type: text/plain\r
57 X-BeenThere: notmuch@notmuchmail.org\r
58 X-Mailman-Version: 2.1.13\r
59 Precedence: list\r
60 List-Id: "Use and development of the notmuch mail system."\r
61         <notmuch.notmuchmail.org>\r
62 List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,\r
63         <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>\r
64 List-Archive: <http://notmuchmail.org/pipermail/notmuch>\r
65 List-Post: <mailto:notmuch@notmuchmail.org>\r
66 List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>\r
67 List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,\r
68         <mailto:notmuch-request@notmuchmail.org?subject=subscribe>\r
69 X-List-Received-Date: Sat, 23 Aug 2014 16:02:50 -0000\r
70 \r
71 On Fri, 01 Aug 2014, Austin Clements <amdragon@MIT.EDU> wrote:\r
72 > Previously, our database schema was versioned by a single number.\r
73 > Each database schema change had to occur "atomically" in Notmuch's\r
74 > development history: before some commit, Notmuch used version N, after\r
75 > that commit, it used version N+1.  Hence, each new schema version\r
76 > could introduce only one change, the task of developing a schema\r
77 > change fell on a single person, and it all had to happen and be\r
78 > perfect in a single commit series.  This made introducing a new schema\r
79 > version hard.  We've seen only two schema changes in the history of\r
80 > Notmuch.\r
81 >\r
82 > This commit introduces database schema version 3; hopefully the last\r
83 > schema version we'll need for a while.  With this version, we switch\r
84 > from a single version number to "features": a set of named,\r
85 > independent aspects of the database schema.\r
86 >\r
87 > Features should make backwards compatibility easier.  For many things,\r
88 > it should be easy to support databases both with and without a\r
89 > feature, which will allow us to make upgrades optional and will enable\r
90 > "unstable" features that can be developed and tested over time.\r
91 >\r
92 > Features also make forwards compatibility easier.  The features\r
93 > recorded in a database include "compatibility flags," which can\r
94 > indicate to an older version of Notmuch when it must support a given\r
95 > feature to open the database for read or for write.  This lets us\r
96 > replace the old vague "I don't recognize this version, so something\r
97 > might go wrong, but I promise to try my best" warnings upon opening a\r
98 > database with an unknown version with precise errors.  If a database\r
99 > is safe to open for read/write despite unknown features, an older\r
100 > version will know that and issue no message at all.  If the database\r
101 > is not safe to open for read/write because of unknown features, an\r
102 > older version will know that, too, and can tell the user exactly which\r
103 > required features it lacks support for.\r
104 \r
105 I agree with the change overall; it might be useful to have another set\r
106 of eyes on the patch though.\r
107 \r
108 > ---\r
109 >  lib/database-private.h |  57 ++++++++++++++-\r
110 >  lib/database.cc        | 190 ++++++++++++++++++++++++++++++++++++++++---------\r
111 >  2 files changed, 213 insertions(+), 34 deletions(-)\r
112 >\r
113 > diff --git a/lib/database-private.h b/lib/database-private.h\r
114 > index d3e65fd..2ffab33 100644\r
115 > --- a/lib/database-private.h\r
116 > +++ b/lib/database-private.h\r
117 > @@ -41,11 +41,15 @@ struct _notmuch_database {\r
118 >  \r
119 >      char *path;\r
120 >  \r
121 > -    notmuch_bool_t needs_upgrade;\r
122 >      notmuch_database_mode_t mode;\r
123 >      int atomic_nesting;\r
124 >      Xapian::Database *xapian_db;\r
125 >  \r
126 > +    /* Bit mask of features used by this database.  Features are\r
127 > +     * named, independent aspects of the database schema.  This is a\r
128 > +     * bitwise-OR of NOTMUCH_FEATURE_* values (below). */\r
129 > +    unsigned int features;\r
130 > +\r
131 >      unsigned int last_doc_id;\r
132 >      uint64_t last_thread_id;\r
133 >  \r
134 > @@ -55,6 +59,57 @@ struct _notmuch_database {\r
135 >      Xapian::ValueRangeProcessor *date_range_processor;\r
136 >  };\r
137 >  \r
138 > +/* Bit masks for _notmuch_database::features. */\r
139 > +enum {\r
140 > +    /* If set, file names are stored in "file-direntry" terms.  If\r
141 > +     * unset, file names are stored in document data.\r
142 > +     *\r
143 > +     * Introduced: version 1.  Implementation support: both for read;\r
144 > +     * required for write. */\r
145 \r
146 Maybe I'm dense, but the implementation support comments could be\r
147 clearer.\r
148 \r
149 > +    NOTMUCH_FEATURE_FILE_TERMS = 1 << 0,\r
150 > +\r
151 > +    /* If set, directory timestamps are stored in documents with\r
152 > +     * XDIRECTORY terms and relative paths.  If unset, directory\r
153 > +     * timestamps are stored in documents with XTIMESTAMP terms and\r
154 > +     * absolute paths.\r
155 > +     *\r
156 > +     * Introduced: version 1.  Implementation support: required. */\r
157 > +    NOTMUCH_FEATURE_DIRECTORY_DOCS = 1 << 1,\r
158 > +\r
159 > +    /* If set, the from, subject, and message-id headers are stored in\r
160 > +     * message document values.  If unset, message documents *may*\r
161 > +     * have these values, but if the value is empty, it must be\r
162 > +     * retrieved from the message file.\r
163 > +     *\r
164 > +     * Introduced: optional in version 1, required as of version 3.\r
165 > +     * Implementation support: both.\r
166 > +     */\r
167 > +    NOTMUCH_FEATURE_FROM_SUBJECT_ID_VALUES = 1 << 2,\r
168 > +\r
169 > +    /* If set, folder terms are boolean and path terms exist.  If\r
170 > +     * unset, folder terms are probabilistic and stemmed and path\r
171 > +     * terms do not exist.\r
172 > +     *\r
173 > +     * Introduced: version 2.  Implementation support: required. */\r
174 > +    NOTMUCH_FEATURE_BOOL_FOLDER = 1 << 3,\r
175 > +};\r
176 > +\r
177 > +/* Prior to database version 3, features were implied by the database\r
178 > + * version number, so hard-code them for earlier versions. */\r
179 > +#define NOTMUCH_FEATURES_V0 (0)\r
180 > +#define NOTMUCH_FEATURES_V1 (NOTMUCH_FEATURES_V0 | NOTMUCH_FEATURE_FILE_TERMS | \\r
181 > +                          NOTMUCH_FEATURE_DIRECTORY_DOCS)\r
182 > +#define NOTMUCH_FEATURES_V2 (NOTMUCH_FEATURES_V1 | NOTMUCH_FEATURE_BOOL_FOLDER)\r
183 > +\r
184 > +/* Current database features.  If any of these are missing from a\r
185 > + * database, request an upgrade.\r
186 > + * NOTMUCH_FEATURE_FROM_SUBJECT_ID_VALUES is not included because\r
187 > + * upgrade doesn't currently introduce the feature (though brand new\r
188 > + * databases will have it). */\r
189 > +#define NOTMUCH_FEATURES_CURRENT \\r
190 > +    (NOTMUCH_FEATURE_FILE_TERMS | NOTMUCH_FEATURE_DIRECTORY_DOCS | \\r
191 > +     NOTMUCH_FEATURE_BOOL_FOLDER)\r
192 > +\r
193 >  /* Return the list of terms from the given iterator matching a prefix.\r
194 >   * The prefix will be stripped from the strings in the returned list.\r
195 >   * The list will be allocated using ctx as the talloc context.\r
196 > diff --git a/lib/database.cc b/lib/database.cc\r
197 > index 45c4260..29a56db 100644\r
198 > --- a/lib/database.cc\r
199 > +++ b/lib/database.cc\r
200 > @@ -20,6 +20,7 @@\r
201 >  \r
202 >  #include "database-private.h"\r
203 >  #include "parse-time-vrp.h"\r
204 > +#include "string-util.h"\r
205 >  \r
206 >  #include <iostream>\r
207 >  \r
208 > @@ -42,7 +43,7 @@ typedef struct {\r
209 >      const char *prefix;\r
210 >  } prefix_t;\r
211 >  \r
212 > -#define NOTMUCH_DATABASE_VERSION 2\r
213 > +#define NOTMUCH_DATABASE_VERSION 3\r
214 >  \r
215 >  #define STRINGIFY(s) _SUB_STRINGIFY(s)\r
216 >  #define _SUB_STRINGIFY(s) #s\r
217 > @@ -151,6 +152,17 @@ typedef struct {\r
218 >   *                   changes are made to the database (such as by\r
219 >   *                   indexing new fields).\r
220 >   *\r
221 > + *   features        The set of features supported by this\r
222 > + *                   database. This consists of a set of\r
223 > + *                   '\n'-separated lines, where each is a feature\r
224 > + *                   name, a '\t', and compatibility flags.  If the\r
225 > + *                   compatibility flags contain 'w', then the\r
226 > + *                   opener must support this feature to safely\r
227 > + *                   write this database.  If the compatibility\r
228 > + *                   flags contain 'r', then the opener must\r
229 > + *                   support this feature to read this database.\r
230 > + *                   Introduced in database version 3.\r
231 > + *\r
232 >   *   last_thread_id  The last thread ID generated. This is stored\r
233 >   *                   as a 16-byte hexadecimal ASCII representation\r
234 >   *                   of a 64-bit unsigned integer. The first ID\r
235 > @@ -251,6 +263,25 @@ _find_prefix (const char *name)\r
236 >      return "";\r
237 >  }\r
238 >  \r
239 > +static const struct\r
240 > +{\r
241 \r
242 Brace should be at the end of the previous line.\r
243 \r
244 > +    /* NOTMUCH_FEATURE_* value. */\r
245 > +    unsigned int value;\r
246 > +    /* Feature name as it appears in the database.  This name should\r
247 > +     * be appropriate for displaying to the user if an older version\r
248 > +     * of notmuch doesn't support this feature. */\r
249 > +    const char *name;\r
250 > +    /* Compatibility flags when this feature is declared. */\r
251 > +    const char *flags;\r
252 > +} feature_names[] = {\r
253 > +    {NOTMUCH_FEATURE_FILE_TERMS,             "multiple paths per message", "rw"},\r
254 > +    {NOTMUCH_FEATURE_DIRECTORY_DOCS,         "relative directory paths", "rw"},\r
255 > +    /* Header values are not required for reading a database because a\r
256 > +     * reader can just refer to the message file. */\r
257 > +    {NOTMUCH_FEATURE_FROM_SUBJECT_ID_VALUES, "from/subject/message-ID in database", "w"},\r
258 > +    {NOTMUCH_FEATURE_BOOL_FOLDER,            "exact folder:/path: search", "rw"},\r
259 \r
260 Spaces missing after the opening braces and before the closing braces.\r
261 \r
262 > +};\r
263 > +\r
264 >  const char *\r
265 >  notmuch_status_to_string (notmuch_status_t status)\r
266 >  {\r
267 > @@ -591,6 +622,11 @@ notmuch_database_create (const char *path, notmuch_database_t **database)\r
268 >                                   &notmuch);\r
269 >      if (status)\r
270 >       goto DONE;\r
271 > +\r
272 > +    /* Upgrade doesn't add this feature to existing databases, but new\r
273 > +     * databases have it. */\r
274 > +    notmuch->features |= NOTMUCH_FEATURE_FROM_SUBJECT_ID_VALUES;\r
275 > +\r
276 >      status = notmuch_database_upgrade (notmuch, NULL, NULL);\r
277 >      if (status) {\r
278 >       notmuch_database_close(notmuch);\r
279 > @@ -619,6 +655,80 @@ _notmuch_database_ensure_writable (notmuch_database_t *notmuch)\r
280 >      return NOTMUCH_STATUS_SUCCESS;\r
281 >  }\r
282 >  \r
283 > +/* Parse a database features string from the given database version.\r
284 > + *\r
285 > + * For version < 3, this ignores the features string and returns a\r
286 > + * hard-coded set of features.\r
287 > + *\r
288 > + * If there are unrecognized features that are required to open the\r
289 > + * database in mode (which should be 'r' or 'w'), return a\r
290 > + * comma-separated list of unrecognized but required features in\r
291 > + * *incompat_out, which will be allocated from ctx.\r
292 \r
293 Please describe the actual return value.\r
294 \r
295 > + */\r
296 > +static unsigned int\r
297 > +_parse_features (const void *ctx, const char *features, unsigned int version,\r
298 > +              char mode, char **incompat_out)\r
299 > +{\r
300 > +    unsigned int res = 0, namelen, i;\r
301 > +    size_t llen = 0;\r
302 > +    const char *flags;\r
303 > +\r
304 > +    /* Prior to database version 3, features were implied by the\r
305 > +     * version number. */\r
306 > +    if (version == 0)\r
307 > +     return NOTMUCH_FEATURES_V0;\r
308 > +    else if (version == 1)\r
309 > +     return NOTMUCH_FEATURES_V1;\r
310 > +    else if (version == 2)\r
311 > +     return NOTMUCH_FEATURES_V2;\r
312 > +\r
313 > +    /* Parse the features string */\r
314 > +    while ((features = strtok_len_c (features + llen, "\n", &llen)) != NULL) {\r
315 > +     flags = strchr (features, '\t');\r
316 > +     if (! flags || flags > features + llen)\r
317 > +         continue;\r
318 > +     namelen = flags - features;\r
319 > +\r
320 > +     for (i = 0; i < ARRAY_SIZE (feature_names); ++i) {\r
321 > +         if (strlen (feature_names[i].name) == namelen &&\r
322 > +             strncmp (feature_names[i].name, features, namelen) == 0) {\r
323 > +             res |= feature_names[i].value;\r
324 > +             break;\r
325 > +         }\r
326 > +     }\r
327 > +\r
328 > +     if (i == ARRAY_SIZE (feature_names)) {\r
329 > +         /* Unrecognized feature */\r
330 > +         const char *have = strchr (flags, mode);\r
331 > +         if (have && have < features + llen) {\r
332 > +             /* This feature is required to access this database in\r
333 > +              * 'mode', but we don't understand it. */\r
334 > +             if (! *incompat_out)\r
335 > +                 *incompat_out = talloc_strdup (ctx, "");\r
336 > +             *incompat_out = talloc_asprintf_append_buffer (\r
337 > +                 *incompat_out, "%s%.*s", **incompat_out ? ", " : "",\r
338 > +                 namelen, features);\r
339 \r
340 Do we intend the lib user to be able to parse the features? Perhaps we\r
341 should use '\n' as separator here too? (Although looks like *currently*\r
342 this is only for printing the message from within the lib.)\r
343 \r
344 > +         }\r
345 > +     }\r
346 > +    }\r
347 > +\r
348 > +    return res;\r
349 > +}\r
350 > +\r
351 > +static char *\r
352 > +_print_features (const void *ctx, unsigned int features)\r
353 > +{\r
354 > +    unsigned int i;\r
355 > +    char *res = talloc_strdup (ctx, "");\r
356 > +\r
357 > +    for (i = 0; i < ARRAY_SIZE (feature_names); ++i)\r
358 > +     if (features & feature_names[i].value)\r
359 > +         res = talloc_asprintf_append_buffer (\r
360 > +             res, "%s\t%s\n", feature_names[i].name, feature_names[i].flags);\r
361 > +\r
362 > +    return res;\r
363 > +}\r
364 > +\r
365 >  notmuch_status_t\r
366 >  notmuch_database_open (const char *path,\r
367 >                      notmuch_database_mode_t mode,\r
368 > @@ -627,7 +737,7 @@ notmuch_database_open (const char *path,\r
369 >      notmuch_status_t status = NOTMUCH_STATUS_SUCCESS;\r
370 >      void *local = talloc_new (NULL);\r
371 >      notmuch_database_t *notmuch = NULL;\r
372 > -    char *notmuch_path, *xapian_path;\r
373 > +    char *notmuch_path, *xapian_path, *incompat_features;\r
374 >      struct stat st;\r
375 >      int err;\r
376 >      unsigned int i, version;\r
377 > @@ -677,7 +787,6 @@ notmuch_database_open (const char *path,\r
378 >      if (notmuch->path[strlen (notmuch->path) - 1] == '/')\r
379 >       notmuch->path[strlen (notmuch->path) - 1] = '\0';\r
380 >  \r
381 > -    notmuch->needs_upgrade = FALSE;\r
382 >      notmuch->mode = mode;\r
383 >      notmuch->atomic_nesting = 0;\r
384 >      try {\r
385 > @@ -686,37 +795,44 @@ notmuch_database_open (const char *path,\r
386 >       if (mode == NOTMUCH_DATABASE_MODE_READ_WRITE) {\r
387 >           notmuch->xapian_db = new Xapian::WritableDatabase (xapian_path,\r
388 >                                                              Xapian::DB_CREATE_OR_OPEN);\r
389 > -         version = notmuch_database_get_version (notmuch);\r
390 > -\r
391 > -         if (version > NOTMUCH_DATABASE_VERSION) {\r
392 > -             fprintf (stderr,\r
393 > -                      "Error: Notmuch database at %s\n"\r
394 > -                      "       has a newer database format version (%u) than supported by this\n"\r
395 > -                      "       version of notmuch (%u). Refusing to open this database in\n"\r
396 > -                      "       read-write mode.\n",\r
397 > -                      notmuch_path, version, NOTMUCH_DATABASE_VERSION);\r
398 > -             notmuch->mode = NOTMUCH_DATABASE_MODE_READ_ONLY;\r
399 > -             notmuch_database_destroy (notmuch);\r
400 > -             notmuch = NULL;\r
401 > -             status = NOTMUCH_STATUS_FILE_ERROR;\r
402 > -             goto DONE;\r
403 > -         }\r
404 > -\r
405 > -         if (version < NOTMUCH_DATABASE_VERSION)\r
406 > -             notmuch->needs_upgrade = TRUE;\r
407 >       } else {\r
408 >           notmuch->xapian_db = new Xapian::Database (xapian_path);\r
409 > -         version = notmuch_database_get_version (notmuch);\r
410 > -         if (version > NOTMUCH_DATABASE_VERSION)\r
411 > -         {\r
412 > -             fprintf (stderr,\r
413 > -                      "Warning: Notmuch database at %s\n"\r
414 > -                      "         has a newer database format version (%u) than supported by this\n"\r
415 > -                      "         version of notmuch (%u). Some operations may behave incorrectly,\n"\r
416 > -                      "         (but the database will not be harmed since it is being opened\n"\r
417 > -                      "         in read-only mode).\n",\r
418 > -                      notmuch_path, version, NOTMUCH_DATABASE_VERSION);\r
419 > -         }\r
420 > +     }\r
421 > +\r
422 > +     /* Check version.  As of database version 3, we represent\r
423 > +      * changes in terms of features, so assume a version bump\r
424 > +      * means a dramatically incompatible change. */\r
425 > +     version = notmuch_database_get_version (notmuch);\r
426 > +     if (version > NOTMUCH_DATABASE_VERSION) {\r
427 > +         fprintf (stderr,\r
428 > +                  "Error: Notmuch database at %s\n"\r
429 > +                  "       has a newer database format version (%u) than supported by this\n"\r
430 > +                  "       version of notmuch (%u).\n",\r
431 > +                  notmuch_path, version, NOTMUCH_DATABASE_VERSION);\r
432 > +         notmuch->mode = NOTMUCH_DATABASE_MODE_READ_ONLY;\r
433 > +         notmuch_database_destroy (notmuch);\r
434 > +         notmuch = NULL;\r
435 > +         status = NOTMUCH_STATUS_FILE_ERROR;\r
436 > +         goto DONE;\r
437 > +     }\r
438 > +\r
439 > +     /* Check features. */\r
440 > +     incompat_features = NULL;\r
441 > +     notmuch->features = _parse_features (\r
442 > +         local, notmuch->xapian_db->get_metadata ("features").c_str (),\r
443 > +         version, mode == NOTMUCH_DATABASE_MODE_READ_WRITE ? 'w' : 'r',\r
444 \r
445 Makes me think _parse_features could use notmuch_database_mode_t mode\r
446 instead of char mode. *shrug*.\r
447 \r
448 > +         &incompat_features);\r
449 > +     if (incompat_features) {\r
450 > +         fprintf (stderr,\r
451 > +                  "Error: Notmuch database at %s\n"\r
452 > +                  "       requires features (%s)\n"\r
453 > +                  "       not supported by this version of notmuch.\n",\r
454 > +                  notmuch_path, incompat_features);\r
455 > +         notmuch->mode = NOTMUCH_DATABASE_MODE_READ_ONLY;\r
456 > +         notmuch_database_destroy (notmuch);\r
457 > +         notmuch = NULL;\r
458 > +         status = NOTMUCH_STATUS_FILE_ERROR;\r
459 > +         goto DONE;\r
460 >       }\r
461 >  \r
462 >       notmuch->last_doc_id = notmuch->xapian_db->get_lastdocid ();\r
463 > @@ -1048,7 +1164,8 @@ notmuch_database_get_version (notmuch_database_t *notmuch)\r
464 >  notmuch_bool_t\r
465 >  notmuch_database_needs_upgrade (notmuch_database_t *notmuch)\r
466 >  {\r
467 > -    return notmuch->needs_upgrade;\r
468 > +    return notmuch->mode == NOTMUCH_DATABASE_MODE_READ_WRITE &&\r
469 > +     (NOTMUCH_FEATURES_CURRENT & ~notmuch->features);\r
470 >  }\r
471 \r
472 Am I correct that this does not lead to a database upgrade from v2 to v3\r
473 until we actually change the features?\r
474 \r
475 Aside, why don't we return a suitable status code from\r
476 notmuch_database_open when an upgrade is required?\r
477 \r
478 >  static volatile sig_atomic_t do_progress_notify = 0;\r
479 > @@ -1077,6 +1194,7 @@ notmuch_database_upgrade (notmuch_database_t *notmuch,\r
480 >                                                  double progress),\r
481 >                         void *closure)\r
482 >  {\r
483 > +    void *local = talloc_new (NULL);\r
484 >      Xapian::WritableDatabase *db;\r
485 >      struct sigaction action;\r
486 >      struct itimerval timerval;\r
487 > @@ -1114,6 +1232,10 @@ notmuch_database_upgrade (notmuch_database_t *notmuch,\r
488 >       timer_is_active = TRUE;\r
489 >      }\r
490 >  \r
491 > +    /* Set the target features so we write out changes in the desired\r
492 > +     * format. */\r
493 > +    notmuch->features |= NOTMUCH_FEATURES_CURRENT;\r
494 > +\r
495 >      /* Before version 1, each message document had its filename in the\r
496 >       * data field. Copy that into the new format by calling\r
497 >       * notmuch_message_add_filename.\r
498 > @@ -1226,6 +1348,7 @@ notmuch_database_upgrade (notmuch_database_t *notmuch,\r
499 >       notmuch_query_destroy (query);\r
500 >      }\r
501 >  \r
502 > +    db->set_metadata ("features", _print_features (local, notmuch->features));\r
503 >      db->set_metadata ("version", STRINGIFY (NOTMUCH_DATABASE_VERSION));\r
504 >      db->flush ();\r
505 >  \r
506 > @@ -1302,6 +1425,7 @@ notmuch_database_upgrade (notmuch_database_t *notmuch,\r
507 >       sigaction (SIGALRM, &action, NULL);\r
508 >      }\r
509 >  \r
510 > +    talloc_free (local);\r
511 >      return NOTMUCH_STATUS_SUCCESS;\r
512 >  }\r
513 >  \r
514 > -- \r
515 > 2.0.0\r
516 >\r
517 > _______________________________________________\r
518 > notmuch mailing list\r
519 > notmuch@notmuchmail.org\r
520 > http://notmuchmail.org/mailman/listinfo/notmuch\r