[RFC PATCH 02/13] Add the concept of a mailstore in its absolute minimal sense
authorEthan Glasser-Camp <glasse@cs.rpi.edu>
Wed, 15 Feb 2012 22:01:55 +0000 (17:01 +1900)
committerW. Trevor King <wking@tremily.us>
Fri, 7 Nov 2014 17:44:33 +0000 (09:44 -0800)
7b/5f91766ed469dc4d88322aed1f40821617eb89 [new file with mode: 0644]

diff --git a/7b/5f91766ed469dc4d88322aed1f40821617eb89 b/7b/5f91766ed469dc4d88322aed1f40821617eb89
new file mode 100644 (file)
index 0000000..efbefb0
--- /dev/null
@@ -0,0 +1,1108 @@
+Return-Path: <glasse@cs.rpi.edu>\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 499BD429E4D\r
+       for <notmuch@notmuchmail.org>; Wed, 15 Feb 2012 14:05:21 -0800 (PST)\r
+X-Virus-Scanned: Debian amavisd-new at olra.theworths.org\r
+X-Spam-Flag: NO\r
+X-Spam-Score: -0.54\r
+X-Spam-Level: \r
+X-Spam-Status: No, score=-0.54 tagged_above=-999 required=5\r
+       tests=[DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1,\r
+       RCVD_IN_BL_SPAMCOP_NET=1.246, RCVD_IN_DNSWL_MED=-2.3,\r
+       RCVD_IN_SORBS_WEB=0.614] 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 l8jycoFcKWZ4 for <notmuch@notmuchmail.org>;\r
+       Wed, 15 Feb 2012 14:05:17 -0800 (PST)\r
+Received: from cliffclavin.cs.rpi.edu (cliffclavin.cs.rpi.edu\r
+ [128.113.126.25])     (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits))\r
+       (No client certificate requested)       by olra.theworths.org (Postfix) with ESMTPS\r
+ id D6089431E62        for <notmuch@notmuchmail.org>; Wed, 15 Feb 2012 14:05:16 -0800\r
+ (PST)\r
+X-Hash: SCtCte|89dfd227c9662973caf8391b7d228905169bd57f|97dc102990e8867edb52cd10b7e2ee4b\r
+X-Countries: Cameroon, United States\r
+X-SMTP-From: accepted <glasse@cs.rpi.edu> [195.24.209.20] [195.24.209.20]\r
+       (localhost) {Cameroon}\r
+DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=cs.rpi.edu; h=from\r
+       :to:cc:subject:date:message-id:in-reply-to:references\r
+       :mime-version:content-type:content-transfer-encoding; s=default;\r
+       i=glasse@cs.rpi.edu; t=1329343514; x=1329948314; l=35856; bh=OT\r
+       sr0oOTFdwKst/jNUR1YAEfm8s=; b=dO/rdBc0sonb8IjwP6uYCMDQX5mU+46QaW\r
+       GDHTdq1M0LxCMl0Re2zWsOs975MGeb5e4IhxwJyQW83BRasSMVPX1wRbdUy0p45f\r
+       I2zFDTGORHlhbphVpOsz9nb/IJTLQkOCoKwjiVkBziFlFtUbd33OlJ5v+ky/+Uqs\r
+       9D8kupyjo=\r
+DomainKey-Signature: a=rsa-sha1; c=nofws; d=cs.rpi.edu; h=from:to:cc\r
+       :subject:date:message-id:in-reply-to:references:mime-version\r
+       :content-type:content-transfer-encoding; q=dns; s=default; b=DQm\r
+       VIkdWCj7voYXR1hMb3ZXdLVLbsPuBzB7PR8EGSkCSb2wlVOpH0TcxYqEW2syBAcY\r
+       LdudrqeN8Y4mqsk0+iJdgGAh+lm4oxWBR1n1R1eW8aUqULD7I6xeNyDtpQeJcrHn\r
+       On4Pmbrv/0f4VPPosFot7q/pf5zQywrZqlzA3RVY=\r
+X-Spam-Info: -2.6; ALL_TRUSTED,AWL,BAYES_00,SARE_SUB_ENC_UTF8\r
+X-Spam-Scanned-By: cliffclavin.cs.rpi.edu using SpamAssassin 3.2.5 (hard limit\r
+       15)\r
+Authentication-Results: cliffclavin.cs.rpi.edu;\r
+       DKIM=neutral (none) header.from=glasse@cs.rpi.edu;\r
+       SPF=neutral (mfrom;\r
+       Mechanism '?all' matched) smtp.mail=glasse@cs.rpi.edu\r
+X-Auth-Passed: cliffclavin.cs.rpi.edu:q1FM3qv2008742 Auth:glasse\r
+X-Virus-Scanned-By: cliffclavin.cs.rpi.edu\r
+Received: from localhost ([195.24.209.20]) (authenticated bits=0)\r
+       by cliffclavin.cs.rpi.edu (8.14.3/8.14.3) with ESMTP id q1FM3qv2008742\r
+       (version=TLSv1/SSLv3 cipher=DHE-RSA-AES128-SHA bits=128 verify=NO);\r
+       Wed, 15 Feb 2012 17:04:06 -0500 (EST)\r
+       (envelope-from glasse@cs.rpi.edu)\r
+From: Ethan Glasser-Camp <glasse@cs.rpi.edu>\r
+To: notmuch@notmuchmail.org\r
+Subject: [RFC PATCH 02/13] Add the concept of a mailstore in its absolute minimal sense\r
+Date: Wed, 15 Feb 2012 17:01:55 -0500\r
+Message-Id: <1329343326-16410-3-git-send-email-glasse@cs.rpi.edu>\r
+X-Mailer: git-send-email 1.7.5.4\r
+In-Reply-To: <1329343326-16410-1-git-send-email-glasse@cs.rpi.edu>\r
+References: <1329343326-16410-1-git-send-email-glasse@cs.rpi.edu>\r
+MIME-Version: 1.0\r
+Content-Type: text/plain; charset=UTF-8\r
+Content-Transfer-Encoding: 8bit\r
+X-Scanned-By: MIMEDefang 2.67 on 128.113.126.25\r
+Cc: Ethan Glasser-Camp <ethan@betacantrips.com>\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: Wed, 15 Feb 2012 22:05:21 -0000\r
+\r
+From: Ethan Glasser-Camp <ethan@betacantrips.com>\r
+\r
+This introduces (and uses) the mailstore parameter to the\r
+notmuch_message_file_open API, and passes this through wherever it\r
+will be needed. This requires touching a lot of places just to change\r
+one API. We end up adding it to the notmuch_database_t struct because\r
+it is needed for notmuch_database_upgrade.\r
+\r
+This doesn't touch the Python bindings, which require a certain amount\r
+of effort. (Therefore, the Python tests will be broken until the next commit.)\r
+\r
+Signed-off-by: Ethan Glasser-Camp <ethan@betacantrips.com>\r
+---\r
+ lib/Makefile.local     |    1 +\r
+ lib/database-private.h |    1 +\r
+ lib/database.cc        |   10 +++++---\r
+ lib/mailstore.c        |   59 ++++++++++++++++++++++++++++++++++++++++++++++++\r
+ lib/message-file.c     |   10 +++++---\r
+ lib/message.cc         |   11 +++++---\r
+ lib/notmuch-private.h  |    7 ++++-\r
+ lib/notmuch.h          |   21 ++++++++++++++--\r
+ lib/thread.cc          |   24 +++++++++++--------\r
+ notmuch-client.h       |    6 +++++\r
+ notmuch-config.c       |   12 +++++++++\r
+ notmuch-count.c        |    3 +-\r
+ notmuch-dump.c         |    3 +-\r
+ notmuch-new.c          |    8 +++++-\r
+ notmuch-reply.c        |   45 ++++++++++++++++++++++++------------\r
+ notmuch-restore.c      |    3 +-\r
+ notmuch-search.c       |    3 +-\r
+ notmuch-show.c         |   56 ++++++++++++++++++++++++++++++---------------\r
+ notmuch-tag.c          |    3 +-\r
+ test/symbol-test.cc    |    3 +-\r
+ 20 files changed, 220 insertions(+), 69 deletions(-)\r
+ create mode 100644 lib/mailstore.c\r
+\r
+diff --git a/lib/Makefile.local b/lib/Makefile.local\r
+index 54c4dea..461e5cd 100644\r
+--- a/lib/Makefile.local\r
++++ b/lib/Makefile.local\r
+@@ -51,6 +51,7 @@ libnotmuch_c_srcs =          \\r
+       $(dir)/filenames.c      \\r
+       $(dir)/string-list.c    \\r
+       $(dir)/libsha1.c        \\r
++      $(dir)/mailstore.c      \\r
+       $(dir)/message-file.c   \\r
+       $(dir)/messages.c       \\r
+       $(dir)/sha1.c           \\r
+diff --git a/lib/database-private.h b/lib/database-private.h\r
+index 88532d5..1cb8c43 100644\r
+--- a/lib/database-private.h\r
++++ b/lib/database-private.h\r
+@@ -39,6 +39,7 @@\r
+ struct _notmuch_database {\r
+     notmuch_bool_t exception_reported;\r
\r
++    notmuch_mailstore_t *mailstore;\r
+     char *path;\r
\r
+     notmuch_bool_t needs_upgrade;\r
+diff --git a/lib/database.cc b/lib/database.cc\r
+index c928d02..e3c8095 100644\r
+--- a/lib/database.cc\r
++++ b/lib/database.cc\r
+@@ -521,7 +521,7 @@ parse_references (void *ctx,\r
+ }\r
\r
+ notmuch_database_t *\r
+-notmuch_database_create (const char *path)\r
++notmuch_database_create (notmuch_mailstore_t *mailstore, const char *path)\r
+ {\r
+     notmuch_database_t *notmuch = NULL;\r
+     char *notmuch_path = NULL;\r
+@@ -556,7 +556,7 @@ notmuch_database_create (const char *path)\r
+       goto DONE;\r
+     }\r
\r
+-    notmuch = notmuch_database_open (path,\r
++    notmuch = notmuch_database_open (mailstore, path,\r
+                                    NOTMUCH_DATABASE_MODE_READ_WRITE);\r
+     notmuch_database_upgrade (notmuch, NULL, NULL);\r
\r
+@@ -579,7 +579,8 @@ _notmuch_database_ensure_writable (notmuch_database_t *notmuch)\r
+ }\r
\r
+ notmuch_database_t *\r
+-notmuch_database_open (const char *path,\r
++notmuch_database_open (notmuch_mailstore_t *mailstore,\r
++                     const char *path,\r
+                      notmuch_database_mode_t mode)\r
+ {\r
+     void *local = talloc_new (NULL);\r
+@@ -619,6 +620,7 @@ notmuch_database_open (const char *path,\r
+     notmuch = talloc_zero (NULL, notmuch_database_t);\r
+     notmuch->exception_reported = FALSE;\r
+     notmuch->path = talloc_strdup (notmuch, path);\r
++    notmuch->mailstore = mailstore;\r
\r
+     if (notmuch->path[strlen (notmuch->path) - 1] == '/')\r
+       notmuch->path[strlen (notmuch->path) - 1] = '\0';\r
+@@ -1636,7 +1638,7 @@ notmuch_database_add_message (notmuch_database_t *notmuch,\r
+     if (ret)\r
+       return ret;\r
\r
+-    message_file = notmuch_message_file_open (filename);\r
++    message_file = notmuch_message_file_open (notmuch->mailstore, filename);\r
+     if (message_file == NULL)\r
+       return NOTMUCH_STATUS_FILE_ERROR;\r
\r
+diff --git a/lib/mailstore.c b/lib/mailstore.c\r
+new file mode 100644\r
+index 0000000..290da70\r
+--- /dev/null\r
++++ b/lib/mailstore.c\r
+@@ -0,0 +1,59 @@\r
++/* mailstore.c - mail storage backends\r
++ *\r
++ * Copyright © 2009 Carl Worth\r
++ *\r
++ * This program is free software: you can redistribute it and/or modify\r
++ * it under the terms of the GNU General Public License as published by\r
++ * the Free Software Foundation, either version 3 of the License, or\r
++ * (at your option) any later version.\r
++ *\r
++ * This program is distributed in the hope that it will be useful,\r
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
++ * GNU General Public License for more details.\r
++ *\r
++ * You should have received a copy of the GNU General Public License\r
++ * along with this program.  If not, see http://www.gnu.org/licenses/ .\r
++ */\r
++\r
++#include <stdio.h>\r
++\r
++#include "notmuch-private.h"\r
++\r
++typedef struct _notmuch_mailstore {\r
++    FILE *(*open) (struct _notmuch_mailstore *mailstore, const char *filename);\r
++} _notmuch_mailstore;\r
++\r
++static FILE *\r
++_maildir_open_function (unused (notmuch_mailstore_t *mailstore),\r
++                      const char *filename)\r
++{\r
++    return fopen (filename, "r");\r
++}\r
++\r
++/* A mailstore is defined as:\r
++ *\r
++ * - A function used to "open" a mail message. This takes the\r
++ *   "filename" for the file and should return a FILE *.\r
++ *\r
++ * - TODO: A way to scan for new messages?\r
++ *\r
++ * - TODO: A "constructor"?\r
++ */\r
++_notmuch_mailstore\r
++notmuch_mailstore_maildir = { _maildir_open_function };\r
++\r
++_notmuch_mailstore *\r
++notmuch_mailstore_get_by_name (const char *name)\r
++{\r
++    if (strcmp (name, "maildir") == 0)\r
++      return &notmuch_mailstore_maildir;\r
++\r
++    return NULL;\r
++}\r
++\r
++FILE *\r
++notmuch_mailstore_open (notmuch_mailstore_t *mailstore, const char *filename)\r
++{\r
++    return mailstore->open (mailstore, filename);\r
++}\r
+diff --git a/lib/message-file.c b/lib/message-file.c\r
+index 915aba8..61f4d04 100644\r
+--- a/lib/message-file.c\r
++++ b/lib/message-file.c\r
+@@ -94,7 +94,8 @@ _notmuch_message_file_destructor (notmuch_message_file_t *message)\r
+ /* Create a new notmuch_message_file_t for 'filename' with 'ctx' as\r
+  * the talloc owner. */\r
+ notmuch_message_file_t *\r
+-_notmuch_message_file_open_ctx (void *ctx, const char *filename)\r
++_notmuch_message_file_open_ctx (void *ctx, notmuch_mailstore_t *mailstore,\r
++                              const char *filename)\r
+ {\r
+     notmuch_message_file_t *message;\r
\r
+@@ -104,7 +105,7 @@ _notmuch_message_file_open_ctx (void *ctx, const char *filename)\r
\r
+     talloc_set_destructor (message, _notmuch_message_file_destructor);\r
\r
+-    message->file = fopen (filename, "r");\r
++    message->file = notmuch_mailstore_open (mailstore, filename);\r
+     if (message->file == NULL)\r
+       goto FAIL;\r
\r
+@@ -126,9 +127,10 @@ _notmuch_message_file_open_ctx (void *ctx, const char *filename)\r
+ }\r
\r
+ notmuch_message_file_t *\r
+-notmuch_message_file_open (const char *filename)\r
++notmuch_message_file_open (notmuch_mailstore_t *mailstore,\r
++                         const char *filename)\r
+ {\r
+-    return _notmuch_message_file_open_ctx (NULL, filename);\r
++    return _notmuch_message_file_open_ctx (NULL, mailstore, filename);\r
+ }\r
\r
+ void\r
+diff --git a/lib/message.cc b/lib/message.cc\r
+index 0075425..762a18f 100644\r
+--- a/lib/message.cc\r
++++ b/lib/message.cc\r
+@@ -395,7 +395,8 @@ notmuch_message_get_message_id (notmuch_message_t *message)\r
+ }\r
\r
+ static void\r
+-_notmuch_message_ensure_message_file (notmuch_message_t *message)\r
++_notmuch_message_ensure_message_file (notmuch_mailstore_t *mailstore,\r
++                                    notmuch_message_t *message)\r
+ {\r
+     const char *filename;\r
\r
+@@ -406,11 +407,13 @@ _notmuch_message_ensure_message_file (notmuch_message_t *message)\r
+     if (unlikely (filename == NULL))\r
+       return;\r
\r
+-    message->message_file = _notmuch_message_file_open_ctx (message, filename);\r
++    message->message_file = _notmuch_message_file_open_ctx (message, mailstore,\r
++                                                          filename);\r
+ }\r
\r
+ const char *\r
+-notmuch_message_get_header (notmuch_message_t *message, const char *header)\r
++notmuch_message_get_header (notmuch_mailstore_t *mailstore,\r
++                          notmuch_message_t *message, const char *header)\r
+ {\r
+     std::string value;\r
\r
+@@ -427,7 +430,7 @@ notmuch_message_get_header (notmuch_message_t *message, const char *header)\r
+       return talloc_strdup (message, value.c_str ());\r
\r
+     /* Otherwise fall back to parsing the file */\r
+-    _notmuch_message_ensure_message_file (message);\r
++    _notmuch_message_ensure_message_file (mailstore, message);\r
+     if (message->message_file == NULL)\r
+       return NULL;\r
\r
+diff --git a/lib/notmuch-private.h b/lib/notmuch-private.h\r
+index 7bf153e..0f01437 100644\r
+--- a/lib/notmuch-private.h\r
++++ b/lib/notmuch-private.h\r
+@@ -331,11 +331,14 @@ typedef struct _notmuch_message_file notmuch_message_file_t;\r
+  * Returns NULL if any error occurs.\r
+  */\r
+ notmuch_message_file_t *\r
+-notmuch_message_file_open (const char *filename);\r
++notmuch_message_file_open (notmuch_mailstore_t *mailstore,\r
++                         const char *filename);\r
\r
+ /* Like notmuch_message_file_open but with 'ctx' as the talloc owner. */\r
+ notmuch_message_file_t *\r
+-_notmuch_message_file_open_ctx (void *ctx, const char *filename);\r
++_notmuch_message_file_open_ctx (void *ctx,\r
++                              notmuch_mailstore_t *mailstore,\r
++                              const char *filename);\r
\r
+ /* Close a notmuch message previously opened with notmuch_message_open. */\r
+ void\r
+diff --git a/lib/notmuch.h b/lib/notmuch.h\r
+index 7929fe7..7ebe034 100644\r
+--- a/lib/notmuch.h\r
++++ b/lib/notmuch.h\r
+@@ -123,6 +123,7 @@ typedef struct _notmuch_message notmuch_message_t;\r
+ typedef struct _notmuch_tags notmuch_tags_t;\r
+ typedef struct _notmuch_directory notmuch_directory_t;\r
+ typedef struct _notmuch_filenames notmuch_filenames_t;\r
++typedef struct _notmuch_mailstore notmuch_mailstore_t;\r
\r
+ /* Create a new, empty notmuch database located at 'path'.\r
+  *\r
+@@ -144,7 +145,7 @@ typedef struct _notmuch_filenames notmuch_filenames_t;\r
+  * an error message on stderr).\r
+  */\r
+ notmuch_database_t *\r
+-notmuch_database_create (const char *path);\r
++notmuch_database_create (notmuch_mailstore_t *mailstore, const char *path);\r
\r
+ typedef enum {\r
+     NOTMUCH_DATABASE_MODE_READ_ONLY = 0,\r
+@@ -172,7 +173,8 @@ typedef enum {\r
+  * an error message on stderr).\r
+  */\r
+ notmuch_database_t *\r
+-notmuch_database_open (const char *path,\r
++notmuch_database_open (notmuch_mailstore_t *mailstore,\r
++                     const char *path,\r
+                      notmuch_database_mode_t mode);\r
\r
+ /* Close the given notmuch database, freeing all associated\r
+@@ -409,6 +411,18 @@ notmuch_database_find_message_by_filename (notmuch_database_t *notmuch,\r
+ notmuch_tags_t *\r
+ notmuch_database_get_all_tags (notmuch_database_t *db);\r
\r
++/* Return a mail storage backend based on the given name.\r
++ *\r
++ * Storage backends are required in order to manipulate message files.\r
++ */\r
++notmuch_mailstore_t *\r
++notmuch_mailstore_get_by_name (const char *name);\r
++\r
++/* Get an input stream for a filename.\r
++ */\r
++FILE *\r
++notmuch_mailstore_open (notmuch_mailstore_t *mailstore, const char *filename);\r
++\r
+ /* Create a new query for 'database'.\r
+  *\r
+  * Here, 'database' should be an open database, (see\r
+@@ -929,7 +943,8 @@ notmuch_message_get_date  (notmuch_message_t *message);\r
+  * header line matching 'header'. Returns NULL if any error occurs.\r
+  */\r
+ const char *\r
+-notmuch_message_get_header (notmuch_message_t *message, const char *header);\r
++notmuch_message_get_header (notmuch_mailstore_t *mailstore,\r
++                          notmuch_message_t *message, const char *header);\r
\r
+ /* Get the tags for 'message', returning a notmuch_tags_t object which\r
+  * can be used to iterate over all tags.\r
+diff --git a/lib/thread.cc b/lib/thread.cc\r
+index 0435ee6..73edf83 100644\r
+--- a/lib/thread.cc\r
++++ b/lib/thread.cc\r
+@@ -213,7 +213,8 @@ _thread_cleanup_author (notmuch_thread_t *thread,\r
+  * reference to it.\r
+  */\r
+ static void\r
+-_thread_add_message (notmuch_thread_t *thread,\r
++_thread_add_message (notmuch_mailstore_t *mailstore,\r
++                   notmuch_thread_t *thread,\r
+                    notmuch_message_t *message)\r
+ {\r
+     notmuch_tags_t *tags;\r
+@@ -231,7 +232,7 @@ _thread_add_message (notmuch_thread_t *thread,\r
+                        xstrdup (notmuch_message_get_message_id (message)),\r
+                        message);\r
\r
+-    from = notmuch_message_get_header (message, "from");\r
++    from = notmuch_message_get_header (mailstore, message, "from");\r
+     if (from)\r
+       list = internet_address_list_parse_string (from);\r
\r
+@@ -253,7 +254,7 @@ _thread_add_message (notmuch_thread_t *thread,\r
\r
+     if (! thread->subject) {\r
+       const char *subject;\r
+-      subject = notmuch_message_get_header (message, "subject");\r
++      subject = notmuch_message_get_header (mailstore, message, "subject");\r
+       thread->subject = talloc_strdup (thread, subject ? subject : "");\r
+     }\r
\r
+@@ -267,13 +268,14 @@ _thread_add_message (notmuch_thread_t *thread,\r
+ }\r
\r
+ static void\r
+-_thread_set_subject_from_message (notmuch_thread_t *thread,\r
++_thread_set_subject_from_message (notmuch_mailstore_t *mailstore,\r
++                                notmuch_thread_t *thread,\r
+                                 notmuch_message_t *message)\r
+ {\r
+     const char *subject;\r
+     const char *cleaned_subject;\r
\r
+-    subject = notmuch_message_get_header (message, "subject");\r
++    subject = notmuch_message_get_header (mailstore, message, "subject");\r
+     if (! subject)\r
+       return;\r
\r
+@@ -300,7 +302,8 @@ _thread_set_subject_from_message (notmuch_thread_t *thread,\r
+  * oldest or newest matching subject is applied to the thread as a\r
+  * whole. */\r
+ static void\r
+-_thread_add_matched_message (notmuch_thread_t *thread,\r
++_thread_add_matched_message (notmuch_mailstore_t *mailstore,\r
++                           notmuch_thread_t *thread,\r
+                            notmuch_message_t *message,\r
+                            notmuch_sort_t sort)\r
+ {\r
+@@ -312,13 +315,13 @@ _thread_add_matched_message (notmuch_thread_t *thread,\r
+     if (date < thread->oldest || ! thread->matched_messages) {\r
+       thread->oldest = date;\r
+       if (sort == NOTMUCH_SORT_OLDEST_FIRST)\r
+-          _thread_set_subject_from_message (thread, message);\r
++          _thread_set_subject_from_message (mailstore, thread, message);\r
+     }\r
\r
+     if (date > thread->newest || ! thread->matched_messages) {\r
+       thread->newest = date;\r
+       if (sort != NOTMUCH_SORT_OLDEST_FIRST)\r
+-          _thread_set_subject_from_message (thread, message);\r
++          _thread_set_subject_from_message (mailstore, thread, message);\r
+     }\r
\r
+     thread->matched_messages++;\r
+@@ -467,11 +470,12 @@ _notmuch_thread_create (void *ctx,\r
+       if (doc_id == seed_doc_id)\r
+           message = seed_message;\r
\r
+-      _thread_add_message (thread, message);\r
++      _thread_add_message (notmuch->mailstore, thread, message);\r
\r
+       if ( _notmuch_doc_id_set_contains (match_set, doc_id)) {\r
+           _notmuch_doc_id_set_remove (match_set, doc_id);\r
+-          _thread_add_matched_message (thread, message, sort);\r
++          _thread_add_matched_message (notmuch->mailstore, thread,\r
++                                       message, sort);\r
+       }\r
\r
+       _notmuch_message_close (message);\r
+diff --git a/notmuch-client.h b/notmuch-client.h\r
+index 4518cb0..c1c30a2 100644\r
+--- a/notmuch-client.h\r
++++ b/notmuch-client.h\r
+@@ -68,14 +68,17 @@ struct notmuch_show_params;\r
+ typedef struct notmuch_show_format {\r
+     const char *message_set_start;\r
+     void (*part) (const void *ctx,\r
++                notmuch_mailstore_t *mailstore,\r
+                 struct mime_node *node, int indent,\r
+                 const struct notmuch_show_params *params);\r
+     const char *message_start;\r
+     void (*message) (const void *ctx,\r
++                   notmuch_mailstore_t *mailstore,\r
+                    notmuch_message_t *message,\r
+                    int indent);\r
+     const char *header_start;\r
+     void (*header) (const void *ctx,\r
++                  notmuch_mailstore_t *mailstore,\r
+                   notmuch_message_t *message);\r
+     void (*header_message_part) (GMimeMessage *message);\r
+     const char *header_end;\r
+@@ -226,6 +229,9 @@ void\r
+ notmuch_config_set_database_type (notmuch_config_t *config,\r
+                                 const char *database_type);\r
\r
++notmuch_mailstore_t *\r
++notmuch_config_get_mailstore (notmuch_config_t *config);\r
++\r
+ const char *\r
+ notmuch_config_get_user_name (notmuch_config_t *config);\r
\r
+diff --git a/notmuch-config.c b/notmuch-config.c\r
+index b8bee69..f611b26 100644\r
+--- a/notmuch-config.c\r
++++ b/notmuch-config.c\r
+@@ -584,6 +584,18 @@ notmuch_config_set_database_type (notmuch_config_t *config,\r
+     config->database_type = NULL;\r
+ }\r
\r
++notmuch_mailstore_t *\r
++notmuch_config_get_mailstore (notmuch_config_t *config)\r
++{\r
++    /* This is just a stub since there's only one mailstore.\r
++     *\r
++     * When there are multiple mailstore types and "constructors" for\r
++     * them, this may have to be much more complicated.\r
++     */\r
++    const char *type = notmuch_config_get_database_type (config);\r
++    return notmuch_mailstore_get_by_name (type);\r
++}\r
++\r
+ const char *\r
+ notmuch_config_get_user_name (notmuch_config_t *config)\r
+ {\r
+diff --git a/notmuch-count.c b/notmuch-count.c\r
+index 63459fb..0c7beef 100644\r
+--- a/notmuch-count.c\r
++++ b/notmuch-count.c\r
+@@ -57,7 +57,8 @@ notmuch_count_command (void *ctx, int argc, char *argv[])\r
+     if (config == NULL)\r
+       return 1;\r
\r
+-    notmuch = notmuch_database_open (notmuch_config_get_database_path (config),\r
++    notmuch = notmuch_database_open (notmuch_config_get_mailstore (config),\r
++                                   notmuch_config_get_database_path (config),\r
+                                    NOTMUCH_DATABASE_MODE_READ_ONLY);\r
+     if (notmuch == NULL)\r
+       return 1;\r
+diff --git a/notmuch-dump.c b/notmuch-dump.c\r
+index a735875..f7729dd 100644\r
+--- a/notmuch-dump.c\r
++++ b/notmuch-dump.c\r
+@@ -36,7 +36,8 @@ notmuch_dump_command (unused (void *ctx), int argc, char *argv[])\r
+     if (config == NULL)\r
+       return 1;\r
\r
+-    notmuch = notmuch_database_open (notmuch_config_get_database_path (config),\r
++    notmuch = notmuch_database_open (notmuch_config_get_mailstore (config),\r
++                                   notmuch_config_get_database_path (config),\r
+                                    NOTMUCH_DATABASE_MODE_READ_ONLY);\r
+     if (notmuch == NULL)\r
+       return 1;\r
+diff --git a/notmuch-new.c b/notmuch-new.c\r
+index 8dbebb3..355dde4 100644\r
+--- a/notmuch-new.c\r
++++ b/notmuch-new.c\r
+@@ -808,6 +808,7 @@ notmuch_new_command (void *ctx, int argc, char *argv[])\r
+ {\r
+     notmuch_config_t *config;\r
+     notmuch_database_t *notmuch;\r
++    notmuch_mailstore_t *mailstore;\r
+     add_files_state_t add_files_state;\r
+     double elapsed;\r
+     struct timeval tv_now, tv_start;\r
+@@ -843,6 +844,7 @@ notmuch_new_command (void *ctx, int argc, char *argv[])\r
+     add_files_state.new_tags = notmuch_config_get_new_tags (config, &add_files_state.new_tags_length);\r
+     add_files_state.synchronize_flags = notmuch_config_get_maildir_synchronize_flags (config);\r
+     db_path = notmuch_config_get_database_path (config);\r
++    mailstore = notmuch_config_get_mailstore (config);\r
\r
+     if (run_hooks) {\r
+       ret = notmuch_run_hook (db_path, "pre-new");\r
+@@ -861,10 +863,12 @@ notmuch_new_command (void *ctx, int argc, char *argv[])\r
+           return 1;\r
\r
+       printf ("Found %d total files (that's not much mail).\n", count);\r
+-      notmuch = notmuch_database_create (db_path);\r
++      notmuch = notmuch_database_create (mailstore,\r
++                                         db_path);\r
+       add_files_state.total_files = count;\r
+     } else {\r
+-      notmuch = notmuch_database_open (db_path,\r
++      notmuch = notmuch_database_open (mailstore,\r
++                                       db_path,\r
+                                        NOTMUCH_DATABASE_MODE_READ_WRITE);\r
+       if (notmuch == NULL)\r
+           return 1;\r
+diff --git a/notmuch-reply.c b/notmuch-reply.c\r
+index 6b244e6..cb1dd6e 100644\r
+--- a/notmuch-reply.c\r
++++ b/notmuch-reply.c\r
+@@ -256,14 +256,15 @@ scan_address_string (const char *recipients,\r
+  * in either the 'To' or 'Cc' header of the message?\r
+  */\r
+ static int\r
+-reply_to_header_is_redundant (notmuch_message_t *message)\r
++reply_to_header_is_redundant (notmuch_mailstore_t *mailstore,\r
++                            notmuch_message_t *message)\r
+ {\r
+     const char *reply_to, *to, *cc, *addr;\r
+     InternetAddressList *list;\r
+     InternetAddress *address;\r
+     InternetAddressMailbox *mailbox;\r
\r
+-    reply_to = notmuch_message_get_header (message, "reply-to");\r
++    reply_to = notmuch_message_get_header (mailstore, message, "reply-to");\r
+     if (reply_to == NULL || *reply_to == '\0')\r
+       return 0;\r
\r
+@@ -279,8 +280,8 @@ reply_to_header_is_redundant (notmuch_message_t *message)\r
+     mailbox = INTERNET_ADDRESS_MAILBOX (address);\r
+     addr = internet_address_mailbox_get_addr (mailbox);\r
\r
+-    to = notmuch_message_get_header (message, "to");\r
+-    cc = notmuch_message_get_header (message, "cc");\r
++    to = notmuch_message_get_header (mailstore, message, "to");\r
++    cc = notmuch_message_get_header (mailstore, message, "cc");\r
\r
+     if ((to && strstr (to, addr) != 0) ||\r
+       (cc && strstr (cc, addr) != 0))\r
+@@ -319,10 +320,13 @@ add_recipients_from_message (GMimeMessage *reply,\r
+       { "cc",         NULL, GMIME_RECIPIENT_TYPE_CC  },\r
+       { "bcc",        NULL, GMIME_RECIPIENT_TYPE_BCC }\r
+     };\r
++    notmuch_mailstore_t *mailstore;\r
+     const char *from_addr = NULL;\r
+     unsigned int i;\r
+     unsigned int n = 0;\r
\r
++    mailstore = notmuch_config_get_mailstore (config);\r
++\r
+     /* Some mailing lists munge the Reply-To header despite it being A Bad\r
+      * Thing, see http://www.unicom.com/pw/reply-to-harmful.html\r
+      *\r
+@@ -334,7 +338,7 @@ add_recipients_from_message (GMimeMessage *reply,\r
+      * that the address in the Reply-To header will always appear in\r
+      * the reply.\r
+      */\r
+-    if (reply_to_header_is_redundant (message)) {\r
++    if (reply_to_header_is_redundant (mailstore, message)) {\r
+       reply_to_map[0].header = "from";\r
+       reply_to_map[0].fallback = NULL;\r
+     }\r
+@@ -342,10 +346,10 @@ add_recipients_from_message (GMimeMessage *reply,\r
+     for (i = 0; i < ARRAY_SIZE (reply_to_map); i++) {\r
+       const char *recipients;\r
\r
+-      recipients = notmuch_message_get_header (message,\r
++      recipients = notmuch_message_get_header (mailstore, message,\r
+                                                reply_to_map[i].header);\r
+       if ((recipients == NULL || recipients[0] == '\0') && reply_to_map[i].fallback)\r
+-          recipients = notmuch_message_get_header (message,\r
++          recipients = notmuch_message_get_header (mailstore, message,\r
+                                                    reply_to_map[i].fallback);\r
\r
+       n += scan_address_string (recipients, config, reply,\r
+@@ -374,6 +378,7 @@ add_recipients_from_message (GMimeMessage *reply,\r
+ static const char *\r
+ guess_from_received_header (notmuch_config_t *config, notmuch_message_t *message)\r
+ {\r
++    notmuch_mailstore_t *mailstore;\r
+     const char *received,*primary,*by;\r
+     const char **other;\r
+     char *tohdr;\r
+@@ -387,6 +392,7 @@ guess_from_received_header (notmuch_config_t *config, notmuch_message_t *message\r
\r
+     primary = notmuch_config_get_user_primary_email (config);\r
+     other = notmuch_config_get_user_other_email (config, &other_len);\r
++    mailstore = notmuch_config_get_mailstore (config);\r
\r
+     /* sadly, there is no standard way to find out to which email\r
+      * address a mail was delivered - what is in the headers depends\r
+@@ -403,7 +409,8 @@ guess_from_received_header (notmuch_config_t *config, notmuch_message_t *message\r
+      * If none of these work, we give up and return NULL\r
+      */\r
+     for (i = 0; i < sizeof(to_headers)/sizeof(*to_headers); i++) {\r
+-      tohdr = xstrdup(notmuch_message_get_header (message, to_headers[i]));\r
++      tohdr = xstrdup(notmuch_message_get_header (mailstore,\r
++                                                  message, to_headers[i]));\r
+       if (tohdr && *tohdr) {\r
+           /* tohdr is potentialy a list of email addresses, so here we\r
+            * check if one of the email addresses is a substring of tohdr\r
+@@ -428,7 +435,7 @@ guess_from_received_header (notmuch_config_t *config, notmuch_message_t *message\r
+      * The Received: header is special in our get_header function\r
+      * and is always concatenated.\r
+      */\r
+-    received = notmuch_message_get_header (message, "received");\r
++    received = notmuch_message_get_header (mailstore, message, "received");\r
+     if (received == NULL)\r
+       return NULL;\r
\r
+@@ -515,10 +522,12 @@ notmuch_reply_format_default(void *ctx,\r
+     GMimeMessage *reply;\r
+     notmuch_messages_t *messages;\r
+     notmuch_message_t *message;\r
++    notmuch_mailstore_t *mailstore;\r
+     const char *subject, *from_addr = NULL;\r
+     const char *in_reply_to, *orig_references, *references;\r
+     const notmuch_show_format_t *format = &format_reply;\r
\r
++    mailstore = notmuch_config_get_mailstore (config);\r
+     for (messages = notmuch_query_search_messages (query);\r
+        notmuch_messages_valid (messages);\r
+        notmuch_messages_move_to_next (messages))\r
+@@ -532,7 +541,7 @@ notmuch_reply_format_default(void *ctx,\r
+           return 1;\r
+       }\r
\r
+-      subject = notmuch_message_get_header (message, "subject");\r
++      subject = notmuch_message_get_header (mailstore, message, "subject");\r
+       if (subject) {\r
+           if (strncasecmp (subject, "Re:", 3))\r
+               subject = talloc_asprintf (ctx, "Re: %s", subject);\r
+@@ -560,7 +569,8 @@ notmuch_reply_format_default(void *ctx,\r
+       g_mime_object_set_header (GMIME_OBJECT (reply),\r
+                                 "In-Reply-To", in_reply_to);\r
\r
+-      orig_references = notmuch_message_get_header (message, "references");\r
++      orig_references = notmuch_message_get_header (mailstore,\r
++                                                    message, "references");\r
+       references = talloc_asprintf (ctx, "%s%s%s",\r
+                                     orig_references ? orig_references : "",\r
+                                     orig_references ? " " : "",\r
+@@ -574,8 +584,8 @@ notmuch_reply_format_default(void *ctx,\r
+       reply = NULL;\r
\r
+       printf ("On %s, %s wrote:\n",\r
+-              notmuch_message_get_header (message, "date"),\r
+-              notmuch_message_get_header (message, "from"));\r
++              notmuch_message_get_header (mailstore, message, "date"),\r
++              notmuch_message_get_header (mailstore, message, "from"));\r
\r
+       show_message_body (message, format, params);\r
\r
+@@ -595,9 +605,12 @@ notmuch_reply_format_headers_only(void *ctx,\r
+     GMimeMessage *reply;\r
+     notmuch_messages_t *messages;\r
+     notmuch_message_t *message;\r
++    notmuch_mailstore_t *mailstore;\r
+     const char *in_reply_to, *orig_references, *references;\r
+     char *reply_headers;\r
\r
++    mailstore = notmuch_config_get_mailstore (config);\r
++\r
+     for (messages = notmuch_query_search_messages (query);\r
+        notmuch_messages_valid (messages);\r
+        notmuch_messages_move_to_next (messages))\r
+@@ -618,7 +631,8 @@ notmuch_reply_format_headers_only(void *ctx,\r
+                                 "In-Reply-To", in_reply_to);\r
\r
\r
+-      orig_references = notmuch_message_get_header (message, "references");\r
++      orig_references = notmuch_message_get_header (mailstore, message,\r
++                                                    "references");\r
\r
+       /* We print In-Reply-To followed by References because git format-patch treats them\r
+          * specially.  Git does not interpret the other headers specially\r
+@@ -720,7 +734,8 @@ notmuch_reply_command (void *ctx, int argc, char *argv[])\r
+       return 1;\r
+     }\r
\r
+-    notmuch = notmuch_database_open (notmuch_config_get_database_path (config),\r
++    notmuch = notmuch_database_open (notmuch_config_get_mailstore (config),\r
++                                   notmuch_config_get_database_path (config),\r
+                                    NOTMUCH_DATABASE_MODE_READ_ONLY);\r
+     if (notmuch == NULL)\r
+       return 1;\r
+diff --git a/notmuch-restore.c b/notmuch-restore.c\r
+index 87d9772..b382b7b 100644\r
+--- a/notmuch-restore.c\r
++++ b/notmuch-restore.c\r
+@@ -40,7 +40,8 @@ notmuch_restore_command (unused (void *ctx), int argc, char *argv[])\r
+     if (config == NULL)\r
+       return 1;\r
\r
+-    notmuch = notmuch_database_open (notmuch_config_get_database_path (config),\r
++    notmuch = notmuch_database_open (notmuch_config_get_mailstore (config),\r
++                                   notmuch_config_get_database_path (config),\r
+                                    NOTMUCH_DATABASE_MODE_READ_WRITE);\r
+     if (notmuch == NULL)\r
+       return 1;\r
+diff --git a/notmuch-search.c b/notmuch-search.c\r
+index d504051..8ba3c48 100644\r
+--- a/notmuch-search.c\r
++++ b/notmuch-search.c\r
+@@ -470,7 +470,8 @@ notmuch_search_command (void *ctx, int argc, char *argv[])\r
+     if (config == NULL)\r
+       return 1;\r
\r
+-    notmuch = notmuch_database_open (notmuch_config_get_database_path (config),\r
++    notmuch = notmuch_database_open (notmuch_config_get_mailstore (config),\r
++                                   notmuch_config_get_database_path (config),\r
+                                    NOTMUCH_DATABASE_MODE_READ_ONLY);\r
+     if (notmuch == NULL)\r
+       return 1;\r
+diff --git a/notmuch-show.c b/notmuch-show.c\r
+index d930f94..81d4cf0 100644\r
+--- a/notmuch-show.c\r
++++ b/notmuch-show.c\r
+@@ -24,7 +24,8 @@ static void\r
+ format_headers_message_part_text (GMimeMessage *message);\r
\r
+ static void\r
+-format_part_text (const void *ctx, mime_node_t *node,\r
++format_part_text (const void *ctx, notmuch_mailstore_t *mailstore,\r
++                mime_node_t *node,\r
+                 int indent, const notmuch_show_params_t *params);\r
\r
+ static const notmuch_show_format_t format_text = {\r
+@@ -36,10 +37,12 @@ static const notmuch_show_format_t format_text = {\r
\r
+ static void\r
+ format_message_json (const void *ctx,\r
++                   notmuch_mailstore_t *mailstore,\r
+                    notmuch_message_t *message,\r
+                    unused (int indent));\r
+ static void\r
+ format_headers_json (const void *ctx,\r
++                   notmuch_mailstore_t *mailstore,\r
+                    notmuch_message_t *message);\r
\r
+ static void\r
+@@ -83,6 +86,7 @@ static const notmuch_show_format_t format_json = {\r
\r
+ static void\r
+ format_message_mbox (const void *ctx,\r
++                   notmuch_mailstore_t *mailstore,\r
+                    notmuch_message_t *message,\r
+                    unused (int indent));\r
\r
+@@ -149,14 +153,15 @@ _get_tags_as_string (const void *ctx, notmuch_message_t *message)\r
\r
+ /* Get a nice, single-line summary of message. */\r
+ static const char *\r
+-_get_one_line_summary (const void *ctx, notmuch_message_t *message)\r
++_get_one_line_summary (const void *ctx, notmuch_mailstore_t *mailstore,\r
++                     notmuch_message_t *message)\r
+ {\r
+     const char *from;\r
+     time_t date;\r
+     const char *relative_date;\r
+     const char *tags;\r
\r
+-    from = notmuch_message_get_header (message, "from");\r
++    from = notmuch_message_get_header (mailstore, message, "from");\r
\r
+     date = notmuch_message_get_date (message);\r
+     relative_date = notmuch_time_relative_date (ctx, date);\r
+@@ -168,7 +173,8 @@ _get_one_line_summary (const void *ctx, notmuch_message_t *message)\r
+ }\r
\r
+ static void\r
+-format_message_json (const void *ctx, notmuch_message_t *message, unused (int indent))\r
++format_message_json (const void *ctx, unused (notmuch_mailstore_t *mailstore),\r
++                   notmuch_message_t *message, unused (int indent))\r
+ {\r
+     notmuch_tags_t *tags;\r
+     int first = 1;\r
+@@ -262,6 +268,7 @@ _is_from_line (const char *line)\r
+  */\r
+ static void\r
+ format_message_mbox (const void *ctx,\r
++                   notmuch_mailstore_t *mailstore,\r
+                    notmuch_message_t *message,\r
+                    unused (int indent))\r
+ {\r
+@@ -285,7 +292,7 @@ format_message_mbox (const void *ctx,\r
+       return;\r
+     }\r
\r
+-    from = notmuch_message_get_header (message, "from");\r
++    from = notmuch_message_get_header (mailstore, message, "from");\r
+     from = _extract_email_address (ctx, from);\r
\r
+     date = notmuch_message_get_date (message);\r
+@@ -327,7 +334,7 @@ format_headers_message_part_text (GMimeMessage *message)\r
+ }\r
\r
+ static void\r
+-format_headers_json (const void *ctx, notmuch_message_t *message)\r
++format_headers_json (const void *ctx, notmuch_mailstore_t *mailstore, notmuch_message_t *message)\r
+ {\r
+     const char *headers[] = {\r
+       "Subject", "From", "To", "Cc", "Bcc", "Date"\r
+@@ -339,7 +346,7 @@ format_headers_json (const void *ctx, notmuch_message_t *message)\r
\r
+     for (i = 0; i < ARRAY_SIZE (headers); i++) {\r
+       name = headers[i];\r
+-      value = notmuch_message_get_header (message, name);\r
++      value = notmuch_message_get_header (mailstore, message, name);\r
+       if (value)\r
+       {\r
+           if (!first_header)\r
+@@ -719,7 +726,8 @@ format_part_content_raw (GMimeObject *part)\r
+ }\r
\r
+ static void\r
+-format_part_text (const void *ctx, mime_node_t *node,\r
++format_part_text (const void *ctx, notmuch_mailstore_t *mailstore,\r
++                mime_node_t *node,\r
+                 int indent, const notmuch_show_params_t *params)\r
+ {\r
+     /* The disposition and content-type metadata are associated with\r
+@@ -768,7 +776,8 @@ format_part_text (const void *ctx, mime_node_t *node,\r
\r
+       printf ("\fheader{\n");\r
+       if (node->envelope_file)\r
+-          printf ("%s\n", _get_one_line_summary (ctx, node->envelope_file));\r
++          printf ("%s\n", _get_one_line_summary (ctx, mailstore,\r
++                                                 node->envelope_file));\r
+       printf ("Subject: %s\n", g_mime_message_get_subject (message));\r
+       printf ("From: %s\n", g_mime_message_get_sender (message));\r
+       recipients = g_mime_message_get_recipients (message, GMIME_RECIPIENT_TYPE_TO);\r
+@@ -800,7 +809,8 @@ format_part_text (const void *ctx, mime_node_t *node,\r
+     }\r
\r
+     for (i = 0; i < node->nchildren; i++)\r
+-      format_part_text (ctx, mime_node_child (node, i), indent, params);\r
++      format_part_text (ctx, mailstore, mime_node_child (node, i),\r
++                        indent, params);\r
\r
+     if (GMIME_IS_MESSAGE (node->part))\r
+       printf ("\fbody}\n");\r
+@@ -811,6 +821,7 @@ format_part_text (const void *ctx, mime_node_t *node,\r
+ static void\r
+ show_message (void *ctx,\r
+             const notmuch_show_format_t *format,\r
++            notmuch_mailstore_t *mailstore,\r
+             notmuch_message_t *message,\r
+             int indent,\r
+             notmuch_show_params_t *params)\r
+@@ -823,7 +834,7 @@ show_message (void *ctx,\r
+                           &root) == NOTMUCH_STATUS_SUCCESS &&\r
+           (part = mime_node_seek_dfs (root, (params->part < 0 ?\r
+                                              0 : params->part))))\r
+-          format->part (local, part, indent, params);\r
++          format->part (local, mailstore, part, indent, params);\r
+       talloc_free (local);\r
+       return;\r
+     }\r
+@@ -831,11 +842,11 @@ show_message (void *ctx,\r
+     if (params->part <= 0) {\r
+       fputs (format->message_start, stdout);\r
+       if (format->message)\r
+-          format->message(ctx, message, indent);\r
++          format->message(ctx, mailstore, message, indent);\r
\r
+       fputs (format->header_start, stdout);\r
+       if (format->header)\r
+-          format->header(ctx, message);\r
++          format->header(ctx, mailstore, message);\r
+       fputs (format->header_end, stdout);\r
\r
+       fputs (format->body_start, stdout);\r
+@@ -854,6 +865,7 @@ show_message (void *ctx,\r
+ static void\r
+ show_messages (void *ctx,\r
+              const notmuch_show_format_t *format,\r
++             notmuch_mailstore_t *mailstore,\r
+              notmuch_messages_t *messages,\r
+              int indent,\r
+              notmuch_show_params_t *params)\r
+@@ -882,7 +894,7 @@ show_messages (void *ctx,\r
+       next_indent = indent;\r
\r
+       if (match || params->entire_thread) {\r
+-          show_message (ctx, format, message, indent, params);\r
++          show_message (ctx, format, mailstore, message, indent, params);\r
+           next_indent = indent + 1;\r
\r
+           fputs (format->message_set_sep, stdout);\r
+@@ -890,6 +902,7 @@ show_messages (void *ctx,\r
\r
+       show_messages (ctx,\r
+                      format,\r
++                     mailstore,\r
+                      notmuch_message_get_replies (message),\r
+                      next_indent,\r
+                      params);\r
+@@ -905,6 +918,7 @@ show_messages (void *ctx,\r
+ /* Formatted output of single message */\r
+ static int\r
+ do_show_single (void *ctx,\r
++              notmuch_mailstore_t *mailstore,\r
+               notmuch_query_t *query,\r
+               const notmuch_show_format_t *format,\r
+               notmuch_show_params_t *params)\r
+@@ -966,7 +980,7 @@ do_show_single (void *ctx,\r
\r
+     } else {\r
\r
+-      show_message (ctx, format, message, 0, params);\r
++      show_message (ctx, format, mailstore, message, 0, params);\r
\r
+     }\r
\r
+@@ -976,6 +990,7 @@ do_show_single (void *ctx,\r
+ /* Formatted output of threads */\r
+ static int\r
+ do_show (void *ctx,\r
++       notmuch_mailstore_t *mailstore,\r
+        notmuch_query_t *query,\r
+        const notmuch_show_format_t *format,\r
+        notmuch_show_params_t *params)\r
+@@ -1003,7 +1018,7 @@ do_show (void *ctx,\r
+           fputs (format->message_set_sep, stdout);\r
+       first_toplevel = 0;\r
\r
+-      show_messages (ctx, format, messages, 0, params);\r
++      show_messages (ctx, format, mailstore, messages, 0, params);\r
\r
+       notmuch_thread_destroy (thread);\r
\r
+@@ -1027,6 +1042,7 @@ notmuch_show_command (void *ctx, unused (int argc), unused (char *argv[]))\r
+ {\r
+     notmuch_config_t *config;\r
+     notmuch_database_t *notmuch;\r
++    notmuch_mailstore_t *mailstore;\r
+     notmuch_query_t *query;\r
+     char *query_string;\r
+     int opt_index, ret;\r
+@@ -1122,7 +1138,9 @@ notmuch_show_command (void *ctx, unused (int argc), unused (char *argv[]))\r
+       return 1;\r
+     }\r
\r
+-    notmuch = notmuch_database_open (notmuch_config_get_database_path (config),\r
++    mailstore = notmuch_config_get_mailstore (config);\r
++    notmuch = notmuch_database_open (mailstore,\r
++                                   notmuch_config_get_database_path (config),\r
+                                    NOTMUCH_DATABASE_MODE_READ_ONLY);\r
+     if (notmuch == NULL)\r
+       return 1;\r
+@@ -1134,9 +1152,9 @@ notmuch_show_command (void *ctx, unused (int argc), unused (char *argv[]))\r
+     }\r
\r
+     if (params.part >= 0)\r
+-      ret = do_show_single (ctx, query, format, &params);\r
++      ret = do_show_single (ctx, mailstore, query, format, &params);\r
+     else\r
+-      ret = do_show (ctx, query, format, &params);\r
++      ret = do_show (ctx, mailstore, query, format, &params);\r
\r
+     notmuch_query_destroy (query);\r
+     notmuch_database_close (notmuch);\r
+diff --git a/notmuch-tag.c b/notmuch-tag.c\r
+index 36b9b09..5e8d74a 100644\r
+--- a/notmuch-tag.c\r
++++ b/notmuch-tag.c\r
+@@ -187,7 +187,8 @@ notmuch_tag_command (void *ctx, int argc, char *argv[])\r
+     if (config == NULL)\r
+       return 1;\r
\r
+-    notmuch = notmuch_database_open (notmuch_config_get_database_path (config),\r
++    notmuch = notmuch_database_open (notmuch_config_get_mailstore (config),\r
++                                   notmuch_config_get_database_path (config),\r
+                                    NOTMUCH_DATABASE_MODE_READ_WRITE);\r
+     if (notmuch == NULL)\r
+       return 1;\r
+diff --git a/test/symbol-test.cc b/test/symbol-test.cc\r
+index 1548ca4..36c6ddb 100644\r
+--- a/test/symbol-test.cc\r
++++ b/test/symbol-test.cc\r
+@@ -4,7 +4,8 @@\r
\r
\r
+ int main() {\r
+-  (void) notmuch_database_open("fakedb", NOTMUCH_DATABASE_MODE_READ_ONLY);\r
++  (void) notmuch_database_open (notmuch_mailstore_get_by_name ("maildir"),\r
++                                "fakedb", NOTMUCH_DATABASE_MODE_READ_ONLY);\r
\r
+   try {\r
+     (void) new Xapian::WritableDatabase("./nonexistant", Xapian::DB_OPEN);\r
+-- \r
+1.7.5.4\r
+\r