--- /dev/null
+Return-Path: <sojkam1@fel.cvut.cz>\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 23FBE404965\r
+ for <notmuch@notmuchmail.org>; Thu, 18 Mar 2010 08:40:59 -0700 (PDT)\r
+X-Virus-Scanned: Debian amavisd-new at olra.theworths.org\r
+X-Spam-Flag: NO\r
+X-Spam-Score: -2.269\r
+X-Spam-Level: \r
+X-Spam-Status: No, score=-2.269 tagged_above=-999 required=5 tests=[AWL=0.330,\r
+ BAYES_00=-2.599] autolearn=ham\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 OKmA-PbJGQQg for <notmuch@notmuchmail.org>;\r
+ Thu, 18 Mar 2010 08:40:55 -0700 (PDT)\r
+Received: from max.feld.cvut.cz (max.feld.cvut.cz [147.32.192.36])\r
+ by olra.theworths.org (Postfix) with ESMTP id 81BEE404964\r
+ for <notmuch@notmuchmail.org>; Thu, 18 Mar 2010 08:40:54 -0700 (PDT)\r
+Received: from localhost (unknown [192.168.200.4])\r
+ by max.feld.cvut.cz (Postfix) with ESMTP id E82B719F3409;\r
+ Thu, 18 Mar 2010 16:40:53 +0100 (CET)\r
+X-Virus-Scanned: IMAP AMAVIS\r
+Received: from max.feld.cvut.cz ([192.168.200.1])\r
+ by localhost (styx.feld.cvut.cz [192.168.200.4]) (amavisd-new,\r
+ port 10044)\r
+ with ESMTP id xS-7LdHy5MBJ; Thu, 18 Mar 2010 16:40:51 +0100 (CET)\r
+Received: from imap.feld.cvut.cz (imap.feld.cvut.cz [147.32.192.34])\r
+ by max.feld.cvut.cz (Postfix) with ESMTP id 1D18519F3401;\r
+ Thu, 18 Mar 2010 16:40:51 +0100 (CET)\r
+Received: from steelpick.localdomain (k335-30.felk.cvut.cz [147.32.86.30])\r
+ (Authenticated sender: sojkam1)\r
+ by imap.feld.cvut.cz (Postfix) with ESMTPSA id ED612FA004;\r
+ Thu, 18 Mar 2010 16:40:50 +0100 (CET)\r
+Received: from wsh by steelpick.localdomain with local (Exim 4.71)\r
+ (envelope-from <sojkam1@fel.cvut.cz>)\r
+ id 1NsHq6-0005Hf-It; Thu, 18 Mar 2010 16:40:50 +0100\r
+From: Michal Sojka <sojkam1@fel.cvut.cz>\r
+To: notmuch@notmuchmail.org\r
+Date: Thu, 18 Mar 2010 16:39:37 +0100\r
+Message-Id: <1268926780-20045-2-git-send-email-sojkam1@fel.cvut.cz>\r
+X-Mailer: git-send-email 1.7.0\r
+In-Reply-To: <1268926780-20045-1-git-send-email-sojkam1@fel.cvut.cz>\r
+References: <1268926780-20045-1-git-send-email-sojkam1@fel.cvut.cz>\r
+Subject: [notmuch] [PATCH 1/4] Mailstore abstraction interface\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: Thu, 18 Mar 2010 15:40:59 -0000\r
+\r
+The goal of mailstore abstraction is to allow notmuch to store tags\r
+together with email messages. The abstract interface is needed because\r
+people want to use different ways of storing their emails. This\r
+patchseries implements two types of mailstore - plain files and\r
+maildir. It is expected that additional git-based mailstore will\r
+follow.\r
+\r
+This patch contains only the interface changes. No functionality is\r
+added, removed or changed.\r
+\r
+A new configuration group [mailstore] is defined. Currently, there is\r
+only one key 'type' whose value determines the used mailstore. The\r
+default value of this option is the plain-file mailstore currently\r
+implemented in notmuch.\r
+\r
+Signed-off-by: Michal Sojka <sojkam1@fel.cvut.cz>\r
+---\r
+ lib/Makefile.local | 2 +\r
+ lib/database-private.h | 1 +\r
+ lib/database.cc | 15 ++++++--\r
+ lib/mailstore-files.c | 43 ++++++++++++++++++++++++\r
+ lib/mailstore-private.h | 59 ++++++++++++++++++++++++++++++++\r
+ lib/mailstore.c | 77 ++++++++++++++++++++++++++++++++++++++++++\r
+ lib/message.cc | 13 +++++++\r
+ lib/notmuch.h | 85 ++++++++++++++++++++++++++++++++++++++++++++--\r
+ notmuch-client.h | 7 ++++\r
+ notmuch-config.c | 34 +++++++++++++++++++\r
+ notmuch-count.c | 3 +-\r
+ notmuch-dump.c | 3 +-\r
+ notmuch-new.c | 6 ++-\r
+ notmuch-reply.c | 3 +-\r
+ notmuch-restore.c | 3 +-\r
+ notmuch-search-tags.c | 3 +-\r
+ notmuch-search.c | 3 +-\r
+ notmuch-show.c | 3 +-\r
+ notmuch-tag.c | 3 +-\r
+ 19 files changed, 348 insertions(+), 18 deletions(-)\r
+ create mode 100644 lib/mailstore-files.c\r
+ create mode 100644 lib/mailstore-private.h\r
+ create mode 100644 lib/mailstore.c\r
+\r
+diff --git a/lib/Makefile.local b/lib/Makefile.local\r
+index 495b27e..fc8883d 100644\r
+--- a/lib/Makefile.local\r
++++ b/lib/Makefile.local\r
+@@ -3,6 +3,8 @@ extra_cflags += -I$(dir)\r
+ \r
+ libnotmuch_c_srcs = \\r
+ $(dir)/libsha1.c \\r
++ $(dir)/mailstore.c \\r
++ $(dir)/mailstore-files.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 41918d7..4499b1a 100644\r
+--- a/lib/database-private.h\r
++++ b/lib/database-private.h\r
+@@ -49,6 +49,7 @@ struct _notmuch_database {\r
+ Xapian::TermGenerator *term_gen;\r
+ Xapian::ValueRangeProcessor *value_range_processor;\r
+ \r
++ notmuch_mailstore_t *mailstore;\r
+ };\r
+ \r
+ /* Convert tags from Xapian internal format to notmuch format.\r
+diff --git a/lib/database.cc b/lib/database.cc\r
+index c91e97c..93c8d0f 100644\r
+--- a/lib/database.cc\r
++++ b/lib/database.cc\r
+@@ -19,6 +19,7 @@\r
+ */\r
+ \r
+ #include "database-private.h"\r
++#include "mailstore-private.h"\r
+ \r
+ #include <iostream>\r
+ \r
+@@ -438,7 +439,7 @@ parse_references (void *ctx,\r
+ }\r
+ \r
+ notmuch_database_t *\r
+-notmuch_database_create (const char *path)\r
++notmuch_database_create (const char *path, notmuch_mailstore_t *mailstore)\r
+ {\r
+ notmuch_database_t *notmuch = NULL;\r
+ char *notmuch_path = NULL;\r
+@@ -474,7 +475,8 @@ notmuch_database_create (const char *path)\r
+ }\r
+ \r
+ notmuch = notmuch_database_open (path,\r
+- NOTMUCH_DATABASE_MODE_READ_WRITE);\r
++ NOTMUCH_DATABASE_MODE_READ_WRITE,\r
++ mailstore);\r
+ notmuch_database_upgrade (notmuch, NULL, NULL);\r
+ \r
+ DONE:\r
+@@ -497,7 +499,8 @@ _notmuch_database_ensure_writable (notmuch_database_t *notmuch)\r
+ \r
+ notmuch_database_t *\r
+ notmuch_database_open (const char *path,\r
+- notmuch_database_mode_t mode)\r
++ notmuch_database_mode_t mode,\r
++ notmuch_mailstore_t *mailstore)\r
+ {\r
+ notmuch_database_t *notmuch = NULL;\r
+ char *notmuch_path = NULL, *xapian_path = NULL;\r
+@@ -605,6 +608,9 @@ notmuch_database_open (const char *path,\r
+ prefix_t *prefix = &PROBABILISTIC_PREFIX[i];\r
+ notmuch->query_parser->add_prefix (prefix->name, prefix->prefix);\r
+ }\r
++\r
++ notmuch->mailstore = mailstore;\r
++ mailstore->notmuch = notmuch;\r
+ } catch (const Xapian::Error &error) {\r
+ fprintf (stderr, "A Xapian exception occurred opening database: %s\n",\r
+ error.get_msg().c_str());\r
+@@ -1493,7 +1499,8 @@ notmuch_database_add_message (notmuch_database_t *notmuch,\r
+ \r
+ DONE:\r
+ if (message) {\r
+- if (ret == NOTMUCH_STATUS_SUCCESS && message_ret)\r
++ if ((ret == NOTMUCH_STATUS_SUCCESS ||\r
++ ret == NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID) && message_ret)\r
+ *message_ret = message;\r
+ else\r
+ notmuch_message_destroy (message);\r
+diff --git a/lib/mailstore-files.c b/lib/mailstore-files.c\r
+new file mode 100644\r
+index 0000000..92d7f5d\r
+--- /dev/null\r
++++ b/lib/mailstore-files.c\r
+@@ -0,0 +1,43 @@\r
++/* mailstore-files.c - Original notmuch mail store - a collection of\r
++ * plain-text email messages (one message per file).\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
++ * Authors: Carl Worth <cworth@cworth.org>\r
++ * Michal Sojka <sojkam1@fel.cvut.cz>\r
++ */\r
++\r
++#include "notmuch.h"\r
++#include "mailstore-private.h"\r
++\r
++\r
++static FILE *\r
++open_file(notmuch_mailstore_t *mailstore, const char *filename)\r
++{\r
++ const char *db_path, *abs_filename;\r
++\r
++ db_path = notmuch_database_get_path(mailstore->notmuch);\r
++ abs_filename = talloc_asprintf(mailstore, "%s/%s", db_path, filename);\r
++ if (unlikely(abs_filename == NULL))\r
++ return NULL;\r
++ return fopen (abs_filename, "r");\r
++}\r
++\r
++/* Original notmuch mail store */\r
++struct _notmuch_mailstore mailstore_files = {\r
++ .type = "files",\r
++ .open_file = open_file,\r
++};\r
+diff --git a/lib/mailstore-private.h b/lib/mailstore-private.h\r
+new file mode 100644\r
+index 0000000..f606e3f\r
+--- /dev/null\r
++++ b/lib/mailstore-private.h\r
+@@ -0,0 +1,59 @@\r
++/* mailstore-private.h - Mailstore abstraction\r
++ *\r
++ * Copyright © 2010 Michal Sojka\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
++ * Author: Michal Sojka <sojkam1@fel.cvut.cz>\r
++ */\r
++\r
++#ifndef MAILSTORE_PRIVATE_H\r
++#define MAILSTORE_PRIVATE_H\r
++\r
++#include "notmuch-private.h"\r
++\r
++struct _notmuch_mailstore {\r
++ /* Constant fields */\r
++ const char *type; /* identification in .notmuch-config */\r
++ void *priv;\r
++\r
++ /* Count files in mailstore so that initial invocation of notmuch\r
++ * new can report remaining time */\r
++ void (*count_files)(notmuch_mailstore_t *mailstore,\r
++ const char *path, int *count,\r
++ volatile sig_atomic_t *interrupted);\r
++ /* Scan for new messages and add them to the database. */\r
++ notmuch_private_status_t (*index_new)(notmuch_mailstore_t *mailstore,\r
++ const char* path,\r
++ notmuch_indexing_context_t *ctx);\r
++ /* Store the tags assigned to the 'messages' to the\r
++ * 'mailstore'. */\r
++ notmuch_private_status_t (*sync_tags)(notmuch_mailstore_t *mailstore,\r
++ notmuch_message_t *message);\r
++ /* Return file handle from which the message can be read.\r
++ *\r
++ * Currently, this is not used and all message access is hardcoded\r
++ * to notmuch. We will need this operation for git-based and other\r
++ * non-filesystem mailstores. */\r
++ FILE * (*open_file)(notmuch_mailstore_t *mailstore,\r
++ const char *filename);\r
++\r
++ /* Run-time fields */\r
++ notmuch_database_t *notmuch;\r
++};\r
++\r
++extern struct _notmuch_mailstore mailstore_files;\r
++extern struct _notmuch_mailstore mailstore_maildir;\r
++\r
++#endif /* MAILSTORE_PRIVATE_H */\r
+diff --git a/lib/mailstore.c b/lib/mailstore.c\r
+new file mode 100644\r
+index 0000000..cdac9a6\r
+--- /dev/null\r
++++ b/lib/mailstore.c\r
+@@ -0,0 +1,77 @@\r
++/* mailstore.c - Mailstore abstraction\r
++ *\r
++ * Copyright © 2010 Michal Sojka\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
++ * Author: Michal Sojka <sojkam1@fel.cvut.cz>\r
++ */\r
++\r
++#include <notmuch.h>\r
++#include "mailstore-private.h"\r
++\r
++#define ARRAY_SIZE(arr) (sizeof (arr) / sizeof (arr[0]))\r
++\r
++static notmuch_mailstore_t *available[] = {\r
++ &mailstore_files,\r
++};\r
++\r
++notmuch_mailstore_t *\r
++notmuch_mailstore_get_by_type (const char *type)\r
++{\r
++ unsigned i;\r
++\r
++ if (type == NULL)\r
++ return available[0];\r
++\r
++ for (i = 0; i < ARRAY_SIZE(available); i++) {\r
++ if (strcasecmp (type, available[i]->type) == 0)\r
++ return available[i];\r
++ }\r
++ return NULL;\r
++}\r
++\r
++const char *\r
++notmuch_mailstore_get_type (notmuch_mailstore_t *mailstore)\r
++{\r
++ if (!mailstore)\r
++ return NULL;\r
++\r
++ return mailstore->type;\r
++}\r
++\r
++void\r
++notmuch_mailstore_count_files (notmuch_mailstore_t *mailstore,\r
++ const char *path, int *count,\r
++ volatile sig_atomic_t *interrupted)\r
++{\r
++ mailstore->count_files (mailstore, path, count, interrupted);\r
++}\r
++\r
++notmuch_status_t\r
++notmuch_mailstore_index_new (notmuch_mailstore_t *mailstore,\r
++ const char *path,\r
++ notmuch_indexing_context_t *ctx)\r
++{\r
++ notmuch_private_status_t status;\r
++ status = mailstore->index_new (mailstore, path, ctx);\r
++ return COERCE_STATUS (status, "Index new");\r
++}\r
++\r
++FILE *\r
++notmuch_mailstore_open_file (notmuch_mailstore_t *mailstore,\r
++ const char *filename)\r
++{\r
++ return mailstore->open_file (mailstore, filename);\r
++}\r
+diff --git a/lib/message.cc b/lib/message.cc\r
+index 721c9a6..c32ee7d 100644\r
+--- a/lib/message.cc\r
++++ b/lib/message.cc\r
+@@ -20,6 +20,7 @@\r
+ \r
+ #include "notmuch-private.h"\r
+ #include "database-private.h"\r
++#include "mailstore-private.h"\r
+ \r
+ #include <stdint.h>\r
+ \r
+@@ -555,10 +556,22 @@ void\r
+ _notmuch_message_sync (notmuch_message_t *message)\r
+ {\r
+ Xapian::WritableDatabase *db;\r
++ notmuch_private_status_t status;\r
+ \r
+ if (message->notmuch->mode == NOTMUCH_DATABASE_MODE_READ_ONLY)\r
+ return;\r
+ \r
++ if (message->notmuch->mailstore->sync_tags) {\r
++ status = message->notmuch->mailstore->sync_tags (message->notmuch->mailstore,\r
++ message);\r
++ if (status != NOTMUCH_PRIVATE_STATUS_SUCCESS) {\r
++ fprintf (stderr, "Error: Cannot sync tags to mailstore (%s)\n",\r
++ notmuch_status_to_string ((notmuch_status_t)status));\r
++ /* Exit to avoid unsynchronized mailstore. */\r
++ exit(1);\r
++ }\r
++ }\r
++\r
+ db = static_cast <Xapian::WritableDatabase *> (message->notmuch->xapian_db);\r
+ db->replace_document (message->doc_id, message->doc);\r
+ }\r
+diff --git a/lib/notmuch.h b/lib/notmuch.h\r
+index 0d9cb0f..4f4cc8b 100644\r
+--- a/lib/notmuch.h\r
++++ b/lib/notmuch.h\r
+@@ -32,6 +32,9 @@\r
+ NOTMUCH_BEGIN_DECLS\r
+ \r
+ #include <time.h>\r
++#include <sys/time.h> /* For struct timeval */\r
++#include <signal.h> /* For sig_atomic_t */\r
++#include <stdio.h> /* For FILE */\r
+ \r
+ #ifndef FALSE\r
+ #define FALSE 0\r
+@@ -119,6 +122,8 @@ 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
+ \r
+ /* Create a new, empty notmuch database located at 'path'.\r
+ *\r
+@@ -127,6 +132,8 @@ typedef struct _notmuch_filenames notmuch_filenames_t;\r
+ * create a new ".notmuch" directory within 'path' where notmuch will\r
+ * store its data.\r
+ *\r
++ * FIXME: Mailstore...\r
++ *\r
+ * After a successful call to notmuch_database_create, the returned\r
+ * database will be open so the caller should call\r
+ * notmuch_database_close when finished with it.\r
+@@ -140,7 +147,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 (const char *path, notmuch_mailstore_t *mailstore);\r
+ \r
+ typedef enum {\r
+ NOTMUCH_DATABASE_MODE_READ_ONLY = 0,\r
+@@ -152,6 +159,8 @@ typedef enum {\r
+ \r
+ /* Open an existing notmuch database located at 'path'.\r
+ *\r
++ * The database will index mails stored in 'mailstore'.\r
++ *\r
+ * The database should have been created at some time in the past,\r
+ * (not necessarily by this process), by calling\r
+ * notmuch_database_create with 'path'. By default the database should be\r
+@@ -169,7 +178,8 @@ typedef enum {\r
+ */\r
+ notmuch_database_t *\r
+ notmuch_database_open (const char *path,\r
+- notmuch_database_mode_t mode);\r
++ notmuch_database_mode_t mode,\r
++ notmuch_mailstore_t *mailstore);\r
+ \r
+ /* Close the given notmuch database, freeing all associated\r
+ * resources. See notmuch_database_open. */\r
+@@ -236,7 +246,8 @@ notmuch_database_get_directory (notmuch_database_t *database,\r
+ * notmuch database will reference the filename, and will not copy the\r
+ * entire contents of the file.\r
+ *\r
+- * If 'message' is not NULL, then, on successful return '*message'\r
++ * If 'message' is not NULL, then, on successful return\r
++ * (NOTMUCH_STATUS_SUCCESS or NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID) '*message'\r
+ * will be initialized to a message object that can be used for things\r
+ * such as adding tags to the just-added message. The user should call\r
+ * notmuch_message_destroy when done with the message. On any failure\r
+@@ -495,7 +506,7 @@ notmuch_threads_destroy (notmuch_threads_t *threads);\r
+ */\r
+ unsigned\r
+ notmuch_query_count_messages (notmuch_query_t *query);\r
+- \r
++\r
+ /* Get the thread ID of 'thread'.\r
+ *\r
+ * The returned string belongs to 'thread' and as such, should not be\r
+@@ -1104,6 +1115,72 @@ notmuch_filenames_move_to_next (notmuch_filenames_t *filenames);\r
+ void\r
+ notmuch_filenames_destroy (notmuch_filenames_t *filenames);\r
+ \r
++/* Returns notmuch_mailstore_t object of a given 'type'.\r
++ *\r
++ * The 'type' is case insensitive. If 'type' is NULL, a default\r
++ * mailstore is returned.\r
++ *\r
++ * When no available mailstore matches 'type', NULL is returned.\r
++ */\r
++notmuch_mailstore_t *\r
++notmuch_mailstore_get_by_type (const char *type);\r
++\r
++/* Returns the type of a mailstore.\r
++ *\r
++ * The returned string is owned by mailstore so should not be modified\r
++ * nor freed by the caller.\r
++ */\r
++const char *\r
++notmuch_mailstore_get_type (notmuch_mailstore_t *mailstore);\r
++\r
++/* Count emails in mailstore.\r
++ *\r
++ * This function returns when interrupted is set to non-zero value.\r
++ */\r
++void\r
++notmuch_mailstore_count_files (notmuch_mailstore_t *mailstore,\r
++ const char *path, int *count,\r
++ volatile sig_atomic_t *interrupted);\r
++\r
++typedef struct notmuch_indexing_context {\r
++ int output_is_a_tty;\r
++ int verbose;\r
++\r
++ int total_files;\r
++ int processed_files;\r
++ int added_messages;\r
++ int renamed_files;\r
++ int removed_files;\r
++ struct timeval tv_start;\r
++\r
++ void *priv;\r
++\r
++ volatile sig_atomic_t interrupted;\r
++ volatile sig_atomic_t print_progress;\r
++ void (*print_progress_cb)(struct notmuch_indexing_context *ctx);\r
++\r
++} notmuch_indexing_context_t;\r
++\r
++\r
++/* Index new mails in the mailstore.\r
++ *\r
++ * Mailstore is responsible for detecting new emails, adding them to\r
++ * the database and tagging them with tags stored in the mailstore.\r
++ */\r
++notmuch_status_t\r
++notmuch_mailstore_index_new (notmuch_mailstore_t *mailstore,\r
++ const char *path,\r
++ notmuch_indexing_context_t *ctx);\r
++\r
++/* Returns file handle to the file in the mailstore.\r
++ *\r
++ * TODO: This function is currently not used and access to mails is\r
++ * hardcoded in other parts of notmuch.\r
++ */\r
++FILE *\r
++notmuch_mailstore_open_file (notmuch_mailstore_t *mailstore,\r
++ const char *filename);\r
++\r
+ NOTMUCH_END_DECLS\r
+ \r
+ #endif\r
+diff --git a/notmuch-client.h b/notmuch-client.h\r
+index c80b39c..4794b8e 100644\r
+--- a/notmuch-client.h\r
++++ b/notmuch-client.h\r
+@@ -171,6 +171,13 @@ notmuch_config_set_user_other_email (notmuch_config_t *config,\r
+ const char *other_email[],\r
+ size_t length);\r
+ \r
++notmuch_mailstore_t *\r
++notmuch_config_get_mailstore(notmuch_config_t *config);\r
++\r
++void\r
++notmuch_config_set_mailstore(notmuch_config_t *config,\r
++ notmuch_mailstore_t *mailstore);\r
++\r
+ notmuch_bool_t\r
+ debugger_is_active (void);\r
+ \r
+diff --git a/notmuch-config.c b/notmuch-config.c\r
+index 95430db..299423a 100644\r
+--- a/notmuch-config.c\r
++++ b/notmuch-config.c\r
+@@ -62,6 +62,7 @@ struct _notmuch_config {\r
+ char *user_primary_email;\r
+ char **user_other_email;\r
+ size_t user_other_email_length;\r
++ notmuch_mailstore_t *mailstore;\r
+ };\r
+ \r
+ static int\r
+@@ -199,6 +200,7 @@ notmuch_config_open (void *ctx,\r
+ config->user_primary_email = NULL;\r
+ config->user_other_email = NULL;\r
+ config->user_other_email_length = 0;\r
++ config->mailstore = NULL;\r
+ \r
+ if (! g_key_file_load_from_file (config->key_file,\r
+ config->filename,\r
+@@ -264,6 +266,10 @@ notmuch_config_open (void *ctx,\r
+ }\r
+ }\r
+ \r
++ if (notmuch_config_get_mailstore (config) == NULL) {\r
++ notmuch_config_set_mailstore(config, notmuch_mailstore_get_by_type(NULL));\r
++ }\r
++\r
+ /* When we create a new configuration file here, we add some\r
+ * comments to help the user understand what can be done. */\r
+ if (is_new) {\r
+@@ -452,3 +458,31 @@ notmuch_config_set_user_other_email (notmuch_config_t *config,\r
+ talloc_free (config->user_other_email);\r
+ config->user_other_email = NULL;\r
+ }\r
++\r
++notmuch_mailstore_t *\r
++notmuch_config_get_mailstore(notmuch_config_t *config)\r
++{\r
++ char *type;\r
++\r
++ if (config->mailstore == NULL) {\r
++ type = g_key_file_get_string (config->key_file,\r
++ "mailstore", "type", NULL);\r
++ if (type) {\r
++ config->mailstore = notmuch_mailstore_get_by_type(type);\r
++ free (type);\r
++ }\r
++ }\r
++\r
++ return config->mailstore;\r
++}\r
++\r
++void\r
++notmuch_config_set_mailstore(notmuch_config_t *config,\r
++ notmuch_mailstore_t *mailstore)\r
++{\r
++ g_key_file_set_string (config->key_file,\r
++ "mailstore", "type",\r
++ notmuch_mailstore_get_type(mailstore));\r
++\r
++ config->mailstore = NULL;\r
++}\r
+diff --git a/notmuch-count.c b/notmuch-count.c\r
+index 77aa433..631b8f8 100644\r
+--- a/notmuch-count.c\r
++++ b/notmuch-count.c\r
+@@ -81,7 +81,8 @@ notmuch_count_command (void *ctx, int argc, char *argv[])\r
+ return 1;\r
+ \r
+ notmuch = notmuch_database_open (notmuch_config_get_database_path (config),\r
+- NOTMUCH_DATABASE_MODE_READ_ONLY);\r
++ NOTMUCH_DATABASE_MODE_READ_ONLY,\r
++ notmuch_config_get_mailstore(config));\r
+ if (notmuch == NULL)\r
+ return 1;\r
+ \r
+diff --git a/notmuch-dump.c b/notmuch-dump.c\r
+index 7e7bc17..e74dfcb 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
+ return 1;\r
+ \r
+ notmuch = notmuch_database_open (notmuch_config_get_database_path (config),\r
+- NOTMUCH_DATABASE_MODE_READ_ONLY);\r
++ NOTMUCH_DATABASE_MODE_READ_ONLY,\r
++ notmuch_config_get_mailstore (config));\r
+ if (notmuch == NULL)\r
+ return 1;\r
+ \r
+diff --git a/notmuch-new.c b/notmuch-new.c\r
+index 44b50aa..2d0ba6c 100644\r
+--- a/notmuch-new.c\r
++++ b/notmuch-new.c\r
+@@ -749,11 +749,13 @@ 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 (db_path,\r
++ notmuch_config_get_mailstore (config));\r
+ add_files_state.total_files = count;\r
+ } else {\r
+ notmuch = notmuch_database_open (db_path,\r
+- NOTMUCH_DATABASE_MODE_READ_WRITE);\r
++ NOTMUCH_DATABASE_MODE_READ_WRITE,\r
++ notmuch_config_get_mailstore (config));\r
+ if (notmuch == NULL)\r
+ return 1;\r
+ \r
+diff --git a/notmuch-reply.c b/notmuch-reply.c\r
+index 6c15536..0d6b7cf 100644\r
+--- a/notmuch-reply.c\r
++++ b/notmuch-reply.c\r
+@@ -468,7 +468,8 @@ notmuch_reply_command (void *ctx, int argc, char *argv[])\r
+ }\r
+ \r
+ notmuch = notmuch_database_open (notmuch_config_get_database_path (config),\r
+- NOTMUCH_DATABASE_MODE_READ_ONLY);\r
++ NOTMUCH_DATABASE_MODE_READ_ONLY,\r
++ notmuch_config_get_mailstore (config));\r
+ if (notmuch == NULL)\r
+ return 1;\r
+ \r
+diff --git a/notmuch-restore.c b/notmuch-restore.c\r
+index b0a4e1c..97d817b 100644\r
+--- a/notmuch-restore.c\r
++++ b/notmuch-restore.c\r
+@@ -37,7 +37,8 @@ notmuch_restore_command (unused (void *ctx), int argc, char *argv[])\r
+ return 1;\r
+ \r
+ notmuch = notmuch_database_open (notmuch_config_get_database_path (config),\r
+- NOTMUCH_DATABASE_MODE_READ_WRITE);\r
++ NOTMUCH_DATABASE_MODE_READ_WRITE,\r
++ notmuch_config_get_mailstore (config));\r
+ if (notmuch == NULL)\r
+ return 1;\r
+ \r
+diff --git a/notmuch-search-tags.c b/notmuch-search-tags.c\r
+index 6f3cfcc..323f416 100644\r
+--- a/notmuch-search-tags.c\r
++++ b/notmuch-search-tags.c\r
+@@ -52,7 +52,8 @@ notmuch_search_tags_command (void *ctx, int argc, char *argv[])\r
+ }\r
+ \r
+ db = notmuch_database_open (notmuch_config_get_database_path (config),\r
+- NOTMUCH_DATABASE_MODE_READ_ONLY);\r
++ NOTMUCH_DATABASE_MODE_READ_ONLY,\r
++ notmuch_config_get_mailstore (config));\r
+ if (db == NULL) {\r
+ goto error;\r
+ }\r
+diff --git a/notmuch-search.c b/notmuch-search.c\r
+index 4e3514b..d57479d 100644\r
+--- a/notmuch-search.c\r
++++ b/notmuch-search.c\r
+@@ -245,7 +245,8 @@ notmuch_search_command (void *ctx, int argc, char *argv[])\r
+ return 1;\r
+ \r
+ notmuch = notmuch_database_open (notmuch_config_get_database_path (config),\r
+- NOTMUCH_DATABASE_MODE_READ_ONLY);\r
++ NOTMUCH_DATABASE_MODE_READ_ONLY,\r
++ notmuch_config_get_mailstore (config));\r
+ if (notmuch == NULL)\r
+ return 1;\r
+ \r
+diff --git a/notmuch-show.c b/notmuch-show.c\r
+index ff1fecb..26581c1 100644\r
+--- a/notmuch-show.c\r
++++ b/notmuch-show.c\r
+@@ -458,7 +458,8 @@ notmuch_show_command (void *ctx, unused (int argc), unused (char *argv[]))\r
+ }\r
+ \r
+ notmuch = notmuch_database_open (notmuch_config_get_database_path (config),\r
+- NOTMUCH_DATABASE_MODE_READ_ONLY);\r
++ NOTMUCH_DATABASE_MODE_READ_ONLY,\r
++ notmuch_config_get_mailstore (config));\r
+ if (notmuch == NULL)\r
+ return 1;\r
+ \r
+diff --git a/notmuch-tag.c b/notmuch-tag.c\r
+index 8b6f7dc..5e1a5c3 100644\r
+--- a/notmuch-tag.c\r
++++ b/notmuch-tag.c\r
+@@ -97,7 +97,8 @@ notmuch_tag_command (void *ctx, unused (int argc), unused (char *argv[]))\r
+ return 1;\r
+ \r
+ notmuch = notmuch_database_open (notmuch_config_get_database_path (config),\r
+- NOTMUCH_DATABASE_MODE_READ_WRITE);\r
++ NOTMUCH_DATABASE_MODE_READ_WRITE,\r
++ notmuch_config_get_mailstore (config));\r
+ if (notmuch == NULL)\r
+ return 1;\r
+ \r
+-- \r
+1.7.0\r
+\r