--- /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 4EC304196F5\r
+ for <notmuch@notmuchmail.org>; Thu, 8 Apr 2010 07:43:12 -0700 (PDT)\r
+X-Virus-Scanned: Debian amavisd-new at olra.theworths.org\r
+X-Spam-Flag: NO\r
+X-Spam-Score: -1.9\r
+X-Spam-Level: \r
+X-Spam-Status: No, score=-1.9 tagged_above=-999 required=5\r
+ tests=[BAYES_00=-1.9] 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 dl2HlPiVMWYm for <notmuch@notmuchmail.org>;\r
+ Thu, 8 Apr 2010 07:43:08 -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 834274196F0\r
+ for <notmuch@notmuchmail.org>; Thu, 8 Apr 2010 07:43:07 -0700 (PDT)\r
+Received: from localhost (unknown [192.168.200.4])\r
+ by max.feld.cvut.cz (Postfix) with ESMTP id E5C9719F33D8;\r
+ Thu, 8 Apr 2010 16:43:06 +0200 (CEST)\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 4g-PakWlGmXu; Thu, 8 Apr 2010 16:43:05 +0200 (CEST)\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 165B519F3404;\r
+ Thu, 8 Apr 2010 16:43:05 +0200 (CEST)\r
+Received: from steelpick.2x.cz (k335-30.felk.cvut.cz [147.32.86.30])\r
+ (Authenticated sender: sojkam1)\r
+ by imap.feld.cvut.cz (Postfix) with ESMTPSA id 12ACF15C062;\r
+ Thu, 8 Apr 2010 16:43:05 +0200 (CEST)\r
+Received: from wsh by steelpick.2x.cz with local (Exim 4.71)\r
+ (envelope-from <sojkam1@fel.cvut.cz>)\r
+ id 1Nzswi-0007cJ-Q0; Thu, 08 Apr 2010 16:43:04 +0200\r
+From: Michal Sojka <sojkam1@fel.cvut.cz>\r
+To: notmuch@notmuchmail.org\r
+Subject: [PATCH 3/4] Access messages through mail store interface\r
+Date: Thu, 8 Apr 2010 16:42:45 +0200\r
+Message-Id: <1270737766-29237-4-git-send-email-sojkam1@fel.cvut.cz>\r
+X-Mailer: git-send-email 1.7.0.2\r
+In-Reply-To: <1270737766-29237-1-git-send-email-sojkam1@fel.cvut.cz>\r
+References: <1270737766-29237-1-git-send-email-sojkam1@fel.cvut.cz>\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, 08 Apr 2010 14:43:12 -0000\r
+\r
+This patch modifies notmuch binary to access the messages through mail\r
+store interface, so that non-file based mail stores can also be\r
+implemented.\r
+\r
+The API of notmuch library was changed. Now,\r
+notmuch_message_get_filename() returns relative file name with respect\r
+to the database path. As a result, notmuch show also outputs relative\r
+paths so that MUAs need to be changed.\r
+\r
+Signed-off-by: Michal Sojka <sojkam1@fel.cvut.cz>\r
+---\r
+ lib/database.cc | 14 +++++++++++---\r
+ lib/index.cc | 8 ++++++--\r
+ lib/mailstore-files.c | 18 +++++++++++++++++-\r
+ lib/message-file.c | 8 ++++----\r
+ lib/message.cc | 33 +++++++++++++++++++++++++--------\r
+ lib/notmuch-private.h | 6 +++---\r
+ lib/notmuch.h | 16 ++++++++++++++--\r
+ lib/sha1.c | 6 +-----\r
+ notmuch-client.h | 2 +-\r
+ notmuch-reply.c | 10 +++++++++-\r
+ notmuch-show.c | 14 ++++++++++++--\r
+ show-message.c | 14 +-------------\r
+ 12 files changed, 104 insertions(+), 45 deletions(-)\r
+\r
+diff --git a/lib/database.cc b/lib/database.cc\r
+index 93c8d0f..bd64ed3 100644\r
+--- a/lib/database.cc\r
++++ b/lib/database.cc\r
+@@ -1374,6 +1374,7 @@ notmuch_database_add_message (notmuch_database_t *notmuch,\r
+ notmuch_message_t *message = NULL;\r
+ notmuch_status_t ret = NOTMUCH_STATUS_SUCCESS;\r
+ notmuch_private_status_t private_status;\r
++ const char *relative;\r
+ \r
+ const char *date, *header;\r
+ const char *from, *to, *subject;\r
+@@ -1386,7 +1387,8 @@ notmuch_database_add_message (notmuch_database_t *notmuch,\r
+ if (ret)\r
+ return ret;\r
+ \r
+- message_file = notmuch_message_file_open (filename);\r
++ relative = _notmuch_database_relative_path (notmuch, filename);\r
++ message_file = notmuch_message_file_open (notmuch->mailstore, relative);\r
+ if (message_file == NULL)\r
+ return NOTMUCH_STATUS_FILE_ERROR;\r
+ \r
+@@ -1438,9 +1440,15 @@ notmuch_database_add_message (notmuch_database_t *notmuch,\r
+ }\r
+ \r
+ if (message_id == NULL ) {\r
++ FILE *file;\r
++ char *sha1 = NULL;\r
+ /* No message-id at all, let's generate one by taking a\r
+ * hash over the file's contents. */\r
+- char *sha1 = notmuch_sha1_of_file (filename);\r
++ file = notmuch_mailstore_open_file (notmuch->mailstore, relative);\r
++ if (file) {\r
++ sha1 = notmuch_sha1_of_file (file);\r
++ fclose (file);\r
++ }\r
+ \r
+ /* If that failed too, something is really wrong. Give up. */\r
+ if (sha1 == NULL) {\r
+@@ -1483,7 +1491,7 @@ notmuch_database_add_message (notmuch_database_t *notmuch,\r
+ date = notmuch_message_file_get_header (message_file, "date");\r
+ _notmuch_message_set_date (message, date);\r
+ \r
+- _notmuch_message_index_file (message, filename);\r
++ _notmuch_message_index_file (message, relative);\r
+ } else {\r
+ ret = NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID;\r
+ }\r
+diff --git a/lib/index.cc b/lib/index.cc\r
+index cf93025..4d8c4dd 100644\r
+--- a/lib/index.cc\r
++++ b/lib/index.cc\r
+@@ -425,15 +425,19 @@ _notmuch_message_index_file (notmuch_message_t *message,\r
+ const char *from, *subject;\r
+ notmuch_status_t ret = NOTMUCH_STATUS_SUCCESS;\r
+ static int initialized = 0;\r
++ notmuch_mailstore_t *mailstore;\r
+ \r
+ if (! initialized) {\r
+ g_mime_init (0);\r
+ initialized = 1;\r
+ }\r
+ \r
+- file = fopen (filename, "r");\r
++ mailstore = notmuch_message_get_mailstore(message);\r
++ file = notmuch_mailstore_open_file (mailstore, filename);\r
+ if (! file) {\r
+- fprintf (stderr, "Error opening %s: %s\n", filename, strerror (errno));\r
++ fprintf (stderr, "Error opening %s: %s\n",\r
++ notmuch_message_get_filename (message),\r
++ strerror (errno));\r
+ ret = NOTMUCH_STATUS_FILE_ERROR;\r
+ goto DONE;\r
+ }\r
+diff --git a/lib/mailstore-files.c b/lib/mailstore-files.c\r
+index 8b5e1d5..f2cb8d7 100644\r
+--- a/lib/mailstore-files.c\r
++++ b/lib/mailstore-files.c\r
+@@ -602,11 +602,27 @@ index_new(notmuch_mailstore_t *mailstore, const char* path,\r
+ return ret;\r
+ }\r
+ \r
++static FILE *\r
++open_file(notmuch_mailstore_t *mailstore, const char *filename)\r
++{\r
++ const char *db_path;\r
++ char *abs_filename;\r
++ FILE *file;\r
++ \r
++ db_path = notmuch_database_get_path(mailstore->notmuch);\r
++ abs_filename = talloc_asprintf(NULL, "%s/%s", db_path, filename);\r
++ if (unlikely(abs_filename == NULL))\r
++ return NULL;\r
++ file = fopen (abs_filename, "r");\r
++ talloc_free(abs_filename);\r
++ return file;\r
++}\r
++\r
+ /* Original notmuch mail store */\r
+ struct _notmuch_mailstore mailstore_files = {\r
+ .type = "files",\r
+ .count_files = count_files,\r
+ .index_new = index_new,\r
+ .sync_tags = NULL, /* We cannot store tags in this mailstore. */\r
+- .open_file = NULL, /* Currently not implemented */\r
++ .open_file = open_file,\r
+ };\r
+diff --git a/lib/message-file.c b/lib/message-file.c\r
+index 0c152a3..13c9f4c 100644\r
+--- a/lib/message-file.c\r
++++ b/lib/message-file.c\r
+@@ -94,7 +94,7 @@ _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, const char *filename)\r
+ {\r
+ notmuch_message_file_t *message;\r
+ \r
+@@ -104,7 +104,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_file(mailstore, filename);\r
+ if (message->file == NULL)\r
+ goto FAIL;\r
+ \r
+@@ -126,9 +126,9 @@ _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, 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 c32ee7d..c7eff7c 100644\r
+--- a/lib/message.cc\r
++++ b/lib/message.cc\r
+@@ -247,6 +247,7 @@ static void\r
+ _notmuch_message_ensure_message_file (notmuch_message_t *message)\r
+ {\r
+ const char *filename;\r
++ notmuch_mailstore_t *mailstore;\r
+ \r
+ if (message->message_file)\r
+ return;\r
+@@ -255,7 +256,9 @@ _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
++ mailstore = notmuch_message_get_mailstore (message);\r
++\r
++ message->message_file = _notmuch_message_file_open_ctx (message, mailstore, filename);\r
+ }\r
+ \r
+ const char *\r
+@@ -429,7 +432,7 @@ notmuch_message_get_filename (notmuch_message_t *message)\r
+ int prefix_len = strlen (prefix);\r
+ Xapian::TermIterator i;\r
+ char *colon, *direntry = NULL;\r
+- const char *db_path, *directory, *basename;\r
++ const char *directory, *basename;\r
+ unsigned int directory_id;\r
+ void *local = talloc_new (message);\r
+ \r
+@@ -474,18 +477,16 @@ notmuch_message_get_filename (notmuch_message_t *message)\r
+ \r
+ *colon = '\0';\r
+ \r
+- db_path = notmuch_database_get_path (message->notmuch);\r
+-\r
+ directory = _notmuch_database_get_directory_path (local,\r
+ message->notmuch,\r
+ directory_id);\r
+ \r
+ if (strlen (directory))\r
+- message->filename = talloc_asprintf (message, "%s/%s/%s",\r
+- db_path, directory, basename);\r
+- else\r
+ message->filename = talloc_asprintf (message, "%s/%s",\r
+- db_path, basename);\r
++ directory, basename);\r
++ else\r
++ message->filename = talloc_asprintf (message, "%s",\r
++ basename);\r
+ talloc_free ((void *) directory);\r
+ \r
+ talloc_free (local);\r
+@@ -493,6 +494,22 @@ notmuch_message_get_filename (notmuch_message_t *message)\r
+ return message->filename;\r
+ }\r
+ \r
++FILE *\r
++notmuch_message_fopen (notmuch_message_t *message)\r
++{\r
++ const char *filename;\r
++ filename = notmuch_message_get_filename (message);\r
++ return notmuch_mailstore_open_file (message->notmuch->mailstore,\r
++ filename);\r
++}\r
++\r
++notmuch_mailstore_t *\r
++notmuch_message_get_mailstore (notmuch_message_t *message)\r
++{\r
++ return message->notmuch->mailstore;\r
++}\r
++\r
++\r
+ notmuch_bool_t\r
+ notmuch_message_get_flag (notmuch_message_t *message,\r
+ notmuch_message_flag_t flag)\r
+diff --git a/lib/notmuch-private.h b/lib/notmuch-private.h\r
+index d52d84d..bab2090 100644\r
+--- a/lib/notmuch-private.h\r
++++ b/lib/notmuch-private.h\r
+@@ -295,11 +295,11 @@ 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, 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, notmuch_mailstore_t *mailstore, const char *filename);\r
+ \r
+ /* Close a notmuch message previously opened with notmuch_message_open. */\r
+ void\r
+@@ -402,7 +402,7 @@ char *\r
+ notmuch_sha1_of_string (const char *str);\r
+ \r
+ char *\r
+-notmuch_sha1_of_file (const char *filename);\r
++notmuch_sha1_of_file (FILE *file);\r
+ \r
+ /* tags.c */\r
+ \r
+diff --git a/lib/notmuch.h b/lib/notmuch.h\r
+index 31e47a4..54de0bd 100644\r
+--- a/lib/notmuch.h\r
++++ b/lib/notmuch.h\r
+@@ -739,8 +739,8 @@ notmuch_message_get_replies (notmuch_message_t *message);\r
+ \r
+ /* Get a filename for the email corresponding to 'message'.\r
+ *\r
+- * The returned filename is an absolute filename, (the initial\r
+- * component will match notmuch_database_get_path() ).\r
++ * The returned filename is an relative filename of the message within\r
++ * the mail store.\r
+ *\r
+ * The returned string belongs to the message so should not be\r
+ * modified or freed by the caller (nor should it be referenced after\r
+@@ -754,6 +754,18 @@ notmuch_message_get_replies (notmuch_message_t *message);\r
+ const char *\r
+ notmuch_message_get_filename (notmuch_message_t *message);\r
+ \r
++/* Return file handle to read the content of the message.\r
++ *\r
++ * This is a helper function which determines message filename and\r
++ * calls notmuch_mailstore_open_file().\r
++ */\r
++FILE *\r
++notmuch_message_fopen (notmuch_message_t *message);\r
++\r
++/* Get a pointer to the mailstore where the message is stored */\r
++notmuch_mailstore_t *\r
++notmuch_message_get_mailstore (notmuch_message_t *message);\r
++\r
+ /* Message flags */\r
+ typedef enum _notmuch_message_flag {\r
+ NOTMUCH_MESSAGE_FLAG_MATCH,\r
+diff --git a/lib/sha1.c b/lib/sha1.c\r
+index cc48108..a8991b1 100644\r
+--- a/lib/sha1.c\r
++++ b/lib/sha1.c\r
+@@ -74,9 +74,8 @@ notmuch_sha1_of_string (const char *str)\r
+ * file not found, etc.), this function returns NULL.\r
+ */\r
+ char *\r
+-notmuch_sha1_of_file (const char *filename)\r
++notmuch_sha1_of_file (FILE *file)\r
+ {\r
+- FILE *file;\r
+ #define BLOCK_SIZE 4096\r
+ unsigned char block[BLOCK_SIZE];\r
+ size_t bytes_read;\r
+@@ -84,7 +83,6 @@ notmuch_sha1_of_file (const char *filename)\r
+ unsigned char digest[SHA1_DIGEST_SIZE];\r
+ char *result;\r
+ \r
+- file = fopen (filename, "r");\r
+ if (file == NULL)\r
+ return NULL;\r
+ \r
+@@ -108,8 +106,6 @@ notmuch_sha1_of_file (const char *filename)\r
+ \r
+ result = _hex_of_sha1_digest (digest);\r
+ \r
+- fclose (file);\r
+-\r
+ return result;\r
+ }\r
+ \r
+diff --git a/notmuch-client.h b/notmuch-client.h\r
+index d8c8df4..728e448 100644\r
+--- a/notmuch-client.h\r
++++ b/notmuch-client.h\r
+@@ -126,7 +126,7 @@ char *\r
+ query_string_from_args (void *ctx, int argc, char *argv[]);\r
+ \r
+ notmuch_status_t\r
+-show_message_body (const char *filename,\r
++show_message_body (FILE *file,\r
+ void (*show_part) (GMimeObject *part, int *part_count));\r
+ \r
+ notmuch_status_t\r
+diff --git a/notmuch-reply.c b/notmuch-reply.c\r
+index 1ec28cd..32d17ef 100644\r
+--- a/notmuch-reply.c\r
++++ b/notmuch-reply.c\r
+@@ -347,6 +347,7 @@ guess_from_received_header (notmuch_config_t *config, notmuch_message_t *message\r
+ static int\r
+ notmuch_reply_format_default(void *ctx, notmuch_config_t *config, notmuch_query_t *query)\r
+ {\r
++ FILE *file;\r
+ GMimeMessage *reply;\r
+ notmuch_messages_t *messages;\r
+ notmuch_message_t *message;\r
+@@ -415,7 +416,14 @@ notmuch_reply_format_default(void *ctx, notmuch_config_t *config, notmuch_query_\r
+ notmuch_message_get_header (message, "date"),\r
+ notmuch_message_get_header (message, "from"));\r
+ \r
+- show_message_body (notmuch_message_get_filename (message), reply_part);\r
++ file = notmuch_message_fopen (message);\r
++ if (file) {\r
++ show_message_body (file, reply_part);\r
++ fclose (file);\r
++ } else\r
++ fprintf (stderr, "Error opening %s: %s\n",\r
++ notmuch_message_get_filename (message),\r
++ strerror (errno));\r
+ \r
+ notmuch_message_destroy (message);\r
+ }\r
+diff --git a/notmuch-show.c b/notmuch-show.c\r
+index 6dca672..66fd773 100644\r
+--- a/notmuch-show.c\r
++++ b/notmuch-show.c\r
+@@ -339,6 +339,8 @@ format_part_json (GMimeObject *part, int *part_count)\r
+ static void\r
+ show_message (void *ctx, const show_format_t *format, notmuch_message_t *message, int indent)\r
+ {\r
++ FILE *file;\r
++\r
+ fputs (format->message_start, stdout);\r
+ if (format->message)\r
+ format->message(ctx, message, indent);\r
+@@ -349,8 +351,16 @@ show_message (void *ctx, const show_format_t *format, notmuch_message_t *message\r
+ fputs (format->header_end, stdout);\r
+ \r
+ fputs (format->body_start, stdout);\r
+- if (format->part)\r
+- show_message_body (notmuch_message_get_filename (message), format->part);\r
++ if (format->part) {\r
++ file = notmuch_message_fopen (message);\r
++ if (file) {\r
++ show_message_body (file, format->part);\r
++ fclose (file);\r
++ } else\r
++ fprintf (stderr, "Error opening %s: %s\n",\r
++ notmuch_message_get_filename (message),\r
++ strerror (errno));\r
++ }\r
+ fputs (format->body_end, stdout);\r
+ \r
+ fputs (format->message_end, stdout);\r
+diff --git a/show-message.c b/show-message.c\r
+index b1b61be..79911a7 100644\r
+--- a/show-message.c\r
++++ b/show-message.c\r
+@@ -60,23 +60,15 @@ show_message_part (GMimeObject *part, int *part_count,\r
+ }\r
+ \r
+ notmuch_status_t\r
+-show_message_body (const char *filename,\r
++show_message_body (FILE *file,\r
+ void (*show_part) (GMimeObject *part, int *part_count))\r
+ {\r
+ GMimeStream *stream = NULL;\r
+ GMimeParser *parser = NULL;\r
+ GMimeMessage *mime_message = NULL;\r
+ notmuch_status_t ret = NOTMUCH_STATUS_SUCCESS;\r
+- FILE *file = NULL;\r
+ int part_count = 0;\r
+ \r
+- file = fopen (filename, "r");\r
+- if (! file) {\r
+- fprintf (stderr, "Error opening %s: %s\n", filename, strerror (errno));\r
+- ret = NOTMUCH_STATUS_FILE_ERROR;\r
+- goto DONE;\r
+- }\r
+-\r
+ stream = g_mime_stream_file_new (file);\r
+ g_mime_stream_file_set_owner (GMIME_STREAM_FILE (stream), FALSE);\r
+ \r
+@@ -87,7 +79,6 @@ show_message_body (const char *filename,\r
+ show_message_part (g_mime_message_get_mime_part (mime_message),\r
+ &part_count, show_part);\r
+ \r
+- DONE:\r
+ if (mime_message)\r
+ g_object_unref (mime_message);\r
+ \r
+@@ -97,9 +88,6 @@ show_message_body (const char *filename,\r
+ if (stream)\r
+ g_object_unref (stream);\r
+ \r
+- if (file)\r
+- fclose (file);\r
+-\r
+ return ret;\r
+ }\r
+ \r
+-- \r
+1.7.0.2\r
+\r