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