char *filename;
notmuch_message_file_t *message_file;
notmuch_message_list_t *replies;
+ unsigned long flags;
Xapian::Document doc;
};
message->doc_id = doc_id;
message->frozen = 0;
+ message->flags = 0;
/* Each of these will be lazily created as needed. */
message->message_id = NULL;
}
/* Create a new notmuch_message_t object for a specific message ID,
- * (which may or may not already exist in the databas).
+ * (which may or may not already exist in the database).
*
* The 'notmuch' database will be the talloc owner of the returned
* message.
{
notmuch_message_t *message;
Xapian::Document doc;
+ Xapian::WritableDatabase *db;
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);
return NULL;
}
+ db = static_cast<Xapian::WritableDatabase *> (notmuch->xapian_db);
try {
doc.add_term (term);
talloc_free (term);
doc.add_value (NOTMUCH_VALUE_MESSAGE_ID, message_id);
- doc_id = notmuch->xapian_db->add_document (doc);
+ doc_id = db->add_document (doc);
} catch (const Xapian::Error &error) {
+ fprintf (stderr, "A Xapian exception occurred creating message: %s\n",
+ error.get_msg().c_str());
+ notmuch->exception_reported = TRUE;
*status_ret = NOTMUCH_PRIVATE_STATUS_XAPIAN_EXCEPTION;
return NULL;
}
i = message->doc.termlist_begin ();
i.skip_to (prefix);
- in_reply_to = *i;
+ if (i != message->doc.termlist_end ())
+ in_reply_to = *i;
/* It's perfectly valid for a message to have no In-Reply-To
* header. For these cases, we return an empty string. */
return message->thread_id;
i = message->doc.termlist_begin ();
-
i.skip_to (prefix);
- id = *i;
+ if (i != message->doc.termlist_end ())
+ id = *i;
if (i == message->doc.termlist_end () || id[0] != *prefix)
INTERNAL_ERROR ("Message with document ID of %d has no thread ID.\n",
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)
+ if (*s == '/' && strlen (s) > db_path_len
+ && strncmp (s, db_path, db_path_len) == 0)
{
- s += db_path_len + 1;
+ s += db_path_len;
+ while (*s == '/') s++;
+
+ if (!*s)
+ INTERNAL_ERROR ("Message filename was same as db prefix.");
}
message->doc.set_data (s);
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)
{
i.skip_to (prefix);
- while (1) {
+ while (i != end) {
tag = *i;
if (tag.empty () || tag[0] != *prefix)
/* GMime really doesn't want to see a NULL date, so protect its
* sensibilities. */
- if (date == NULL)
+ if (date == NULL || *date == '\0')
time_value = 0;
else
time_value = g_mime_utils_header_decode_date (date, NULL);
void
_notmuch_message_sync (notmuch_message_t *message)
{
- Xapian::WritableDatabase *db = message->notmuch->xapian_db;
+ Xapian::WritableDatabase *db;
+ if (message->notmuch->mode == NOTMUCH_DATABASE_MODE_READ_ONLY)
+ return;
+
+ db = static_cast <Xapian::WritableDatabase *> (message->notmuch->xapian_db);
db->replace_document (message->doc_id, message->doc);
}
+/* Ensure that 'message' is not holding any file object open. Future
+ * calls to various functions will still automatically open the
+ * message file as needed.
+ */
+void
+_notmuch_message_close (notmuch_message_t *message)
+{
+ if (message->message_file) {
+ notmuch_message_file_close (message->message_file);
+ message->message_file = NULL;
+ }
+}
+
/* Add a name:value term to 'message', (the actual term will be
* encoded by prefixing the value with a short prefix). See
* NORMAL_PREFIX and BOOLEAN_PREFIX arrays for the mapping of term