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 213D541733F for ; Sat, 27 Mar 2010 13:44:42 -0700 (PDT) X-Virus-Scanned: Debian amavisd-new at olra.theworths.org X-Spam-Flag: NO X-Spam-Score: -1.9 X-Spam-Level: X-Spam-Status: No, score=-1.9 tagged_above=-999 required=5 tests=[BAYES_00=-1.9] autolearn=ham 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 cGwBzSnYHH9O for ; Sat, 27 Mar 2010 13:44:38 -0700 (PDT) Received: from max.feld.cvut.cz (max.feld.cvut.cz [147.32.192.36]) by olra.theworths.org (Postfix) with ESMTP id EA52B4196F5 for ; Sat, 27 Mar 2010 13:44:33 -0700 (PDT) Received: from localhost (unknown [192.168.200.4]) by max.feld.cvut.cz (Postfix) with ESMTP id 514A419F3419; Sat, 27 Mar 2010 21:44:33 +0100 (CET) X-Virus-Scanned: IMAP AMAVIS Received: from max.feld.cvut.cz ([192.168.200.1]) by localhost (styx.feld.cvut.cz [192.168.200.4]) (amavisd-new, port 10044) with ESMTP id VRT1Ad0wrKIy; Sat, 27 Mar 2010 21:44:31 +0100 (CET) Received: from imap.feld.cvut.cz (imap.feld.cvut.cz [147.32.192.34]) by max.feld.cvut.cz (Postfix) with ESMTP id 82D0519F341C; Sat, 27 Mar 2010 21:44:31 +0100 (CET) Received: from steelpick.2x.cz (r5da224.net.upc.cz [86.49.116.224]) (Authenticated sender: sojkam1) by imap.feld.cvut.cz (Postfix) with ESMTPSA id 46B73FA006; Sat, 27 Mar 2010 21:44:31 +0100 (CET) Received: from wsh by steelpick.2x.cz with local (Exim 4.71) (envelope-from ) id 1Nvcru-0001ny-4U; Sat, 27 Mar 2010 21:44:30 +0100 From: Michal Sojka To: notmuch@notmuchmail.org Date: Sat, 27 Mar 2010 21:44:20 +0100 Message-Id: <1269722661-6894-5-git-send-email-sojkam1@fel.cvut.cz> X-Mailer: git-send-email 1.7.0.2 In-Reply-To: <8739zlijhp.fsf@steelpick.2x.cz> References: <8739zlijhp.fsf@steelpick.2x.cz> Subject: [notmuch] [PATCH v3 5/6] Access messages through mail store interface 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: Sat, 27 Mar 2010 20:44:42 -0000 This patch modifies notmuch binary to access the messages through mail store interface, so that non-file based mail stores can also be implemented. The API of notmuch library was changed. Now, notmuch_message_get_filename() returns relative file name with respect to the database path. As a result, notmuch show also outputs relative paths so that MUAs need to be changed. Signed-off-by: Michal Sojka --- lib/database.cc | 14 +++++++++++--- lib/index.cc | 8 ++++++-- lib/mailstore-files.c | 24 +++++++++++++++++------- lib/message-file.c | 8 ++++---- lib/message.cc | 33 +++++++++++++++++++++++++-------- lib/notmuch-private.h | 6 +++--- lib/notmuch.h | 16 ++++++++++++++-- lib/sha1.c | 6 +----- notmuch-client.h | 2 +- notmuch-reply.c | 10 +++++++++- notmuch-show.c | 14 ++++++++++++-- show-message.c | 14 +------------- 12 files changed, 104 insertions(+), 51 deletions(-) diff --git a/lib/database.cc b/lib/database.cc index 33ef889..4f3ce88 100644 --- a/lib/database.cc +++ b/lib/database.cc @@ -1374,6 +1374,7 @@ notmuch_database_add_message (notmuch_database_t *notmuch, notmuch_message_t *message = NULL; notmuch_status_t ret = NOTMUCH_STATUS_SUCCESS; notmuch_private_status_t private_status; + const char *relative; const char *date, *header; const char *from, *to, *subject; @@ -1386,7 +1387,8 @@ notmuch_database_add_message (notmuch_database_t *notmuch, if (ret) return ret; - message_file = notmuch_message_file_open (filename); + relative = _notmuch_database_relative_path (notmuch, filename); + message_file = notmuch_message_file_open (notmuch->mailstore, relative); if (message_file == NULL) return NOTMUCH_STATUS_FILE_ERROR; @@ -1438,9 +1440,15 @@ notmuch_database_add_message (notmuch_database_t *notmuch, } if (message_id == NULL ) { + FILE *file; + char *sha1 = NULL; /* No message-id at all, let's generate one by taking a * hash over the file's contents. */ - char *sha1 = notmuch_sha1_of_file (filename); + file = notmuch_mailstore_open_file (notmuch->mailstore, relative); + if (file) { + sha1 = notmuch_sha1_of_file (file); + fclose (file); + } /* If that failed too, something is really wrong. Give up. */ if (sha1 == NULL) { @@ -1490,7 +1498,7 @@ notmuch_database_add_message (notmuch_database_t *notmuch, date = notmuch_message_file_get_header (message_file, "date"); _notmuch_message_set_date (message, date); - _notmuch_message_index_file (message, filename); + _notmuch_message_index_file (message, relative); } else { ret = NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID; } diff --git a/lib/index.cc b/lib/index.cc index cf93025..4d8c4dd 100644 --- a/lib/index.cc +++ b/lib/index.cc @@ -425,15 +425,19 @@ _notmuch_message_index_file (notmuch_message_t *message, const char *from, *subject; notmuch_status_t ret = NOTMUCH_STATUS_SUCCESS; static int initialized = 0; + notmuch_mailstore_t *mailstore; if (! initialized) { g_mime_init (0); initialized = 1; } - file = fopen (filename, "r"); + mailstore = notmuch_message_get_mailstore(message); + file = notmuch_mailstore_open_file (mailstore, filename); if (! file) { - fprintf (stderr, "Error opening %s: %s\n", filename, strerror (errno)); + fprintf (stderr, "Error opening %s: %s\n", + notmuch_message_get_filename (message), + strerror (errno)); ret = NOTMUCH_STATUS_FILE_ERROR; goto DONE; } diff --git a/lib/mailstore-files.c b/lib/mailstore-files.c index b4e6e42..0250dba 100644 --- a/lib/mailstore-files.c +++ b/lib/mailstore-files.c @@ -246,9 +246,10 @@ maildir_sync_tags (notmuch_mailstore_t *mailstore, notmuch_message_t *message) { char flags[ARRAY_SIZE(flag2tag)+1]; - const char *filename, *p; + const char *filename, *p, *db_path; char *filename_new, *subdir = NULL; int ret; + char *abs1, *abs2; (void)mailstore; get_new_flags (message, flags); @@ -273,11 +274,16 @@ maildir_sync_tags (notmuch_mailstore_t *mailstore, strcpy (filename_new+(p-filename)+3, flags); if (strcmp (filename, filename_new) != 0) { - ret = rename (filename, filename_new); + db_path = notmuch_database_get_path (mailstore->notmuch); + asprintf(&abs1, "%s/%s", db_path, filename); + asprintf(&abs2, "%s/%s", db_path, filename_new); + ret = rename (abs1, abs2); if (ret == -1) { - perror (talloc_asprintf (message, "rename of %s to %s failed", filename, filename_new)); + perror (talloc_asprintf (message, "rename of %s to %s failed", abs1, abs2)); exit (1); } + free(abs1); + free(abs2); return _notmuch_message_rename (message, filename_new); /* _notmuch_message_sync is our caller. Do not call it here. */ } @@ -782,13 +788,17 @@ index_new(notmuch_mailstore_t *mailstore, const char* path, static FILE * open_file(notmuch_mailstore_t *mailstore, const char *filename) { - const char *db_path, *abs_filename; - + const char *db_path; + char *abs_filename; + FILE *file; + db_path = notmuch_database_get_path(mailstore->notmuch); - abs_filename = talloc_asprintf(mailstore, "%s/%s", db_path, filename); + abs_filename = talloc_asprintf(NULL, "%s/%s", db_path, filename); if (unlikely(abs_filename == NULL)) return NULL; - return fopen (abs_filename, "r"); + file = fopen (abs_filename, "r"); + talloc_free(abs_filename); + return file; } struct mailstore_priv files_priv = { diff --git a/lib/message-file.c b/lib/message-file.c index 3a1a681..5752e69 100644 --- a/lib/message-file.c +++ b/lib/message-file.c @@ -94,7 +94,7 @@ _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 +104,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_file(mailstore, filename); if (message->file == NULL) goto FAIL; @@ -126,9 +126,9 @@ _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 51208ba..292e95e 100644 --- a/lib/message.cc +++ b/lib/message.cc @@ -247,6 +247,7 @@ static void _notmuch_message_ensure_message_file (notmuch_message_t *message) { const char *filename; + notmuch_mailstore_t *mailstore; if (message->message_file) return; @@ -255,7 +256,9 @@ _notmuch_message_ensure_message_file (notmuch_message_t *message) if (unlikely (filename == NULL)) return; - message->message_file = _notmuch_message_file_open_ctx (message, filename); + mailstore = notmuch_message_get_mailstore (message); + + message->message_file = _notmuch_message_file_open_ctx (message, mailstore, filename); } const char * @@ -429,7 +432,7 @@ notmuch_message_get_filename (notmuch_message_t *message) int prefix_len = strlen (prefix); Xapian::TermIterator i; char *colon, *direntry = NULL; - const char *db_path, *directory, *basename; + const char *directory, *basename; unsigned int directory_id; void *local = talloc_new (message); @@ -474,18 +477,16 @@ notmuch_message_get_filename (notmuch_message_t *message) *colon = '\0'; - db_path = notmuch_database_get_path (message->notmuch); - directory = _notmuch_database_get_directory_path (local, message->notmuch, directory_id); if (strlen (directory)) - message->filename = talloc_asprintf (message, "%s/%s/%s", - db_path, directory, basename); - else message->filename = talloc_asprintf (message, "%s/%s", - db_path, basename); + directory, basename); + else + message->filename = talloc_asprintf (message, "%s", + basename); talloc_free ((void *) directory); talloc_free (local); @@ -493,6 +494,22 @@ notmuch_message_get_filename (notmuch_message_t *message) return message->filename; } +FILE * +notmuch_message_fopen (notmuch_message_t *message) +{ + const char *filename; + filename = notmuch_message_get_filename (message); + return notmuch_mailstore_open_file (message->notmuch->mailstore, + filename); +} + +notmuch_mailstore_t * +notmuch_message_get_mailstore (notmuch_message_t *message) +{ + return message->notmuch->mailstore; +} + + notmuch_bool_t notmuch_message_get_flag (notmuch_message_t *message, notmuch_message_flag_t flag) diff --git a/lib/notmuch-private.h b/lib/notmuch-private.h index 63e75ec..c257365 100644 --- a/lib/notmuch-private.h +++ b/lib/notmuch-private.h @@ -299,11 +299,11 @@ 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 @@ -406,7 +406,7 @@ char * notmuch_sha1_of_string (const char *str); char * -notmuch_sha1_of_file (const char *filename); +notmuch_sha1_of_file (FILE *file); /* tags.c */ diff --git a/lib/notmuch.h b/lib/notmuch.h index c554f6d..76ac6fc 100644 --- a/lib/notmuch.h +++ b/lib/notmuch.h @@ -742,8 +742,8 @@ notmuch_message_get_replies (notmuch_message_t *message); /* Get a filename for the email corresponding to 'message'. * - * The returned filename is an absolute filename, (the initial - * component will match notmuch_database_get_path() ). + * The returned filename is an relative filename of the message within + * the mail store. * * The returned string belongs to the message so should not be * modified or freed by the caller (nor should it be referenced after @@ -757,6 +757,18 @@ notmuch_message_get_replies (notmuch_message_t *message); const char * notmuch_message_get_filename (notmuch_message_t *message); +/* Return file handle to read the content of the message. + * + * This is a helper function which determines message filename and + * calls notmuch_mailstore_open_file(). + */ +FILE * +notmuch_message_fopen (notmuch_message_t *message); + +/* Get a pointer to the mailstore where the message is stored */ +notmuch_mailstore_t * +notmuch_message_get_mailstore (notmuch_message_t *message); + /* Message flags */ typedef enum _notmuch_message_flag { NOTMUCH_MESSAGE_FLAG_MATCH, diff --git a/lib/sha1.c b/lib/sha1.c index cc48108..a8991b1 100644 --- a/lib/sha1.c +++ b/lib/sha1.c @@ -74,9 +74,8 @@ notmuch_sha1_of_string (const char *str) * file not found, etc.), this function returns NULL. */ char * -notmuch_sha1_of_file (const char *filename) +notmuch_sha1_of_file (FILE *file) { - FILE *file; #define BLOCK_SIZE 4096 unsigned char block[BLOCK_SIZE]; size_t bytes_read; @@ -84,7 +83,6 @@ notmuch_sha1_of_file (const char *filename) unsigned char digest[SHA1_DIGEST_SIZE]; char *result; - file = fopen (filename, "r"); if (file == NULL) return NULL; @@ -108,8 +106,6 @@ notmuch_sha1_of_file (const char *filename) result = _hex_of_sha1_digest (digest); - fclose (file); - return result; } diff --git a/notmuch-client.h b/notmuch-client.h index 4794b8e..f5106cd 100644 --- a/notmuch-client.h +++ b/notmuch-client.h @@ -120,7 +120,7 @@ char * query_string_from_args (void *ctx, int argc, char *argv[]); notmuch_status_t -show_message_body (const char *filename, +show_message_body (FILE *file, void (*show_part) (GMimeObject *part, int *part_count)); char * diff --git a/notmuch-reply.c b/notmuch-reply.c index 0d6b7cf..a471137 100644 --- a/notmuch-reply.c +++ b/notmuch-reply.c @@ -285,6 +285,7 @@ add_recipients_from_message (GMimeMessage *reply, static int notmuch_reply_format_default(void *ctx, notmuch_config_t *config, notmuch_query_t *query) { + FILE *file; GMimeMessage *reply; notmuch_messages_t *messages; notmuch_message_t *message; @@ -350,7 +351,14 @@ notmuch_reply_format_default(void *ctx, notmuch_config_t *config, notmuch_query_ notmuch_message_get_header (message, "date"), notmuch_message_get_header (message, "from")); - show_message_body (notmuch_message_get_filename (message), reply_part); + file = notmuch_message_fopen (message); + if (file) { + show_message_body (file, reply_part); + fclose (file); + } else + fprintf (stderr, "Error opening %s: %s\n", + notmuch_message_get_filename (message), + strerror (errno)); notmuch_message_destroy (message); } diff --git a/notmuch-show.c b/notmuch-show.c index 26581c1..0fcaacf 100644 --- a/notmuch-show.c +++ b/notmuch-show.c @@ -336,6 +336,8 @@ format_part_json (GMimeObject *part, int *part_count) static void show_message (void *ctx, const show_format_t *format, notmuch_message_t *message, int indent) { + FILE *file; + fputs (format->message_start, stdout); if (format->message) format->message(ctx, message, indent); @@ -346,8 +348,16 @@ show_message (void *ctx, const show_format_t *format, notmuch_message_t *message fputs (format->header_end, stdout); fputs (format->body_start, stdout); - if (format->part) - show_message_body (notmuch_message_get_filename (message), format->part); + if (format->part) { + file = notmuch_message_fopen (message); + if (file) { + show_message_body (file, format->part); + fclose (file); + } else + fprintf (stderr, "Error opening %s: %s\n", + notmuch_message_get_filename (message), + strerror (errno)); + } fputs (format->body_end, stdout); fputs (format->message_end, stdout); diff --git a/show-message.c b/show-message.c index 05ced9c..2df859a 100644 --- a/show-message.c +++ b/show-message.c @@ -60,23 +60,15 @@ show_message_part (GMimeObject *part, int *part_count, } notmuch_status_t -show_message_body (const char *filename, +show_message_body (FILE *file, void (*show_part) (GMimeObject *part, int *part_count)) { GMimeStream *stream = NULL; GMimeParser *parser = NULL; GMimeMessage *mime_message = NULL; notmuch_status_t ret = NOTMUCH_STATUS_SUCCESS; - FILE *file = NULL; int part_count = 0; - file = fopen (filename, "r"); - if (! file) { - fprintf (stderr, "Error opening %s: %s\n", filename, strerror (errno)); - ret = NOTMUCH_STATUS_FILE_ERROR; - goto DONE; - } - stream = g_mime_stream_file_new (file); g_mime_stream_file_set_owner (GMIME_STREAM_FILE (stream), FALSE); @@ -87,7 +79,6 @@ show_message_body (const char *filename, show_message_part (g_mime_message_get_mime_part (mime_message), &part_count, show_part); - DONE: if (mime_message) g_object_unref (mime_message); @@ -97,8 +88,5 @@ show_message_body (const char *filename, if (stream) g_object_unref (stream); - if (file) - fclose (file); - return ret; } -- 1.7.0.2