Fix add_message and get_filename to strip/re-add the database path.
authorCarl Worth <cworth@cworth.org>
Wed, 28 Oct 2009 23:50:14 +0000 (16:50 -0700)
committerCarl Worth <cworth@cworth.org>
Wed, 28 Oct 2009 23:51:56 +0000 (16:51 -0700)
We now store only a relative path inside the database so the database
is not nicely relocatable.

database.cc
message.cc
notmuch-private.h
notmuch.c
notmuch.h

index d7cd26c7656d2fd6fb85464d8c1c582d96ee11af..3e00aa59754c0f69b610cf369441020a057dcb55 100644 (file)
@@ -487,6 +487,9 @@ notmuch_database_open (const char *path)
     notmuch = talloc (NULL, notmuch_database_t);
     notmuch->path = talloc_strdup (notmuch, path);
 
+    if (notmuch->path[strlen (notmuch->path) - 1] == '/')
+       notmuch->path[strlen (notmuch->path) - 1] = '\0';
+
     try {
        notmuch->xapian_db = new Xapian::WritableDatabase (xapian_path,
                                                           Xapian::DB_CREATE_OR_OPEN);
@@ -856,9 +859,10 @@ notmuch_database_add_message (notmuch_database_t *notmuch,
     notmuch_message_file_t *message_file;
     notmuch_message_t *message;
     notmuch_status_t ret = NOTMUCH_STATUS_SUCCESS;
+    notmuch_private_status_t private_status;
 
     const char *date, *header;
-    const char *from, *to, *subject, *old_filename;
+    const char *from, *to, *subject;
     char *message_id;
 
     if (message_ret)
@@ -932,21 +936,20 @@ notmuch_database_add_message (notmuch_database_t *notmuch,
        message = _notmuch_message_create_for_message_id (NULL,
                                                          notmuch,
                                                          message_id,
-                                                         &ret);
+                                                         &private_status);
 
        talloc_free (message_id);
 
        if (message == NULL)
            goto DONE;
 
-       /* Has a message previously been added with the same ID? */
-       old_filename = notmuch_message_get_filename (message);
-       if (old_filename && strlen (old_filename)) {
-           ret = NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID;
-           goto DONE;
-       } else {
+       /* Is this a newly created message object? */
+       if (private_status == NOTMUCH_PRIVATE_STATUS_NO_DOCUMENT_FOUND) {
            _notmuch_message_set_filename (message, filename);
            _notmuch_message_add_term (message, "type", "mail");
+       } else {
+           ret = NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID;
+           goto DONE;
        }
 
        ret = _notmuch_database_link_message (notmuch, message, message_file);
index 75e752c800221f4c99837bf2dcd1a3faec8611ba..169b20c193695c16744744233aaac041292e2dfb 100644 (file)
@@ -146,7 +146,8 @@ _notmuch_message_create (const void *talloc_owner,
  * If there is already a document with message ID 'message_id' in the
  * database, then the returned message can be used to query/modify the
  * document. Otherwise, a new document will be inserted into the
- * database before this function returns.
+ * database before this function returns, (and *status will be set
+ * to NOTMUCH_PRIVATE_STATUS_NO_DOCUMENT_FOUND).
  *
  * If an error occurs, this function will return NULL and *status
  * will be set as appropriate. (The status pointer argument must
@@ -156,15 +157,14 @@ notmuch_message_t *
 _notmuch_message_create_for_message_id (const void *talloc_owner,
                                        notmuch_database_t *notmuch,
                                        const char *message_id,
-                                       notmuch_status_t *status)
+                                       notmuch_private_status_t *status_ret)
 {
-    notmuch_private_status_t private_status;
     notmuch_message_t *message;
     Xapian::Document doc;
     unsigned int doc_id;
     char *term;
 
-    *status = NOTMUCH_STATUS_SUCCESS;
+    *status_ret = NOTMUCH_PRIVATE_STATUS_SUCCESS;
 
     message = notmuch_database_find_message (notmuch, message_id);
     if (message)
@@ -173,7 +173,7 @@ _notmuch_message_create_for_message_id (const void *talloc_owner,
     term = talloc_asprintf (NULL, "%s%s",
                            _find_prefix ("id"), message_id);
     if (term == NULL) {
-       *status = NOTMUCH_STATUS_OUT_OF_MEMORY;
+       *status_ret = NOTMUCH_PRIVATE_STATUS_OUT_OF_MEMORY;
        return NULL;
     }
 
@@ -185,15 +185,17 @@ _notmuch_message_create_for_message_id (const void *talloc_owner,
 
        doc_id = notmuch->xapian_db->add_document (doc);
     } catch (const Xapian::Error &error) {
-       *status = NOTMUCH_STATUS_XAPIAN_EXCEPTION;
+       *status_ret = NOTMUCH_PRIVATE_STATUS_XAPIAN_EXCEPTION;
        return NULL;
     }
 
     message = _notmuch_message_create (talloc_owner, notmuch,
-                                      doc_id, &private_status);
+                                      doc_id, status_ret);
 
-    *status = COERCE_STATUS (private_status,
-                            "Failed to find dcocument after inserting it.");
+    /* We want to inform the caller that we had to create a new
+     * document. */
+    if (*status_ret == NOTMUCH_PRIVATE_STATUS_SUCCESS)
+       *status_ret = NOTMUCH_PRIVATE_STATUS_NO_DOCUMENT_FOUND;
 
     return message;
 }
@@ -297,21 +299,49 @@ void
 _notmuch_message_set_filename (notmuch_message_t *message,
                               const char *filename)
 {
-    if (message->filename)
+    const char *s;
+    const char *db_path;
+    unsigned int db_path_len;
+
+    if (message->filename) {
        talloc_free (message->filename);
-    message->doc.set_data (filename);
+       message->filename = NULL;
+    }
+
+    if (filename == NULL)
+       INTERNAL_ERROR ("Message filename cannot be NULL.");
+
+    s = filename;
+
+    db_path = notmuch_database_get_path (message->notmuch);
+    db_path_len = strlen (db_path);
+
+    if (*s == '/' && strncmp (s, db_path, db_path_len) == 0
+       && strlen (s) > db_path_len)
+    {
+       s += db_path_len + 1;
+    }
+
+    message->doc.set_data (s);
 }
 
 const char *
 notmuch_message_get_filename (notmuch_message_t *message)
 {
     std::string filename_str;
+    const char *db_path;
 
     if (message->filename)
        return message->filename;
 
     filename_str = message->doc.get_data ();
-    message->filename = talloc_strdup (message, filename_str.c_str ());
+    db_path = notmuch_database_get_path (message->notmuch);
+
+    if (filename_str[0] != '/')
+       message->filename = talloc_asprintf (message, "%s/%s", db_path,
+                                            filename_str.c_str ());
+    else
+       message->filename = talloc_strdup (message, filename_str.c_str ());
 
     return message->filename;
 }
index 440860babc569d653f6b8d00dfef95071db0406f..da36c30098ed0fce9f8b2f9017ff1e81dd165d81 100644 (file)
@@ -172,7 +172,7 @@ notmuch_message_t *
 _notmuch_message_create_for_message_id (const void *talloc_owner,
                                        notmuch_database_t *notmuch,
                                        const char *message_id,
-                                       notmuch_status_t *status);
+                                       notmuch_private_status_t *status);
 
 const char *
 _notmuch_message_get_subject (notmuch_message_t *message);
index 5a0ca5c946c69e12adadca235969463e98983f91..757f09d797b6df0f51bb6b6ef2cc51315884f93e 100644 (file)
--- a/notmuch.c
+++ b/notmuch.c
@@ -531,6 +531,30 @@ setup_command (unused (int argc), unused (char *argv[]))
        free (default_path);
     }
 
+    /* Coerce th directory into an absolute directory name. */
+    if (*mail_directory != '/') {
+       char *cwd, *absolute_mail_directory;
+
+       cwd = getcwd (NULL, 0);
+       if (cwd == NULL) {
+           fprintf (stderr, "Out of memory.\n");
+           exit (1);
+       }
+
+       if (asprintf (&absolute_mail_directory, "%s/%s",
+                     cwd, mail_directory) < 0)
+       {
+           fprintf (stderr, "Out of memory.\n");
+           exit (1);
+       }
+
+       free (cwd);
+       free (mail_directory);
+       mail_directory = absolute_mail_directory;
+
+       printf ("Abs: %s\n", mail_directory);
+    }
+
     notmuch = notmuch_database_create (mail_directory);
     if (notmuch == NULL) {
        fprintf (stderr, "Failed to create new notmuch database at %s\n",
index f4e59ab2ca47f47df30c81fba7323f3605b0033f..165fe85224e0c7b9dd48e176541fda7f74a4cbf7 100644 (file)
--- a/notmuch.h
+++ b/notmuch.h
@@ -246,11 +246,14 @@ notmuch_database_get_timestamp (notmuch_database_t *database,
 /* Add a new message to the given notmuch database.
  *
  * Here,'filename' should be a path relative to the the path of
- * 'database' (see notmuch_database_get_path). The file should be a
- * single mail message (not a multi-message mbox) that is expected to
- * remain at its current location, (since the notmuch database will
- * reference the filename, and will not copy the entire contents of
- * the file.
+ * 'database' (see notmuch_database_get_path), or else should be an
+ * absolute filename with initial components that match the path of
+ * 'database'.
+ *
+ * The file should be a single mail message (not a multi-message mbox)
+ * that is expected to remain at its current location, (since the
+ * notmuch database will reference the filename, and will not copy the
+ * entire contents of the file.
  *
  * If 'message' is not NULL, then, on successful return '*message'
  * will be initialized to a message object that can be used for things
@@ -605,8 +608,9 @@ notmuch_message_get_thread_id (notmuch_message_t *message);
 
 /* Get the filename for the email corresponding to 'message'.
  *
- * The returned filename is relative to the base of the database from
- * which 'message' was obtained. See notmuch_database_get_path() .
+ * The returned filename is an absolute filename, (the initial
+ * component will match notmuch_database_get_path() ).
+ *
  * The returned string belongs to the message so should not be
  * modified or freed by the caller (nor should it be referenced after
  * the message is destroyed). */