]> git.notmuchmail.org Git - notmuch/blobdiff - lib/message.cc
database: Store mail filename as a new 'direntry' term, not as 'data'.
[notmuch] / lib / message.cc
index a410394d3d5ac8c2d7772a6b3d1d65762c24ed85..3f5334239e0839d5d0bcae3595e4e28b7f1b5280 100644 (file)
@@ -37,6 +37,7 @@ struct _notmuch_message {
     char *filename;
     notmuch_message_file_t *message_file;
     notmuch_message_list_t *replies;
+    unsigned long flags;
 
     Xapian::Document doc;
 };
@@ -108,6 +109,7 @@ _notmuch_message_create (const void *talloc_owner,
     message->doc_id = doc_id;
 
     message->frozen = 0;
+    message->flags = 0;
 
     /* Each of these will be lazily created as needed. */
     message->message_id = NULL;
@@ -316,9 +318,9 @@ _notmuch_message_get_in_reply_to (notmuch_message_t *message)
     in_reply_to = *i;
 
     if (i != message->doc.termlist_end () &&
-       strncmp ((*i).c_str (), prefix, prefix_len))
+       strncmp ((*i).c_str (), prefix, prefix_len) == 0)
     {
-       INTERNAL_ERROR ("Message %s has duplicate In-Reply-To IDs: %s and %s\n"
+       INTERNAL_ERROR ("Message %s has duplicate In-Reply-To IDs: %s and %s\n",
                        notmuch_message_get_message_id (message),
                        message->in_reply_to,
                        (*i).c_str () + prefix_len);
@@ -390,13 +392,15 @@ notmuch_message_get_replies (notmuch_message_t *message)
  *
  * This change will not be reflected in the database until the next
  * call to _notmuch_message_set_sync. */
-void
+notmuch_status_t
 _notmuch_message_set_filename (notmuch_message_t *message,
                               const char *filename)
 {
-    const char *s;
-    const char *db_path;
-    unsigned int db_path_len;
+    const char *relative, *directory, *basename;
+    char *term;
+    Xapian::docid directory_id;
+    notmuch_status_t status;
+    void *local = talloc_new (message);
 
     if (message->filename) {
        talloc_free (message->filename);
@@ -406,45 +410,101 @@ _notmuch_message_set_filename (notmuch_message_t *message,
     if (filename == NULL)
        INTERNAL_ERROR ("Message filename cannot be NULL.");
 
-    s = filename;
+    relative = _notmuch_database_relative_path (message->notmuch, filename);
 
-    db_path = notmuch_database_get_path (message->notmuch);
-    db_path_len = strlen (db_path);
+    status = _notmuch_database_split_path (local, relative,
+                                          &directory, &basename);
+    if (status)
+       return status;
 
-    if (*s == '/' && strlen (s) > db_path_len
-       && strncmp (s, db_path, db_path_len) == 0)
-    {
-       s += db_path_len;
-       while (*s == '/') s++;
+    status = _notmuch_database_find_directory_id (message->notmuch, directory,
+                                                 &directory_id);
+    if (status)
+       return status;
 
-       if (!*s)
-               INTERNAL_ERROR ("Message filename was same as db prefix.");
-    }
+    term = talloc_asprintf (local, "%s%u:%s",
+                           _find_prefix ("direntry"), directory_id, basename);
+
+    message->doc.add_term (term);
 
-    message->doc.set_data (s);
+    talloc_free (local);
+
+    return NOTMUCH_STATUS_SUCCESS;
 }
 
 const char *
 notmuch_message_get_filename (notmuch_message_t *message)
 {
-    std::string filename_str;
-    const char *db_path;
+    const char *prefix = _find_prefix ("direntry");
+    int prefix_len = strlen (prefix);
+    Xapian::TermIterator i;
+    char *direntry, *colon;
+    const char *db_path, *directory, *basename;
+    unsigned int directory_id;
+    void *local = talloc_new (message);
 
     if (message->filename)
        return message->filename;
 
-    filename_str = message->doc.get_data ();
+    i = message->doc.termlist_begin ();
+    i.skip_to (prefix);
+
+    if (i != message->doc.termlist_end ())
+       direntry = talloc_strdup (local, (*i).c_str ());
+
+    if (i == message->doc.termlist_end () ||
+       strncmp (direntry, prefix, prefix_len))
+    {
+       INTERNAL_ERROR ("message with no filename");
+    }
+
+    direntry += prefix_len;
+
+    directory_id = strtol (direntry, &colon, 10);
+
+    if (colon == NULL || *colon != ':')
+       INTERNAL_ERROR ("malformed direntry");
+
+    basename = colon + 1;
+
+    *colon = '\0';
+
     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 ());
+    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_strdup (message, filename_str.c_str ());
+       message->filename = talloc_asprintf (message, "%s/%s",
+                                            db_path, basename);
+    talloc_free ((void *) directory);
+
+    talloc_free (local);
 
     return message->filename;
 }
 
+notmuch_bool_t
+notmuch_message_get_flag (notmuch_message_t *message,
+                         notmuch_message_flag_t flag)
+{
+    return message->flags & (1 << flag);
+}
+
+void
+notmuch_message_set_flag (notmuch_message_t *message,
+                         notmuch_message_flag_t flag, notmuch_bool_t enable)
+{
+    if (enable)
+       message->flags |= (1 << flag);
+    else
+       message->flags &= ~(1 << flag);
+}
+
 time_t
 notmuch_message_get_date (notmuch_message_t *message)
 {