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 <sojkam1 at fel.cvut.cz>
---
 lib/database.cc       |   14 +++++++++++---
 lib/index.cc          |    8 ++++++--
 lib/mailstore-files.c |   18 +++++++++++++++++-
 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(+), 45 deletions(-)

diff --git a/lib/database.cc b/lib/database.cc
index 93c8d0f..bd64ed3 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) {
@@ -1483,7 +1491,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 8b5e1d5..f2cb8d7 100644
--- a/lib/mailstore-files.c
+++ b/lib/mailstore-files.c
@@ -602,11 +602,27 @@ index_new(notmuch_mailstore_t *mailstore, const char* 
path,
     return ret;
 }

+static FILE *
+open_file(notmuch_mailstore_t *mailstore, const char *filename)
+{
+    const char *db_path;
+    char *abs_filename;
+    FILE *file;
+    
+    db_path = notmuch_database_get_path(mailstore->notmuch);
+    abs_filename = talloc_asprintf(NULL, "%s/%s", db_path, filename);
+    if (unlikely(abs_filename == NULL))
+       return NULL;
+    file = fopen (abs_filename, "r");
+    talloc_free(abs_filename);
+    return file;
+}
+
 /* Original notmuch mail store */
 struct _notmuch_mailstore mailstore_files = {
     .type = "files",
     .count_files = count_files,
     .index_new = index_new,
     .sync_tags = NULL,         /* We cannot store tags in this mailstore. */
-    .open_file = NULL,         /* Currently not implemented */
+    .open_file = open_file,
 };
diff --git a/lib/message-file.c b/lib/message-file.c
index 0c152a3..13c9f4c 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 c32ee7d..c7eff7c 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 d52d84d..bab2090 100644
--- a/lib/notmuch-private.h
+++ b/lib/notmuch-private.h
@@ -295,11 +295,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
@@ -402,7 +402,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 31e47a4..54de0bd 100644
--- a/lib/notmuch.h
+++ b/lib/notmuch.h
@@ -739,8 +739,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
@@ -754,6 +754,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 d8c8df4..728e448 100644
--- a/notmuch-client.h
+++ b/notmuch-client.h
@@ -126,7 +126,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));

 notmuch_status_t
diff --git a/notmuch-reply.c b/notmuch-reply.c
index 1ec28cd..32d17ef 100644
--- a/notmuch-reply.c
+++ b/notmuch-reply.c
@@ -347,6 +347,7 @@ guess_from_received_header (notmuch_config_t *config, 
notmuch_message_t *message
 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;
@@ -415,7 +416,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 6dca672..66fd773 100644
--- a/notmuch-show.c
+++ b/notmuch-show.c
@@ -339,6 +339,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);
@@ -349,8 +351,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 b1b61be..79911a7 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,9 +88,6 @@ show_message_body (const char *filename,
     if (stream)
        g_object_unref (stream);

-    if (file)
-       fclose (file);
-
     return ret;
 }

-- 
1.7.0.2

Reply via email to