]> git.notmuchmail.org Git - notmuch/blobdiff - lib/message.cc
lib: Implement versioning in the database and provide upgrade function.
[notmuch] / lib / message.cc
index 0fc54668cb9a362454551d8880bade40b7c6583e..baeaa46972867d10a1cc5cde801fac03c0817df1 100644 (file)
@@ -174,11 +174,6 @@ _notmuch_message_create_for_message_id (notmuch_database_t *notmuch,
     unsigned int doc_id;
     char *term;
 
-    if (notmuch->mode == NOTMUCH_DATABASE_MODE_READ_ONLY) {
-       *status_ret = NOTMUCH_PRIVATE_STATUS_READONLY_DATABASE;
-       return NULL;
-    }
-
     *status_ret = NOTMUCH_PRIVATE_STATUS_SUCCESS;
 
     message = notmuch_database_find_message (notmuch, message_id);
@@ -192,6 +187,9 @@ _notmuch_message_create_for_message_id (notmuch_database_t *notmuch,
        return NULL;
     }
 
+    if (notmuch->mode == NOTMUCH_DATABASE_MODE_READ_ONLY)
+       INTERNAL_ERROR ("Failure to ensure database is writable.");
+
     db = static_cast<Xapian::WritableDatabase *> (notmuch->xapian_db);
     try {
        doc.add_term (term);
@@ -418,6 +416,24 @@ _notmuch_message_add_filename (notmuch_message_t *message,
     return NOTMUCH_STATUS_SUCCESS;
 }
 
+/* Move the filename from the data field (as it was in database format
+ * version 0) to a file-direntry term instead (as in database format
+ * version 1).
+ */
+void
+_notmuch_message_upgrade_filename_storage (notmuch_message_t *message)
+{
+    char *filename;
+
+    filename = talloc_strdup (message, message->doc.get_data ().c_str ());
+    if (filename && *filename != '\0') {
+       _notmuch_message_add_filename (message, filename);
+       message->doc.set_data ("");
+       _notmuch_message_sync (message);
+    }
+    talloc_free (filename);
+}
+
 const char *
 notmuch_message_get_filename (notmuch_message_t *message)
 {
@@ -443,7 +459,10 @@ notmuch_message_get_filename (notmuch_message_t *message)
     {
        /* A message document created by an old version of notmuch
         * (prior to rename support) will have the filename in the
-        * data of the document rather than as a file-direntry term. */
+        * data of the document rather than as a file-direntry term.
+        *
+        * It would be nice to do the upgrade of the document directly
+        * here, but the database is likely open in read-only mode. */
        const char *data;
 
        data = message->doc.get_data ().c_str ();
@@ -706,7 +725,12 @@ _notmuch_message_remove_term (notmuch_message_t *message,
 notmuch_status_t
 notmuch_message_add_tag (notmuch_message_t *message, const char *tag)
 {
-    notmuch_private_status_t status;
+    notmuch_private_status_t private_status;
+    notmuch_status_t status;
+
+    status = _notmuch_database_ensure_writable (message->notmuch);
+    if (status)
+       return status;
 
     if (tag == NULL)
        return NOTMUCH_STATUS_NULL_POINTER;
@@ -714,10 +738,10 @@ notmuch_message_add_tag (notmuch_message_t *message, const char *tag)
     if (strlen (tag) > NOTMUCH_TAG_MAX)
        return NOTMUCH_STATUS_TAG_TOO_LONG;
 
-    status = _notmuch_message_add_term (message, "tag", tag);
-    if (status) {
+    private_status = _notmuch_message_add_term (message, "tag", tag);
+    if (private_status) {
        INTERNAL_ERROR ("_notmuch_message_add_term return unexpected value: %d\n",
-                       status);
+                       private_status);
     }
 
     if (! message->frozen)
@@ -729,7 +753,12 @@ notmuch_message_add_tag (notmuch_message_t *message, const char *tag)
 notmuch_status_t
 notmuch_message_remove_tag (notmuch_message_t *message, const char *tag)
 {
-    notmuch_private_status_t status;
+    notmuch_private_status_t private_status;
+    notmuch_status_t status;
+
+    status = _notmuch_database_ensure_writable (message->notmuch);
+    if (status)
+       return status;
 
     if (tag == NULL)
        return NOTMUCH_STATUS_NULL_POINTER;
@@ -737,10 +766,10 @@ notmuch_message_remove_tag (notmuch_message_t *message, const char *tag)
     if (strlen (tag) > NOTMUCH_TAG_MAX)
        return NOTMUCH_STATUS_TAG_TOO_LONG;
 
-    status = _notmuch_message_remove_term (message, "tag", tag);
-    if (status) {
+    private_status = _notmuch_message_remove_term (message, "tag", tag);
+    if (private_status) {
        INTERNAL_ERROR ("_notmuch_message_remove_term return unexpected value: %d\n",
-                       status);
+                       private_status);
     }
 
     if (! message->frozen)
@@ -749,39 +778,60 @@ notmuch_message_remove_tag (notmuch_message_t *message, const char *tag)
     return NOTMUCH_STATUS_SUCCESS;
 }
 
-void
+notmuch_status_t
 notmuch_message_remove_all_tags (notmuch_message_t *message)
 {
-    notmuch_private_status_t status;
+    notmuch_private_status_t private_status;
+    notmuch_status_t status;
     notmuch_tags_t *tags;
     const char *tag;
 
+    status = _notmuch_database_ensure_writable (message->notmuch);
+    if (status)
+       return status;
+
     for (tags = notmuch_message_get_tags (message);
         notmuch_tags_has_more (tags);
         notmuch_tags_advance (tags))
     {
        tag = notmuch_tags_get (tags);
 
-       status = _notmuch_message_remove_term (message, "tag", tag);
-       if (status) {
+       private_status = _notmuch_message_remove_term (message, "tag", tag);
+       if (private_status) {
            INTERNAL_ERROR ("_notmuch_message_remove_term return unexpected value: %d\n",
-                           status);
+                           private_status);
        }
     }
 
     if (! message->frozen)
        _notmuch_message_sync (message);
+
+    return NOTMUCH_STATUS_SUCCESS;
 }
 
-void
+notmuch_status_t
 notmuch_message_freeze (notmuch_message_t *message)
 {
+    notmuch_status_t status;
+
+    status = _notmuch_database_ensure_writable (message->notmuch);
+    if (status)
+       return status;
+
     message->frozen++;
+
+    return NOTMUCH_STATUS_SUCCESS;
 }
 
 notmuch_status_t
 notmuch_message_thaw (notmuch_message_t *message)
 {
+    notmuch_status_t status;
+
+    status = _notmuch_database_ensure_writable (message->notmuch);
+    if (status)
+       return status;
+
     if (message->frozen > 0) {
        message->frozen--;
        if (message->frozen == 0)