--- /dev/null
+Return-Path: <jani@nikula.org>\r
+X-Original-To: notmuch@notmuchmail.org\r
+Delivered-To: notmuch@notmuchmail.org\r
+Received: from localhost (localhost [127.0.0.1])\r
+ by olra.theworths.org (Postfix) with ESMTP id 3C43D431FB6\r
+ for <notmuch@notmuchmail.org>; Sat, 23 Aug 2014 09:02:50 -0700 (PDT)\r
+X-Virus-Scanned: Debian amavisd-new at olra.theworths.org\r
+X-Spam-Flag: NO\r
+X-Spam-Score: -0.7\r
+X-Spam-Level: \r
+X-Spam-Status: No, score=-0.7 tagged_above=-999 required=5\r
+ tests=[RCVD_IN_DNSWL_LOW=-0.7] autolearn=disabled\r
+Received: from olra.theworths.org ([127.0.0.1])\r
+ by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024)\r
+ with ESMTP id bPYCnr-aBRuP for <notmuch@notmuchmail.org>;\r
+ Sat, 23 Aug 2014 09:02:43 -0700 (PDT)\r
+Received: from mail-wi0-f171.google.com (mail-wi0-f171.google.com\r
+ [209.85.212.171]) (using TLSv1 with cipher RC4-SHA (128/128 bits))\r
+ (No client certificate requested)\r
+ by olra.theworths.org (Postfix) with ESMTPS id A3418431FAF\r
+ for <notmuch@notmuchmail.org>; Sat, 23 Aug 2014 09:02:42 -0700 (PDT)\r
+Received: by mail-wi0-f171.google.com with SMTP id hi2so844068wib.16\r
+ for <notmuch@notmuchmail.org>; Sat, 23 Aug 2014 09:02:41 -0700 (PDT)\r
+X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;\r
+ d=1e100.net; s=20130820;\r
+ h=x-gm-message-state:from:to:subject:in-reply-to:references\r
+ :user-agent:date:message-id:mime-version:content-type;\r
+ bh=UE6h6AnDwL0D9gvGPUnAfS5fKTsOKdPfacIwzt7V7KQ=;\r
+ b=bzetmBlRlQOizY3PhWhAoo3cE+VP6iv+c+q2bn4CVIYwAXAYHpYueHY96rRRHC3qMQ\r
+ 3El5ND4wAkUXGBCR8I3vbIhXccGeoXiskKsx/yttIoCQkzljuZQficEf/3gOmZ1r1h17\r
+ W0xB28/GA8DPF3LlC4E9HwuSLYHjxcj89fYbqBqei0lshMUQ5kfWWzvg2eu3OclK9RGI\r
+ JnS0tyM1VsOZKHK1otA3ujlNbHOQ+NHYIrzTXfByXa8czh1vlXkROoVp+sNavLVNqusL\r
+ HZbjilh5rssqaMux0tJB3nJXU1/LbDG2dVr32gDkpvcqJXAHct4KJj0ZWUkUCEVWVhhn\r
+ 5mYA==\r
+X-Gm-Message-State:\r
+ ALoCoQnXOVuCL3NVkQr9Oi1AaSAVu6EDqFqIxXBXFKLbjPSirI0noI/6Tun+6U6tXGxn8ZDARVBk\r
+X-Received: by 10.180.21.101 with SMTP id u5mr4647284wie.68.1408809761398;\r
+ Sat, 23 Aug 2014 09:02:41 -0700 (PDT)\r
+Received: from localhost (dsl-hkibrasgw2-58c374-75.dhcp.inet.fi.\r
+ [88.195.116.75]) by mx.google.com with ESMTPSA id\r
+ y10sm10563955wie.18.2014.08.23.09.02.39 for <multiple recipients>\r
+ (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128);\r
+ Sat, 23 Aug 2014 09:02:40 -0700 (PDT)\r
+From: Jani Nikula <jani@nikula.org>\r
+To: Austin Clements <amdragon@MIT.EDU>, notmuch@notmuchmail.org\r
+Subject: Re: [PATCH v3 04/13] lib: Database version 3: Introduce\r
+ fine-grained "features"\r
+In-Reply-To: <1406859003-11561-5-git-send-email-amdragon@mit.edu>\r
+References: <1406859003-11561-1-git-send-email-amdragon@mit.edu>\r
+ <1406859003-11561-5-git-send-email-amdragon@mit.edu>\r
+User-Agent: Notmuch/0.18.1+65~g9f0f30f (http://notmuchmail.org) Emacs/24.3.1\r
+ (x86_64-pc-linux-gnu)\r
+Date: Sat, 23 Aug 2014 19:02:39 +0300\r
+Message-ID: <87r407jisg.fsf@nikula.org>\r
+MIME-Version: 1.0\r
+Content-Type: text/plain\r
+X-BeenThere: notmuch@notmuchmail.org\r
+X-Mailman-Version: 2.1.13\r
+Precedence: list\r
+List-Id: "Use and development of the notmuch mail system."\r
+ <notmuch.notmuchmail.org>\r
+List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,\r
+ <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>\r
+List-Archive: <http://notmuchmail.org/pipermail/notmuch>\r
+List-Post: <mailto:notmuch@notmuchmail.org>\r
+List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>\r
+List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,\r
+ <mailto:notmuch-request@notmuchmail.org?subject=subscribe>\r
+X-List-Received-Date: Sat, 23 Aug 2014 16:02:50 -0000\r
+\r
+On Fri, 01 Aug 2014, Austin Clements <amdragon@MIT.EDU> wrote:\r
+> Previously, our database schema was versioned by a single number.\r
+> Each database schema change had to occur "atomically" in Notmuch's\r
+> development history: before some commit, Notmuch used version N, after\r
+> that commit, it used version N+1. Hence, each new schema version\r
+> could introduce only one change, the task of developing a schema\r
+> change fell on a single person, and it all had to happen and be\r
+> perfect in a single commit series. This made introducing a new schema\r
+> version hard. We've seen only two schema changes in the history of\r
+> Notmuch.\r
+>\r
+> This commit introduces database schema version 3; hopefully the last\r
+> schema version we'll need for a while. With this version, we switch\r
+> from a single version number to "features": a set of named,\r
+> independent aspects of the database schema.\r
+>\r
+> Features should make backwards compatibility easier. For many things,\r
+> it should be easy to support databases both with and without a\r
+> feature, which will allow us to make upgrades optional and will enable\r
+> "unstable" features that can be developed and tested over time.\r
+>\r
+> Features also make forwards compatibility easier. The features\r
+> recorded in a database include "compatibility flags," which can\r
+> indicate to an older version of Notmuch when it must support a given\r
+> feature to open the database for read or for write. This lets us\r
+> replace the old vague "I don't recognize this version, so something\r
+> might go wrong, but I promise to try my best" warnings upon opening a\r
+> database with an unknown version with precise errors. If a database\r
+> is safe to open for read/write despite unknown features, an older\r
+> version will know that and issue no message at all. If the database\r
+> is not safe to open for read/write because of unknown features, an\r
+> older version will know that, too, and can tell the user exactly which\r
+> required features it lacks support for.\r
+\r
+I agree with the change overall; it might be useful to have another set\r
+of eyes on the patch though.\r
+\r
+> ---\r
+> lib/database-private.h | 57 ++++++++++++++-\r
+> lib/database.cc | 190 ++++++++++++++++++++++++++++++++++++++++---------\r
+> 2 files changed, 213 insertions(+), 34 deletions(-)\r
+>\r
+> diff --git a/lib/database-private.h b/lib/database-private.h\r
+> index d3e65fd..2ffab33 100644\r
+> --- a/lib/database-private.h\r
+> +++ b/lib/database-private.h\r
+> @@ -41,11 +41,15 @@ struct _notmuch_database {\r
+> \r
+> char *path;\r
+> \r
+> - notmuch_bool_t needs_upgrade;\r
+> notmuch_database_mode_t mode;\r
+> int atomic_nesting;\r
+> Xapian::Database *xapian_db;\r
+> \r
+> + /* Bit mask of features used by this database. Features are\r
+> + * named, independent aspects of the database schema. This is a\r
+> + * bitwise-OR of NOTMUCH_FEATURE_* values (below). */\r
+> + unsigned int features;\r
+> +\r
+> unsigned int last_doc_id;\r
+> uint64_t last_thread_id;\r
+> \r
+> @@ -55,6 +59,57 @@ struct _notmuch_database {\r
+> Xapian::ValueRangeProcessor *date_range_processor;\r
+> };\r
+> \r
+> +/* Bit masks for _notmuch_database::features. */\r
+> +enum {\r
+> + /* If set, file names are stored in "file-direntry" terms. If\r
+> + * unset, file names are stored in document data.\r
+> + *\r
+> + * Introduced: version 1. Implementation support: both for read;\r
+> + * required for write. */\r
+\r
+Maybe I'm dense, but the implementation support comments could be\r
+clearer.\r
+\r
+> + NOTMUCH_FEATURE_FILE_TERMS = 1 << 0,\r
+> +\r
+> + /* If set, directory timestamps are stored in documents with\r
+> + * XDIRECTORY terms and relative paths. If unset, directory\r
+> + * timestamps are stored in documents with XTIMESTAMP terms and\r
+> + * absolute paths.\r
+> + *\r
+> + * Introduced: version 1. Implementation support: required. */\r
+> + NOTMUCH_FEATURE_DIRECTORY_DOCS = 1 << 1,\r
+> +\r
+> + /* If set, the from, subject, and message-id headers are stored in\r
+> + * message document values. If unset, message documents *may*\r
+> + * have these values, but if the value is empty, it must be\r
+> + * retrieved from the message file.\r
+> + *\r
+> + * Introduced: optional in version 1, required as of version 3.\r
+> + * Implementation support: both.\r
+> + */\r
+> + NOTMUCH_FEATURE_FROM_SUBJECT_ID_VALUES = 1 << 2,\r
+> +\r
+> + /* If set, folder terms are boolean and path terms exist. If\r
+> + * unset, folder terms are probabilistic and stemmed and path\r
+> + * terms do not exist.\r
+> + *\r
+> + * Introduced: version 2. Implementation support: required. */\r
+> + NOTMUCH_FEATURE_BOOL_FOLDER = 1 << 3,\r
+> +};\r
+> +\r
+> +/* Prior to database version 3, features were implied by the database\r
+> + * version number, so hard-code them for earlier versions. */\r
+> +#define NOTMUCH_FEATURES_V0 (0)\r
+> +#define NOTMUCH_FEATURES_V1 (NOTMUCH_FEATURES_V0 | NOTMUCH_FEATURE_FILE_TERMS | \\r
+> + NOTMUCH_FEATURE_DIRECTORY_DOCS)\r
+> +#define NOTMUCH_FEATURES_V2 (NOTMUCH_FEATURES_V1 | NOTMUCH_FEATURE_BOOL_FOLDER)\r
+> +\r
+> +/* Current database features. If any of these are missing from a\r
+> + * database, request an upgrade.\r
+> + * NOTMUCH_FEATURE_FROM_SUBJECT_ID_VALUES is not included because\r
+> + * upgrade doesn't currently introduce the feature (though brand new\r
+> + * databases will have it). */\r
+> +#define NOTMUCH_FEATURES_CURRENT \\r
+> + (NOTMUCH_FEATURE_FILE_TERMS | NOTMUCH_FEATURE_DIRECTORY_DOCS | \\r
+> + NOTMUCH_FEATURE_BOOL_FOLDER)\r
+> +\r
+> /* Return the list of terms from the given iterator matching a prefix.\r
+> * The prefix will be stripped from the strings in the returned list.\r
+> * The list will be allocated using ctx as the talloc context.\r
+> diff --git a/lib/database.cc b/lib/database.cc\r
+> index 45c4260..29a56db 100644\r
+> --- a/lib/database.cc\r
+> +++ b/lib/database.cc\r
+> @@ -20,6 +20,7 @@\r
+> \r
+> #include "database-private.h"\r
+> #include "parse-time-vrp.h"\r
+> +#include "string-util.h"\r
+> \r
+> #include <iostream>\r
+> \r
+> @@ -42,7 +43,7 @@ typedef struct {\r
+> const char *prefix;\r
+> } prefix_t;\r
+> \r
+> -#define NOTMUCH_DATABASE_VERSION 2\r
+> +#define NOTMUCH_DATABASE_VERSION 3\r
+> \r
+> #define STRINGIFY(s) _SUB_STRINGIFY(s)\r
+> #define _SUB_STRINGIFY(s) #s\r
+> @@ -151,6 +152,17 @@ typedef struct {\r
+> * changes are made to the database (such as by\r
+> * indexing new fields).\r
+> *\r
+> + * features The set of features supported by this\r
+> + * database. This consists of a set of\r
+> + * '\n'-separated lines, where each is a feature\r
+> + * name, a '\t', and compatibility flags. If the\r
+> + * compatibility flags contain 'w', then the\r
+> + * opener must support this feature to safely\r
+> + * write this database. If the compatibility\r
+> + * flags contain 'r', then the opener must\r
+> + * support this feature to read this database.\r
+> + * Introduced in database version 3.\r
+> + *\r
+> * last_thread_id The last thread ID generated. This is stored\r
+> * as a 16-byte hexadecimal ASCII representation\r
+> * of a 64-bit unsigned integer. The first ID\r
+> @@ -251,6 +263,25 @@ _find_prefix (const char *name)\r
+> return "";\r
+> }\r
+> \r
+> +static const struct\r
+> +{\r
+\r
+Brace should be at the end of the previous line.\r
+\r
+> + /* NOTMUCH_FEATURE_* value. */\r
+> + unsigned int value;\r
+> + /* Feature name as it appears in the database. This name should\r
+> + * be appropriate for displaying to the user if an older version\r
+> + * of notmuch doesn't support this feature. */\r
+> + const char *name;\r
+> + /* Compatibility flags when this feature is declared. */\r
+> + const char *flags;\r
+> +} feature_names[] = {\r
+> + {NOTMUCH_FEATURE_FILE_TERMS, "multiple paths per message", "rw"},\r
+> + {NOTMUCH_FEATURE_DIRECTORY_DOCS, "relative directory paths", "rw"},\r
+> + /* Header values are not required for reading a database because a\r
+> + * reader can just refer to the message file. */\r
+> + {NOTMUCH_FEATURE_FROM_SUBJECT_ID_VALUES, "from/subject/message-ID in database", "w"},\r
+> + {NOTMUCH_FEATURE_BOOL_FOLDER, "exact folder:/path: search", "rw"},\r
+\r
+Spaces missing after the opening braces and before the closing braces.\r
+\r
+> +};\r
+> +\r
+> const char *\r
+> notmuch_status_to_string (notmuch_status_t status)\r
+> {\r
+> @@ -591,6 +622,11 @@ notmuch_database_create (const char *path, notmuch_database_t **database)\r
+> ¬much);\r
+> if (status)\r
+> goto DONE;\r
+> +\r
+> + /* Upgrade doesn't add this feature to existing databases, but new\r
+> + * databases have it. */\r
+> + notmuch->features |= NOTMUCH_FEATURE_FROM_SUBJECT_ID_VALUES;\r
+> +\r
+> status = notmuch_database_upgrade (notmuch, NULL, NULL);\r
+> if (status) {\r
+> notmuch_database_close(notmuch);\r
+> @@ -619,6 +655,80 @@ _notmuch_database_ensure_writable (notmuch_database_t *notmuch)\r
+> return NOTMUCH_STATUS_SUCCESS;\r
+> }\r
+> \r
+> +/* Parse a database features string from the given database version.\r
+> + *\r
+> + * For version < 3, this ignores the features string and returns a\r
+> + * hard-coded set of features.\r
+> + *\r
+> + * If there are unrecognized features that are required to open the\r
+> + * database in mode (which should be 'r' or 'w'), return a\r
+> + * comma-separated list of unrecognized but required features in\r
+> + * *incompat_out, which will be allocated from ctx.\r
+\r
+Please describe the actual return value.\r
+\r
+> + */\r
+> +static unsigned int\r
+> +_parse_features (const void *ctx, const char *features, unsigned int version,\r
+> + char mode, char **incompat_out)\r
+> +{\r
+> + unsigned int res = 0, namelen, i;\r
+> + size_t llen = 0;\r
+> + const char *flags;\r
+> +\r
+> + /* Prior to database version 3, features were implied by the\r
+> + * version number. */\r
+> + if (version == 0)\r
+> + return NOTMUCH_FEATURES_V0;\r
+> + else if (version == 1)\r
+> + return NOTMUCH_FEATURES_V1;\r
+> + else if (version == 2)\r
+> + return NOTMUCH_FEATURES_V2;\r
+> +\r
+> + /* Parse the features string */\r
+> + while ((features = strtok_len_c (features + llen, "\n", &llen)) != NULL) {\r
+> + flags = strchr (features, '\t');\r
+> + if (! flags || flags > features + llen)\r
+> + continue;\r
+> + namelen = flags - features;\r
+> +\r
+> + for (i = 0; i < ARRAY_SIZE (feature_names); ++i) {\r
+> + if (strlen (feature_names[i].name) == namelen &&\r
+> + strncmp (feature_names[i].name, features, namelen) == 0) {\r
+> + res |= feature_names[i].value;\r
+> + break;\r
+> + }\r
+> + }\r
+> +\r
+> + if (i == ARRAY_SIZE (feature_names)) {\r
+> + /* Unrecognized feature */\r
+> + const char *have = strchr (flags, mode);\r
+> + if (have && have < features + llen) {\r
+> + /* This feature is required to access this database in\r
+> + * 'mode', but we don't understand it. */\r
+> + if (! *incompat_out)\r
+> + *incompat_out = talloc_strdup (ctx, "");\r
+> + *incompat_out = talloc_asprintf_append_buffer (\r
+> + *incompat_out, "%s%.*s", **incompat_out ? ", " : "",\r
+> + namelen, features);\r
+\r
+Do we intend the lib user to be able to parse the features? Perhaps we\r
+should use '\n' as separator here too? (Although looks like *currently*\r
+this is only for printing the message from within the lib.)\r
+\r
+> + }\r
+> + }\r
+> + }\r
+> +\r
+> + return res;\r
+> +}\r
+> +\r
+> +static char *\r
+> +_print_features (const void *ctx, unsigned int features)\r
+> +{\r
+> + unsigned int i;\r
+> + char *res = talloc_strdup (ctx, "");\r
+> +\r
+> + for (i = 0; i < ARRAY_SIZE (feature_names); ++i)\r
+> + if (features & feature_names[i].value)\r
+> + res = talloc_asprintf_append_buffer (\r
+> + res, "%s\t%s\n", feature_names[i].name, feature_names[i].flags);\r
+> +\r
+> + return res;\r
+> +}\r
+> +\r
+> notmuch_status_t\r
+> notmuch_database_open (const char *path,\r
+> notmuch_database_mode_t mode,\r
+> @@ -627,7 +737,7 @@ notmuch_database_open (const char *path,\r
+> notmuch_status_t status = NOTMUCH_STATUS_SUCCESS;\r
+> void *local = talloc_new (NULL);\r
+> notmuch_database_t *notmuch = NULL;\r
+> - char *notmuch_path, *xapian_path;\r
+> + char *notmuch_path, *xapian_path, *incompat_features;\r
+> struct stat st;\r
+> int err;\r
+> unsigned int i, version;\r
+> @@ -677,7 +787,6 @@ notmuch_database_open (const char *path,\r
+> if (notmuch->path[strlen (notmuch->path) - 1] == '/')\r
+> notmuch->path[strlen (notmuch->path) - 1] = '\0';\r
+> \r
+> - notmuch->needs_upgrade = FALSE;\r
+> notmuch->mode = mode;\r
+> notmuch->atomic_nesting = 0;\r
+> try {\r
+> @@ -686,37 +795,44 @@ notmuch_database_open (const char *path,\r
+> if (mode == NOTMUCH_DATABASE_MODE_READ_WRITE) {\r
+> notmuch->xapian_db = new Xapian::WritableDatabase (xapian_path,\r
+> Xapian::DB_CREATE_OR_OPEN);\r
+> - version = notmuch_database_get_version (notmuch);\r
+> -\r
+> - if (version > NOTMUCH_DATABASE_VERSION) {\r
+> - fprintf (stderr,\r
+> - "Error: Notmuch database at %s\n"\r
+> - " has a newer database format version (%u) than supported by this\n"\r
+> - " version of notmuch (%u). Refusing to open this database in\n"\r
+> - " read-write mode.\n",\r
+> - notmuch_path, version, NOTMUCH_DATABASE_VERSION);\r
+> - notmuch->mode = NOTMUCH_DATABASE_MODE_READ_ONLY;\r
+> - notmuch_database_destroy (notmuch);\r
+> - notmuch = NULL;\r
+> - status = NOTMUCH_STATUS_FILE_ERROR;\r
+> - goto DONE;\r
+> - }\r
+> -\r
+> - if (version < NOTMUCH_DATABASE_VERSION)\r
+> - notmuch->needs_upgrade = TRUE;\r
+> } else {\r
+> notmuch->xapian_db = new Xapian::Database (xapian_path);\r
+> - version = notmuch_database_get_version (notmuch);\r
+> - if (version > NOTMUCH_DATABASE_VERSION)\r
+> - {\r
+> - fprintf (stderr,\r
+> - "Warning: Notmuch database at %s\n"\r
+> - " has a newer database format version (%u) than supported by this\n"\r
+> - " version of notmuch (%u). Some operations may behave incorrectly,\n"\r
+> - " (but the database will not be harmed since it is being opened\n"\r
+> - " in read-only mode).\n",\r
+> - notmuch_path, version, NOTMUCH_DATABASE_VERSION);\r
+> - }\r
+> + }\r
+> +\r
+> + /* Check version. As of database version 3, we represent\r
+> + * changes in terms of features, so assume a version bump\r
+> + * means a dramatically incompatible change. */\r
+> + version = notmuch_database_get_version (notmuch);\r
+> + if (version > NOTMUCH_DATABASE_VERSION) {\r
+> + fprintf (stderr,\r
+> + "Error: Notmuch database at %s\n"\r
+> + " has a newer database format version (%u) than supported by this\n"\r
+> + " version of notmuch (%u).\n",\r
+> + notmuch_path, version, NOTMUCH_DATABASE_VERSION);\r
+> + notmuch->mode = NOTMUCH_DATABASE_MODE_READ_ONLY;\r
+> + notmuch_database_destroy (notmuch);\r
+> + notmuch = NULL;\r
+> + status = NOTMUCH_STATUS_FILE_ERROR;\r
+> + goto DONE;\r
+> + }\r
+> +\r
+> + /* Check features. */\r
+> + incompat_features = NULL;\r
+> + notmuch->features = _parse_features (\r
+> + local, notmuch->xapian_db->get_metadata ("features").c_str (),\r
+> + version, mode == NOTMUCH_DATABASE_MODE_READ_WRITE ? 'w' : 'r',\r
+\r
+Makes me think _parse_features could use notmuch_database_mode_t mode\r
+instead of char mode. *shrug*.\r
+\r
+> + &incompat_features);\r
+> + if (incompat_features) {\r
+> + fprintf (stderr,\r
+> + "Error: Notmuch database at %s\n"\r
+> + " requires features (%s)\n"\r
+> + " not supported by this version of notmuch.\n",\r
+> + notmuch_path, incompat_features);\r
+> + notmuch->mode = NOTMUCH_DATABASE_MODE_READ_ONLY;\r
+> + notmuch_database_destroy (notmuch);\r
+> + notmuch = NULL;\r
+> + status = NOTMUCH_STATUS_FILE_ERROR;\r
+> + goto DONE;\r
+> }\r
+> \r
+> notmuch->last_doc_id = notmuch->xapian_db->get_lastdocid ();\r
+> @@ -1048,7 +1164,8 @@ notmuch_database_get_version (notmuch_database_t *notmuch)\r
+> notmuch_bool_t\r
+> notmuch_database_needs_upgrade (notmuch_database_t *notmuch)\r
+> {\r
+> - return notmuch->needs_upgrade;\r
+> + return notmuch->mode == NOTMUCH_DATABASE_MODE_READ_WRITE &&\r
+> + (NOTMUCH_FEATURES_CURRENT & ~notmuch->features);\r
+> }\r
+\r
+Am I correct that this does not lead to a database upgrade from v2 to v3\r
+until we actually change the features?\r
+\r
+Aside, why don't we return a suitable status code from\r
+notmuch_database_open when an upgrade is required?\r
+\r
+> static volatile sig_atomic_t do_progress_notify = 0;\r
+> @@ -1077,6 +1194,7 @@ notmuch_database_upgrade (notmuch_database_t *notmuch,\r
+> double progress),\r
+> void *closure)\r
+> {\r
+> + void *local = talloc_new (NULL);\r
+> Xapian::WritableDatabase *db;\r
+> struct sigaction action;\r
+> struct itimerval timerval;\r
+> @@ -1114,6 +1232,10 @@ notmuch_database_upgrade (notmuch_database_t *notmuch,\r
+> timer_is_active = TRUE;\r
+> }\r
+> \r
+> + /* Set the target features so we write out changes in the desired\r
+> + * format. */\r
+> + notmuch->features |= NOTMUCH_FEATURES_CURRENT;\r
+> +\r
+> /* Before version 1, each message document had its filename in the\r
+> * data field. Copy that into the new format by calling\r
+> * notmuch_message_add_filename.\r
+> @@ -1226,6 +1348,7 @@ notmuch_database_upgrade (notmuch_database_t *notmuch,\r
+> notmuch_query_destroy (query);\r
+> }\r
+> \r
+> + db->set_metadata ("features", _print_features (local, notmuch->features));\r
+> db->set_metadata ("version", STRINGIFY (NOTMUCH_DATABASE_VERSION));\r
+> db->flush ();\r
+> \r
+> @@ -1302,6 +1425,7 @@ notmuch_database_upgrade (notmuch_database_t *notmuch,\r
+> sigaction (SIGALRM, &action, NULL);\r
+> }\r
+> \r
+> + talloc_free (local);\r
+> return NOTMUCH_STATUS_SUCCESS;\r
+> }\r
+> \r
+> -- \r
+> 2.0.0\r
+>\r
+> _______________________________________________\r
+> notmuch mailing list\r
+> notmuch@notmuchmail.org\r
+> http://notmuchmail.org/mailman/listinfo/notmuch\r