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;
{
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)
{
notmuch_tags_t *
notmuch_message_get_tags (notmuch_message_t *message)
{
- const char *prefix = _find_prefix ("tag");
Xapian::TermIterator i, end;
- notmuch_tags_t *tags;
- std::string tag;
-
- /* Currently this iteration is written with the assumption that
- * "tag" has a single-character prefix. */
- assert (strlen (prefix) == 1);
-
- tags = _notmuch_tags_create (message);
- if (unlikely (tags == NULL))
- return NULL;
-
- i = message->doc.termlist_begin ();
- end = message->doc.termlist_end ();
-
- i.skip_to (prefix);
-
- while (1) {
- tag = *i;
-
- if (tag.empty () || tag[0] != *prefix)
- break;
-
- _notmuch_tags_add_tag (tags, tag.c_str () + 1);
-
- i++;
- }
-
- _notmuch_tags_prepare_iterator (tags);
-
- return tags;
+ i = message->doc.termlist_begin();
+ end = message->doc.termlist_end();
+ return _notmuch_convert_tags(message, i, end);
}
void
/* 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);
}