aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDavid Bremner <david@tethera.net>2020-12-13 10:38:31 -0400
committerDavid Bremner <david@tethera.net>2020-12-13 10:38:31 -0400
commit7a9c97e8a57f2662b9069dae01b6e5cb2f650563 (patch)
tree2b7bfbf5b3848866444e61f7069ccc755301f844 /lib
parentb7ca3c23d17d247bda37645c7f861b3c0d04bf25 (diff)
parent900ee94b0f4f48ee536bd2e9bd6bb2dfc661d615 (diff)
Merge tag 'debian/0.31.2-3' into debian/buster-backports
notmuch release 0.31.2-3 for unstable (sid) [dgit] [dgit distro=debian no-split --quilt=linear]
Diffstat (limited to 'lib')
-rw-r--r--lib/Makefile.local2
-rw-r--r--lib/add-message.cc41
-rw-r--r--lib/built-with.c4
-rw-r--r--lib/config.cc16
-rw-r--r--lib/database-private.h48
-rw-r--r--lib/database.cc367
-rw-r--r--lib/directory.cc83
-rw-r--r--lib/index.cc230
-rw-r--r--lib/indexopts.c25
-rw-r--r--lib/message-file.c37
-rw-r--r--lib/message-id.c4
-rw-r--r--lib/message-property.cc3
-rw-r--r--lib/message.cc387
-rw-r--r--lib/messages.c4
-rw-r--r--lib/notmuch-private.h74
-rw-r--r--lib/notmuch.h137
-rw-r--r--lib/parse-time-vrp.cc73
-rw-r--r--lib/parse-time-vrp.h17
-rw-r--r--lib/query-fp.cc3
-rw-r--r--lib/query-fp.h13
-rw-r--r--lib/query.cc66
-rw-r--r--lib/regexp-fields.cc35
-rw-r--r--lib/regexp-fields.h18
-rw-r--r--lib/sha1.c1
-rw-r--r--lib/string-list.c6
-rw-r--r--lib/thread-fp.cc3
-rw-r--r--lib/thread-fp.h13
-rw-r--r--lib/thread.cc126
28 files changed, 1068 insertions, 768 deletions
diff --git a/lib/Makefile.local b/lib/Makefile.local
index 5dc057c0..a6400126 100644
--- a/lib/Makefile.local
+++ b/lib/Makefile.local
@@ -1,4 +1,4 @@
-# -*- makefile -*-
+# -*- makefile-gmake -*-
dir := lib
diff --git a/lib/add-message.cc b/lib/add-message.cc
index da37032c..485debad 100644
--- a/lib/add-message.cc
+++ b/lib/add-message.cc
@@ -34,7 +34,7 @@ parse_references (void *ctx,
* reference to the database. We should avoid making a message
* its own parent, thus the above check.
*/
- return talloc_strdup(ctx, last_ref);
+ return talloc_strdup (ctx, last_ref);
}
static const char *
@@ -43,15 +43,12 @@ _notmuch_database_generate_thread_id (notmuch_database_t *notmuch)
/* 16 bytes (+ terminator) for hexadecimal representation of
* a 64-bit integer. */
static char thread_id[17];
- Xapian::WritableDatabase *db;
-
- db = static_cast <Xapian::WritableDatabase *> (notmuch->xapian_db);
notmuch->last_thread_id++;
sprintf (thread_id, "%016" PRIx64, notmuch->last_thread_id);
- db->set_metadata ("last_thread_id", thread_id);
+ notmuch->writable_xapian_db->set_metadata ("last_thread_id", thread_id);
return thread_id;
}
@@ -161,16 +158,16 @@ _resolve_message_id_to_thread_id_old (notmuch_database_t *notmuch,
* can return the thread ID stored in the metadata. Otherwise, we
* generate a new thread ID and store it there.
*/
- db = static_cast <Xapian::WritableDatabase *> (notmuch->xapian_db);
+ db = notmuch->writable_xapian_db;
metadata_key = _get_metadata_thread_id_key (ctx, message_id);
thread_id_string = notmuch->xapian_db->get_metadata (metadata_key);
- if (thread_id_string.empty()) {
+ if (thread_id_string.empty ()) {
*thread_id_ret = talloc_strdup (ctx,
_notmuch_database_generate_thread_id (notmuch));
db->set_metadata (metadata_key, *thread_id_ret);
} else {
- *thread_id_ret = talloc_strdup (ctx, thread_id_string.c_str());
+ *thread_id_ret = talloc_strdup (ctx, thread_id_string.c_str ());
}
talloc_free (metadata_key);
@@ -190,7 +187,7 @@ _merge_threads (notmuch_database_t *notmuch,
_notmuch_database_find_doc_ids (notmuch, "thread", loser_thread_id, &loser, &loser_end);
- for ( ; loser != loser_end; loser++) {
+ for (; loser != loser_end; loser++) {
message = _notmuch_message_create (notmuch, notmuch,
*loser, &private_status);
if (message == NULL) {
@@ -264,7 +261,7 @@ _notmuch_database_link_message_to_parents (notmuch_database_t *notmuch,
last_ref_message_id);
} else if (in_reply_to_message_id) {
_notmuch_message_add_term (message, "replyto",
- in_reply_to_message_id);
+ in_reply_to_message_id);
}
keys = g_hash_table_get_keys (parents);
@@ -317,7 +314,7 @@ _notmuch_database_link_message_to_children (notmuch_database_t *notmuch,
_notmuch_database_find_doc_ids (notmuch, "reference", message_id, &child, &children_end);
- for ( ; child != children_end; child++) {
+ for (; child != children_end; child++) {
child_message = _notmuch_message_create (message, notmuch,
*child, &private_status);
@@ -370,13 +367,9 @@ _consume_metadata_thread_id (void *ctx, notmuch_database_t *notmuch,
if (stored_id.empty ()) {
return NULL;
} else {
- Xapian::WritableDatabase *db;
-
- db = static_cast <Xapian::WritableDatabase *> (notmuch->xapian_db);
-
/* Clear the metadata for this message ID. We don't need it
* anymore. */
- db->set_metadata (metadata_key, "");
+ notmuch->writable_xapian_db->set_metadata (metadata_key, "");
return talloc_strdup (ctx, stored_id.c_str ());
}
@@ -461,7 +454,7 @@ _notmuch_database_link_message (notmuch_database_t *notmuch,
_notmuch_message_add_term (message, "thread", thread_id);
}
- DONE:
+ DONE:
talloc_free (local);
return status;
@@ -477,7 +470,7 @@ notmuch_database_index_file (notmuch_database_t *notmuch,
notmuch_message_t *message = NULL;
notmuch_status_t ret = NOTMUCH_STATUS_SUCCESS, ret2;
notmuch_private_status_t private_status;
- bool is_ghost = false, is_new = false;
+ notmuch_bool_t is_ghost = false, is_new = false;
notmuch_indexopts_t *def_indexopts = NULL;
const char *date;
@@ -525,7 +518,9 @@ notmuch_database_index_file (notmuch_database_t *notmuch,
is_new = true;
break;
case NOTMUCH_PRIVATE_STATUS_SUCCESS:
- is_ghost = notmuch_message_get_flag (message, NOTMUCH_MESSAGE_FLAG_GHOST);
+ ret = notmuch_message_get_flag_st (message, NOTMUCH_MESSAGE_FLAG_GHOST, &is_ghost);
+ if (ret)
+ goto DONE;
is_new = false;
break;
default:
@@ -544,14 +539,14 @@ notmuch_database_index_file (notmuch_database_t *notmuch,
}
ret = _notmuch_database_link_message (notmuch, message,
- message_file, is_ghost);
+ message_file, is_ghost);
if (ret)
goto DONE;
if (is_new || is_ghost)
_notmuch_message_set_header_values (message, date, from, subject);
- if (!indexopts) {
+ if (! indexopts) {
def_indexopts = notmuch_database_get_default_indexopts (notmuch);
indexopts = def_indexopts;
}
@@ -560,13 +555,13 @@ notmuch_database_index_file (notmuch_database_t *notmuch,
if (ret)
goto DONE;
- if (! is_new && !is_ghost)
+ if (! is_new && ! is_ghost)
ret = NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID;
_notmuch_message_sync (message);
} catch (const Xapian::Error &error) {
_notmuch_database_log (notmuch, "A Xapian exception occurred adding message: %s.\n",
- error.get_msg().c_str());
+ error.get_msg ().c_str ());
notmuch->exception_reported = true;
ret = NOTMUCH_STATUS_XAPIAN_EXCEPTION;
goto DONE;
diff --git a/lib/built-with.c b/lib/built-with.c
index 320be6c5..0c70010b 100644
--- a/lib/built-with.c
+++ b/lib/built-with.c
@@ -25,9 +25,9 @@ notmuch_bool_t
notmuch_built_with (const char *name)
{
if (STRNCMP_LITERAL (name, "compact") == 0) {
- return HAVE_XAPIAN_COMPACT;
+ return true;
} else if (STRNCMP_LITERAL (name, "field_processor") == 0) {
- return HAVE_XAPIAN_FIELD_PROCESSOR;
+ return true;
} else if (STRNCMP_LITERAL (name, "retry_lock") == 0) {
return HAVE_XAPIAN_DB_RETRY_LOCK;
} else if (STRNCMP_LITERAL (name, "session_key") == 0) {
diff --git a/lib/config.cc b/lib/config.cc
index a8bcdf83..efab01e4 100644
--- a/lib/config.cc
+++ b/lib/config.cc
@@ -45,22 +45,20 @@ notmuch_database_set_config (notmuch_database_t *notmuch,
const char *value)
{
notmuch_status_t status;
- Xapian::WritableDatabase *db;
status = _notmuch_database_ensure_writable (notmuch);
if (status)
return status;
try {
- db = static_cast <Xapian::WritableDatabase *> (notmuch->xapian_db);
- db->set_metadata (CONFIG_PREFIX + key, value);
+ notmuch->writable_xapian_db->set_metadata (CONFIG_PREFIX + key, value);
} catch (const Xapian::Error &error) {
status = NOTMUCH_STATUS_XAPIAN_EXCEPTION;
notmuch->exception_reported = true;
_notmuch_database_log (notmuch, "Error: A Xapian exception occurred setting metadata: %s\n",
- error.get_msg().c_str());
+ error.get_msg ().c_str ());
}
- return NOTMUCH_STATUS_SUCCESS;
+ return status;
}
static notmuch_status_t
@@ -76,7 +74,7 @@ _metadata_value (notmuch_database_t *notmuch,
status = NOTMUCH_STATUS_XAPIAN_EXCEPTION;
notmuch->exception_reported = true;
_notmuch_database_log (notmuch, "Error: A Xapian exception occurred getting metadata: %s\n",
- error.get_msg().c_str());
+ error.get_msg ().c_str ());
}
return status;
}
@@ -115,7 +113,6 @@ notmuch_database_get_config_list (notmuch_database_t *notmuch,
goto DONE;
}
- talloc_set_destructor (list, _notmuch_config_list_destroy);
list->notmuch = notmuch;
list->current_key = NULL;
list->current_val = NULL;
@@ -123,11 +120,12 @@ notmuch_database_get_config_list (notmuch_database_t *notmuch,
try {
new(&(list->iterator)) Xapian::TermIterator (notmuch->xapian_db->metadata_keys_begin
- (CONFIG_PREFIX + (prefix ? prefix : "")));
+ (CONFIG_PREFIX + (prefix ? prefix : "")));
+ talloc_set_destructor (list, _notmuch_config_list_destroy);
} catch (const Xapian::Error &error) {
_notmuch_database_log (notmuch, "A Xapian exception occurred getting metadata iterator: %s.\n",
- error.get_msg().c_str());
+ error.get_msg ().c_str ());
notmuch->exception_reported = true;
status = NOTMUCH_STATUS_XAPIAN_EXCEPTION;
}
diff --git a/lib/database-private.h b/lib/database-private.h
index 9d1dabf1..041602cd 100644
--- a/lib/database-private.h
+++ b/lib/database-private.h
@@ -62,7 +62,7 @@ enum _notmuch_features {
* unset, file names are stored in document data.
*
* Introduced: version 1. */
- NOTMUCH_FEATURE_FILE_TERMS = 1 << 0,
+ NOTMUCH_FEATURE_FILE_TERMS = 1 << 0,
/* If set, directory timestamps are stored in documents with
* XDIRECTORY terms and relative paths. If unset, directory
@@ -70,7 +70,7 @@ enum _notmuch_features {
* absolute paths.
*
* Introduced: version 1. */
- NOTMUCH_FEATURE_DIRECTORY_DOCS = 1 << 1,
+ NOTMUCH_FEATURE_DIRECTORY_DOCS = 1 << 1,
/* If set, the from, subject, and message-id headers are stored in
* message document values. If unset, message documents *may*
@@ -79,21 +79,21 @@ enum _notmuch_features {
*
* Introduced: optional in version 1, required as of version 3.
*/
- NOTMUCH_FEATURE_FROM_SUBJECT_ID_VALUES = 1 << 2,
+ NOTMUCH_FEATURE_FROM_SUBJECT_ID_VALUES = 1 << 2,
/* If set, folder terms are boolean and path terms exist. If
* unset, folder terms are probabilistic and stemmed and path
* terms do not exist.
*
* Introduced: version 2. */
- NOTMUCH_FEATURE_BOOL_FOLDER = 1 << 3,
+ NOTMUCH_FEATURE_BOOL_FOLDER = 1 << 3,
/* If set, missing messages are stored in ghost mail documents.
* If unset, thread IDs of ghost messages are stored as database
* metadata instead of in ghost documents.
*
* Introduced: version 3. */
- NOTMUCH_FEATURE_GHOSTS = 1 << 4,
+ NOTMUCH_FEATURE_GHOSTS = 1 << 4,
/* If set, then the database was created after the introduction of
@@ -101,52 +101,52 @@ enum _notmuch_features {
* mixture of messages with indexed and non-indexed mime types.
*
* Introduced: version 3. */
- NOTMUCH_FEATURE_INDEXED_MIMETYPES = 1 << 5,
+ NOTMUCH_FEATURE_INDEXED_MIMETYPES = 1 << 5,
/* If set, messages store the revision number of the last
* modification in NOTMUCH_VALUE_LAST_MOD.
*
* Introduced: version 3. */
- NOTMUCH_FEATURE_LAST_MOD = 1 << 6,
+ NOTMUCH_FEATURE_LAST_MOD = 1 << 6,
/* If set, unprefixed terms are stored only for the message body,
* not for headers.
*
* Introduced: version 3. */
- NOTMUCH_FEATURE_UNPREFIX_BODY_ONLY = 1 << 7,
+ NOTMUCH_FEATURE_UNPREFIX_BODY_ONLY = 1 << 7,
};
/* In C++, a named enum is its own type, so define bitwise operators
* on _notmuch_features. */
inline _notmuch_features
-operator|(_notmuch_features a, _notmuch_features b)
+operator| (_notmuch_features a, _notmuch_features b)
{
return static_cast<_notmuch_features>(
static_cast<unsigned>(a) | static_cast<unsigned>(b));
}
inline _notmuch_features
-operator&(_notmuch_features a, _notmuch_features b)
+operator& (_notmuch_features a, _notmuch_features b)
{
return static_cast<_notmuch_features>(
static_cast<unsigned>(a) & static_cast<unsigned>(b));
}
inline _notmuch_features
-operator~(_notmuch_features a)
+operator~ (_notmuch_features a)
{
return static_cast<_notmuch_features>(~static_cast<unsigned>(a));
}
inline _notmuch_features&
-operator|=(_notmuch_features &a, _notmuch_features b)
+operator|= (_notmuch_features &a, _notmuch_features b)
{
a = a | b;
return a;
}
inline _notmuch_features&
-operator&=(_notmuch_features &a, _notmuch_features b)
+operator&= (_notmuch_features &a, _notmuch_features b)
{
a = a & b;
return a;
@@ -155,23 +155,23 @@ operator&=(_notmuch_features &a, _notmuch_features b)
/*
* Configuration options for xapian database fields */
typedef enum notmuch_field_flags {
- NOTMUCH_FIELD_NO_FLAGS = 0,
- NOTMUCH_FIELD_EXTERNAL = 1 << 0,
+ NOTMUCH_FIELD_NO_FLAGS = 0,
+ NOTMUCH_FIELD_EXTERNAL = 1 << 0,
NOTMUCH_FIELD_PROBABILISTIC = 1 << 1,
- NOTMUCH_FIELD_PROCESSOR = 1 << 2,
+ NOTMUCH_FIELD_PROCESSOR = 1 << 2,
} notmuch_field_flag_t;
/*
* define bitwise operators to hide casts */
inline notmuch_field_flag_t
-operator|(notmuch_field_flag_t a, notmuch_field_flag_t b)
+operator| (notmuch_field_flag_t a, notmuch_field_flag_t b)
{
return static_cast<notmuch_field_flag_t>(
static_cast<unsigned>(a) | static_cast<unsigned>(b));
}
inline notmuch_field_flag_t
-operator&(notmuch_field_flag_t a, notmuch_field_flag_t b)
+operator& (notmuch_field_flag_t a, notmuch_field_flag_t b)
{
return static_cast<notmuch_field_flag_t>(
static_cast<unsigned>(a) & static_cast<unsigned>(b));
@@ -189,12 +189,12 @@ struct _notmuch_database {
char *path;
- notmuch_database_mode_t mode;
int atomic_nesting;
/* true if changes have been made in this atomic section */
bool atomic_dirty;
Xapian::Database *xapian_db;
-
+ Xapian::WritableDatabase *writable_xapian_db;
+ bool open;
/* Bit mask of features used by this database. This is a
* bitwise-OR of NOTMUCH_FEATURE_* values (above). */
enum _notmuch_features features;
@@ -218,9 +218,9 @@ struct _notmuch_database {
unsigned long view;
Xapian::QueryParser *query_parser;
Xapian::TermGenerator *term_gen;
- Xapian::ValueRangeProcessor *value_range_processor;
- Xapian::ValueRangeProcessor *date_range_processor;
- Xapian::ValueRangeProcessor *last_mod_range_processor;
+ Xapian::RangeProcessor *value_range_processor;
+ Xapian::RangeProcessor *date_range_processor;
+ Xapian::RangeProcessor *last_mod_range_processor;
/* XXX it's slightly gross to use two parallel string->string maps
* here, but at least they are small */
@@ -230,7 +230,7 @@ struct _notmuch_database {
/* Prior to database version 3, features were implied by the database
* version number, so hard-code them for earlier versions. */
-#define NOTMUCH_FEATURES_V0 ((enum _notmuch_features)0)
+#define NOTMUCH_FEATURES_V0 ((enum _notmuch_features) 0)
#define NOTMUCH_FEATURES_V1 (NOTMUCH_FEATURES_V0 | NOTMUCH_FEATURE_FILE_TERMS | \
NOTMUCH_FEATURE_DIRECTORY_DOCS)
#define NOTMUCH_FEATURES_V2 (NOTMUCH_FEATURES_V1 | NOTMUCH_FEATURE_BOOL_FOLDER)
diff --git a/lib/database.cc b/lib/database.cc
index 4c4c9edc..75189685 100644
--- a/lib/database.cc
+++ b/lib/database.cc
@@ -32,10 +32,10 @@
#include <signal.h>
#include <ftw.h>
-#include <glib.h> /* g_free, GPtrArray, GHashTable */
-#include <glib-object.h> /* g_type_init */
+#include <glib.h> /* g_free, GPtrArray, GHashTable */
+#include <glib-object.h> /* g_type_init */
-#include <gmime/gmime.h> /* g_mime_init */
+#include <gmime/gmime.h> /* g_mime_init */
using namespace std;
@@ -49,7 +49,7 @@ typedef struct {
#define NOTMUCH_DATABASE_VERSION 3
-#define STRINGIFY(s) _SUB_STRINGIFY(s)
+#define STRINGIFY(s) _SUB_STRINGIFY (s)
#define _SUB_STRINGIFY(s) #s
#if HAVE_XAPIAN_DB_RETRY_LOCK
@@ -58,6 +58,26 @@ typedef struct {
#define DB_ACTION Xapian::DB_CREATE_OR_OPEN
#endif
+#define LOG_XAPIAN_EXCEPTION(message, error) _log_xapian_exception (__location__, message, error)
+
+static void
+_log_xapian_exception (const char *where, notmuch_database_t *notmuch, const Xapian::Error error) {
+ _notmuch_database_log (notmuch,
+ "A Xapian exception occurred at %s: %s\n",
+ where,
+ error.get_msg ().c_str ());
+ notmuch->exception_reported = true;
+}
+
+notmuch_database_mode_t
+_notmuch_database_mode (notmuch_database_t *notmuch)
+{
+ if (notmuch->writable_xapian_db)
+ return NOTMUCH_DATABASE_MODE_READ_WRITE;
+ else
+ return NOTMUCH_DATABASE_MODE_READ_ONLY;
+}
+
/* Here's the current schema for our database (for NOTMUCH_DATABASE_VERSION):
*
* We currently have three different types of documents (mail, ghost,
@@ -263,59 +283,57 @@ typedef struct {
static const
prefix_t prefix_table[] = {
/* name term prefix flags */
- { "type", "T", NOTMUCH_FIELD_NO_FLAGS },
- { "reference", "XREFERENCE", NOTMUCH_FIELD_NO_FLAGS },
- { "replyto", "XREPLYTO", NOTMUCH_FIELD_NO_FLAGS },
- { "directory", "XDIRECTORY", NOTMUCH_FIELD_NO_FLAGS },
- { "file-direntry", "XFDIRENTRY", NOTMUCH_FIELD_NO_FLAGS },
- { "directory-direntry", "XDDIRENTRY", NOTMUCH_FIELD_NO_FLAGS },
- { "body", "", NOTMUCH_FIELD_EXTERNAL |
- NOTMUCH_FIELD_PROBABILISTIC},
- { "thread", "G", NOTMUCH_FIELD_EXTERNAL |
- NOTMUCH_FIELD_PROCESSOR },
- { "tag", "K", NOTMUCH_FIELD_EXTERNAL |
- NOTMUCH_FIELD_PROCESSOR },
- { "is", "K", NOTMUCH_FIELD_EXTERNAL |
- NOTMUCH_FIELD_PROCESSOR },
- { "id", "Q", NOTMUCH_FIELD_EXTERNAL },
- { "mid", "Q", NOTMUCH_FIELD_EXTERNAL |
- NOTMUCH_FIELD_PROCESSOR },
- { "path", "P", NOTMUCH_FIELD_EXTERNAL|
- NOTMUCH_FIELD_PROCESSOR },
- { "property", "XPROPERTY", NOTMUCH_FIELD_EXTERNAL },
+ { "type", "T", NOTMUCH_FIELD_NO_FLAGS },
+ { "reference", "XREFERENCE", NOTMUCH_FIELD_NO_FLAGS },
+ { "replyto", "XREPLYTO", NOTMUCH_FIELD_NO_FLAGS },
+ { "directory", "XDIRECTORY", NOTMUCH_FIELD_NO_FLAGS },
+ { "file-direntry", "XFDIRENTRY", NOTMUCH_FIELD_NO_FLAGS },
+ { "directory-direntry", "XDDIRENTRY", NOTMUCH_FIELD_NO_FLAGS },
+ { "body", "", NOTMUCH_FIELD_EXTERNAL |
+ NOTMUCH_FIELD_PROBABILISTIC },
+ { "thread", "G", NOTMUCH_FIELD_EXTERNAL |
+ NOTMUCH_FIELD_PROCESSOR },
+ { "tag", "K", NOTMUCH_FIELD_EXTERNAL |
+ NOTMUCH_FIELD_PROCESSOR },
+ { "is", "K", NOTMUCH_FIELD_EXTERNAL |
+ NOTMUCH_FIELD_PROCESSOR },
+ { "id", "Q", NOTMUCH_FIELD_EXTERNAL },
+ { "mid", "Q", NOTMUCH_FIELD_EXTERNAL |
+ NOTMUCH_FIELD_PROCESSOR },
+ { "path", "P", NOTMUCH_FIELD_EXTERNAL |
+ NOTMUCH_FIELD_PROCESSOR },
+ { "property", "XPROPERTY", NOTMUCH_FIELD_EXTERNAL },
/*
* Unconditionally add ':' to reduce potential ambiguity with
* overlapping prefixes and/or terms that start with capital
* letters. See Xapian document termprefixes.html for related
* discussion.
*/
- { "folder", "XFOLDER:", NOTMUCH_FIELD_EXTERNAL |
- NOTMUCH_FIELD_PROCESSOR },
-#if HAVE_XAPIAN_FIELD_PROCESSOR
- { "date", NULL, NOTMUCH_FIELD_EXTERNAL |
- NOTMUCH_FIELD_PROCESSOR },
- { "query", NULL, NOTMUCH_FIELD_EXTERNAL |
- NOTMUCH_FIELD_PROCESSOR },
-#endif
- { "from", "XFROM", NOTMUCH_FIELD_EXTERNAL |
- NOTMUCH_FIELD_PROBABILISTIC |
- NOTMUCH_FIELD_PROCESSOR },
- { "to", "XTO", NOTMUCH_FIELD_EXTERNAL |
- NOTMUCH_FIELD_PROBABILISTIC },
- { "attachment", "XATTACHMENT", NOTMUCH_FIELD_EXTERNAL |
- NOTMUCH_FIELD_PROBABILISTIC },
- { "mimetype", "XMIMETYPE", NOTMUCH_FIELD_EXTERNAL |
- NOTMUCH_FIELD_PROBABILISTIC },
- { "subject", "XSUBJECT", NOTMUCH_FIELD_EXTERNAL |
- NOTMUCH_FIELD_PROBABILISTIC |
- NOTMUCH_FIELD_PROCESSOR},
+ { "folder", "XFOLDER:", NOTMUCH_FIELD_EXTERNAL |
+ NOTMUCH_FIELD_PROCESSOR },
+ { "date", NULL, NOTMUCH_FIELD_EXTERNAL |
+ NOTMUCH_FIELD_PROCESSOR },
+ { "query", NULL, NOTMUCH_FIELD_EXTERNAL |
+ NOTMUCH_FIELD_PROCESSOR },
+ { "from", "XFROM", NOTMUCH_FIELD_EXTERNAL |
+ NOTMUCH_FIELD_PROBABILISTIC |
+ NOTMUCH_FIELD_PROCESSOR },
+ { "to", "XTO", NOTMUCH_FIELD_EXTERNAL |
+ NOTMUCH_FIELD_PROBABILISTIC },
+ { "attachment", "XATTACHMENT", NOTMUCH_FIELD_EXTERNAL |
+ NOTMUCH_FIELD_PROBABILISTIC },
+ { "mimetype", "XMIMETYPE", NOTMUCH_FIELD_EXTERNAL |
+ NOTMUCH_FIELD_PROBABILISTIC },
+ { "subject", "XSUBJECT", NOTMUCH_FIELD_EXTERNAL |
+ NOTMUCH_FIELD_PROBABILISTIC |
+ NOTMUCH_FIELD_PROCESSOR },
};
static void
_setup_query_field_default (const prefix_t *prefix, notmuch_database_t *notmuch)
{
if (prefix->prefix)
- notmuch->query_parser->add_prefix ("",prefix->prefix);
+ notmuch->query_parser->add_prefix ("", prefix->prefix);
if (prefix->flags & NOTMUCH_FIELD_PROBABILISTIC)
notmuch->query_parser->add_prefix (prefix->name, prefix->prefix);
else
@@ -329,9 +347,9 @@ _notmuch_database_user_headers (notmuch_database_t *notmuch)
}
const char *
-_user_prefix (void *ctx, const char* name)
+_user_prefix (void *ctx, const char *name)
{
- return talloc_asprintf(ctx, "XU%s:", name);
+ return talloc_asprintf (ctx, "XU%s:", name);
}
static notmuch_status_t
@@ -357,7 +375,7 @@ _setup_user_query_fields (notmuch_database_t *notmuch)
prefix_t query_field;
const char *key = notmuch_config_list_key (list)
- + sizeof (CONFIG_HEADER_PREFIX) - 1;
+ + sizeof (CONFIG_HEADER_PREFIX) - 1;
_notmuch_string_map_append (notmuch->user_prefix,
key,
@@ -370,7 +388,7 @@ _setup_user_query_fields (notmuch_database_t *notmuch)
query_field.name = talloc_strdup (notmuch, key);
query_field.prefix = _user_prefix (notmuch, key);
query_field.flags = NOTMUCH_FIELD_PROBABILISTIC
- | NOTMUCH_FIELD_EXTERNAL;
+ | NOTMUCH_FIELD_EXTERNAL;
_setup_query_field_default (&query_field, notmuch);
}
@@ -380,7 +398,6 @@ _setup_user_query_fields (notmuch_database_t *notmuch)
return NOTMUCH_STATUS_SUCCESS;
}
-#if HAVE_XAPIAN_FIELD_PROCESSOR
static void
_setup_query_field (const prefix_t *prefix, notmuch_database_t *notmuch)
{
@@ -388,10 +405,10 @@ _setup_query_field (const prefix_t *prefix, notmuch_database_t *notmuch)
Xapian::FieldProcessor *fp;
if (STRNCMP_LITERAL (prefix->name, "date") == 0)
- fp = (new DateFieldProcessor())->release ();
+ fp = (new DateFieldProcessor(NOTMUCH_VALUE_TIMESTAMP))->release ();
else if (STRNCMP_LITERAL(prefix->name, "query") == 0)
fp = (new QueryFieldProcessor (*notmuch->query_parser, notmuch))->release ();
- else if (STRNCMP_LITERAL(prefix->name, "thread") == 0)
+ else if (STRNCMP_LITERAL (prefix->name, "thread") == 0)
fp = (new ThreadFieldProcessor (*notmuch->query_parser, notmuch))->release ();
else
fp = (new RegexpFieldProcessor (prefix->name, prefix->flags,
@@ -399,19 +416,12 @@ _setup_query_field (const prefix_t *prefix, notmuch_database_t *notmuch)
/* we treat all field-processor fields as boolean in order to get the raw input */
if (prefix->prefix)
- notmuch->query_parser->add_prefix ("",prefix->prefix);
+ notmuch->query_parser->add_prefix ("", prefix->prefix);
notmuch->query_parser->add_boolean_prefix (prefix->name, fp);
} else {
_setup_query_field_default (prefix, notmuch);
}
}
-#else
-static inline void
-_setup_query_field (const prefix_t *prefix, notmuch_database_t *notmuch)
-{
- _setup_query_field_default (prefix, notmuch);
-}
-#endif
const char *
_find_prefix (const char *name)
@@ -469,18 +479,18 @@ static const struct {
{ NOTMUCH_FEATURE_BOOL_FOLDER,
"exact folder:/path: search", "rw" },
{ NOTMUCH_FEATURE_GHOSTS,
- "mail documents for missing messages", "w"},
+ "mail documents for missing messages", "w" },
/* Knowledge of the index mime-types are not required for reading
* a database because a reader will just be unable to query
* them. */
{ NOTMUCH_FEATURE_INDEXED_MIMETYPES,
- "indexed MIME types", "w"},
+ "indexed MIME types", "w" },
{ NOTMUCH_FEATURE_LAST_MOD,
- "modification tracking", "w"},
+ "modification tracking", "w" },
/* Existing databases will work fine for all queries not involving
* 'body:' */
{ NOTMUCH_FEATURE_UNPREFIX_BODY_ONLY,
- "index body and headers separately", "w"},
+ "index body and headers separately", "w" },
};
const char *
@@ -529,8 +539,8 @@ notmuch_status_to_string (notmuch_status_t status)
void
_notmuch_database_log (notmuch_database_t *notmuch,
- const char *format,
- ...)
+ const char *format,
+ ...)
{
va_list va_args;
@@ -545,8 +555,8 @@ _notmuch_database_log (notmuch_database_t *notmuch,
void
_notmuch_database_log_append (notmuch_database_t *notmuch,
- const char *format,
- ...)
+ const char *format,
+ ...)
{
va_list va_args;
@@ -669,7 +679,7 @@ notmuch_database_find_message (notmuch_database_t *notmuch,
return NOTMUCH_STATUS_SUCCESS;
} catch (const Xapian::Error &error) {
_notmuch_database_log (notmuch, "A Xapian exception occurred finding message: %s.\n",
- error.get_msg().c_str());
+ error.get_msg ().c_str ());
notmuch->exception_reported = true;
*message_ret = NULL;
return NOTMUCH_STATUS_XAPIAN_EXCEPTION;
@@ -720,7 +730,7 @@ notmuch_database_create_verbose (const char *path,
err = stat (path, &st);
if (err) {
IGNORE_RESULT (asprintf (&message, "Error: Cannot create database at %s: %s.\n",
- path, strerror (errno)));
+ path, strerror (errno)));
status = NOTMUCH_STATUS_FILE_ERROR;
goto DONE;
}
@@ -758,7 +768,7 @@ notmuch_database_create_verbose (const char *path,
status = notmuch_database_upgrade (notmuch, NULL, NULL);
if (status) {
- notmuch_database_close(notmuch);
+ notmuch_database_close (notmuch);
notmuch = NULL;
}
@@ -782,7 +792,7 @@ notmuch_database_create_verbose (const char *path,
notmuch_status_t
_notmuch_database_ensure_writable (notmuch_database_t *notmuch)
{
- if (notmuch->mode == NOTMUCH_DATABASE_MODE_READ_ONLY) {
+ if (_notmuch_database_mode (notmuch) == NOTMUCH_DATABASE_MODE_READ_ONLY) {
_notmuch_database_log (notmuch, "Cannot write to a read-only database.\n");
return NOTMUCH_STATUS_READ_ONLY_DATABASE;
}
@@ -893,7 +903,7 @@ notmuch_database_open (const char *path,
notmuch_status_t status;
status = notmuch_database_open_verbose (path, mode, database,
- &status_string);
+ &status_string);
if (status_string) {
fputs (status_string, stderr);
@@ -952,7 +962,7 @@ notmuch_database_open_verbose (const char *path,
}
/* Initialize the GLib type system and threads */
-#if !GLIB_CHECK_VERSION(2, 35, 1)
+#if ! GLIB_CHECK_VERSION (2, 35, 1)
g_type_init ();
#endif
@@ -967,9 +977,9 @@ notmuch_database_open_verbose (const char *path,
notmuch->status_string = NULL;
notmuch->path = talloc_strdup (notmuch, path);
- strip_trailing(notmuch->path, '/');
+ strip_trailing (notmuch->path, '/');
- notmuch->mode = mode;
+ notmuch->writable_xapian_db = NULL;
notmuch->atomic_nesting = 0;
notmuch->view = 1;
try {
@@ -977,8 +987,9 @@ notmuch_database_open_verbose (const char *path,
string last_mod;
if (mode == NOTMUCH_DATABASE_MODE_READ_WRITE) {
- notmuch->xapian_db = new Xapian::WritableDatabase (xapian_path,
- DB_ACTION);
+ notmuch->writable_xapian_db = new Xapian::WritableDatabase (xapian_path,
+ DB_ACTION);
+ notmuch->xapian_db = notmuch->writable_xapian_db;
} else {
notmuch->xapian_db = new Xapian::Database (xapian_path);
}
@@ -989,11 +1000,10 @@ notmuch_database_open_verbose (const char *path,
version = notmuch_database_get_version (notmuch);
if (version > NOTMUCH_DATABASE_VERSION) {
IGNORE_RESULT (asprintf (&message,
- "Error: Notmuch database at %s\n"
- " has a newer database format version (%u) than supported by this\n"
- " version of notmuch (%u).\n",
+ "Error: Notmuch database at %s\n"
+ " has a newer database format version (%u) than supported by this\n"
+ " version of notmuch (%u).\n",
notmuch_path, version, NOTMUCH_DATABASE_VERSION));
- notmuch->mode = NOTMUCH_DATABASE_MODE_READ_ONLY;
notmuch_database_destroy (notmuch);
notmuch = NULL;
status = NOTMUCH_STATUS_FILE_ERROR;
@@ -1008,11 +1018,10 @@ notmuch_database_open_verbose (const char *path,
&incompat_features);
if (incompat_features) {
IGNORE_RESULT (asprintf (&message,
- "Error: Notmuch database at %s\n"
- " requires features (%s)\n"
- " not supported by this version of notmuch.\n",
+ "Error: Notmuch database at %s\n"
+ " requires features (%s)\n"
+ " not supported by this version of notmuch.\n",
notmuch_path, incompat_features));
- notmuch->mode = NOTMUCH_DATABASE_MODE_READ_ONLY;
notmuch_database_destroy (notmuch);
notmuch = NULL;
status = NOTMUCH_STATUS_FILE_ERROR;
@@ -1046,17 +1055,16 @@ notmuch_database_open_verbose (const char *path,
notmuch->query_parser = new Xapian::QueryParser;
notmuch->term_gen = new Xapian::TermGenerator;
notmuch->term_gen->set_stemmer (Xapian::Stem ("english"));
- notmuch->value_range_processor = new Xapian::NumberValueRangeProcessor (NOTMUCH_VALUE_TIMESTAMP);
- notmuch->date_range_processor = new ParseTimeValueRangeProcessor (NOTMUCH_VALUE_TIMESTAMP);
- notmuch->last_mod_range_processor = new Xapian::NumberValueRangeProcessor (NOTMUCH_VALUE_LAST_MOD, "lastmod:");
-
+ notmuch->value_range_processor = new Xapian::NumberRangeProcessor (NOTMUCH_VALUE_TIMESTAMP);
+ notmuch->date_range_processor = new ParseTimeRangeProcessor (NOTMUCH_VALUE_TIMESTAMP, "date:");
+ notmuch->last_mod_range_processor = new Xapian::NumberRangeProcessor (NOTMUCH_VALUE_LAST_MOD, "lastmod:");
notmuch->query_parser->set_default_op (Xapian::Query::OP_AND);
notmuch->query_parser->set_database (*notmuch->xapian_db);
notmuch->query_parser->set_stemmer (Xapian::Stem ("english"));
notmuch->query_parser->set_stemming_strategy (Xapian::QueryParser::STEM_SOME);
- notmuch->query_parser->add_valuerangeprocessor (notmuch->value_range_processor);
- notmuch->query_parser->add_valuerangeprocessor (notmuch->date_range_processor);
- notmuch->query_parser->add_valuerangeprocessor (notmuch->last_mod_range_processor);
+ notmuch->query_parser->add_rangeprocessor (notmuch->value_range_processor);
+ notmuch->query_parser->add_rangeprocessor (notmuch->date_range_processor);
+ notmuch->query_parser->add_rangeprocessor (notmuch->last_mod_range_processor);
for (i = 0; i < ARRAY_SIZE (prefix_table); i++) {
const prefix_t *prefix = &prefix_table[i];
@@ -1067,7 +1075,7 @@ notmuch_database_open_verbose (const char *path,
status = _setup_user_query_fields (notmuch);
} catch (const Xapian::Error &error) {
IGNORE_RESULT (asprintf (&message, "A Xapian exception occurred opening database: %s\n",
- error.get_msg().c_str()));
+ error.get_msg ().c_str ()));
notmuch_database_destroy (notmuch);
notmuch = NULL;
status = NOTMUCH_STATUS_XAPIAN_EXCEPTION;
@@ -1087,6 +1095,10 @@ notmuch_database_open_verbose (const char *path,
*database = notmuch;
else
talloc_free (notmuch);
+
+ if (notmuch)
+ notmuch->open = true;
+
return status;
}
@@ -1098,50 +1110,36 @@ notmuch_database_close (notmuch_database_t *notmuch)
/* Many Xapian objects (and thus notmuch objects) hold references to
* the database, so merely deleting the database may not suffice to
* close it. Thus, we explicitly close it here. */
- if (notmuch->xapian_db != NULL) {
+ if (notmuch->open) {
try {
/* If there's an outstanding transaction, it's unclear if
* closing the Xapian database commits everything up to
* that transaction, or may discard committed (but
* unflushed) transactions. To be certain, explicitly
* cancel any outstanding transaction before closing. */
- if (notmuch->mode == NOTMUCH_DATABASE_MODE_READ_WRITE &&
+ if (_notmuch_database_mode (notmuch) == NOTMUCH_DATABASE_MODE_READ_WRITE &&
notmuch->atomic_nesting)
- (static_cast <Xapian::WritableDatabase *> (notmuch->xapian_db))
- ->cancel_transaction ();
+ notmuch->writable_xapian_db->cancel_transaction ();
/* Close the database. This implicitly flushes
* outstanding changes. */
- notmuch->xapian_db->close();
+ notmuch->xapian_db->close ();
} catch (const Xapian::Error &error) {
status = NOTMUCH_STATUS_XAPIAN_EXCEPTION;
if (! notmuch->exception_reported) {
_notmuch_database_log (notmuch, "Error: A Xapian exception occurred closing database: %s\n",
- error.get_msg().c_str());
+ error.get_msg ().c_str ());
}
}
}
-
- delete notmuch->term_gen;
- notmuch->term_gen = NULL;
- delete notmuch->query_parser;
- notmuch->query_parser = NULL;
- delete notmuch->xapian_db;
- notmuch->xapian_db = NULL;
- delete notmuch->value_range_processor;
- notmuch->value_range_processor = NULL;
- delete notmuch->date_range_processor;
- notmuch->date_range_processor = NULL;
- delete notmuch->last_mod_range_processor;
- notmuch->last_mod_range_processor = NULL;
-
+ notmuch->open = false;
return status;
}
notmuch_status_t
_notmuch_database_reopen (notmuch_database_t *notmuch)
{
- if (notmuch->mode != NOTMUCH_DATABASE_MODE_READ_ONLY)
+ if (_notmuch_database_mode (notmuch) != NOTMUCH_DATABASE_MODE_READ_ONLY)
return NOTMUCH_STATUS_UNSUPPORTED_OPERATION;
try {
@@ -1182,7 +1180,9 @@ class NotmuchCompactor : public Xapian::Compactor
public:
NotmuchCompactor(notmuch_compact_status_cb_t cb, void *closure) :
- status_cb (cb), status_closure (closure) { }
+ status_cb (cb), status_closure (closure)
+ {
+ }
virtual void
set_status (const std::string &table, const std::string &status)
@@ -1193,9 +1193,9 @@ public:
return;
if (status.length () == 0)
- msg = talloc_asprintf (NULL, "compacting table %s", table.c_str());
+ msg = talloc_asprintf (NULL, "compacting table %s", table.c_str ());
else
- msg = talloc_asprintf (NULL, " %s", status.c_str());
+ msg = talloc_asprintf (NULL, " %s", status.c_str ());
if (msg == NULL) {
return;
@@ -1265,8 +1265,7 @@ notmuch_database_compact (const char *path,
goto DONE;
}
keep_backup = false;
- }
- else {
+ } else {
keep_backup = true;
}
@@ -1277,7 +1276,7 @@ notmuch_database_compact (const char *path,
}
if (errno != ENOENT) {
_notmuch_database_log (notmuch, "Unknown error while stat()ing path: %s\n",
- strerror (errno));
+ strerror (errno));
ret = NOTMUCH_STATUS_FILE_ERROR;
goto DONE;
}
@@ -1290,27 +1289,23 @@ notmuch_database_compact (const char *path,
try {
NotmuchCompactor compactor (status_cb, closure);
-
- compactor.set_renumber (false);
- compactor.add_source (xapian_path);
- compactor.set_destdir (compact_xapian_path);
- compactor.compact ();
+ notmuch->xapian_db->compact (compact_xapian_path, Xapian::DBCOMPACT_NO_RENUMBER, 0, compactor);
} catch (const Xapian::Error &error) {
- _notmuch_database_log (notmuch, "Error while compacting: %s\n", error.get_msg().c_str());
+ _notmuch_database_log (notmuch, "Error while compacting: %s\n", error.get_msg ().c_str ());
ret = NOTMUCH_STATUS_XAPIAN_EXCEPTION;
goto DONE;
}
if (rename (xapian_path, backup_path)) {
_notmuch_database_log (notmuch, "Error moving %s to %s: %s\n",
- xapian_path, backup_path, strerror (errno));
+ xapian_path, backup_path, strerror (errno));
ret = NOTMUCH_STATUS_FILE_ERROR;
goto DONE;
}
if (rename (compact_xapian_path, xapian_path)) {
_notmuch_database_log (notmuch, "Error moving %s to %s: %s\n",
- compact_xapian_path, xapian_path, strerror (errno));
+ compact_xapian_path, xapian_path, strerror (errno));
ret = NOTMUCH_STATUS_FILE_ERROR;
goto DONE;
}
@@ -1318,7 +1313,7 @@ notmuch_database_compact (const char *path,
if (! keep_backup) {
if (rmtree (backup_path)) {
_notmuch_database_log (notmuch, "Error removing old database %s: %s\n",
- backup_path, strerror (errno));
+ backup_path, strerror (errno));
ret = NOTMUCH_STATUS_FILE_ERROR;
goto DONE;
}
@@ -1350,6 +1345,20 @@ notmuch_database_destroy (notmuch_database_t *notmuch)
notmuch_status_t status;
status = notmuch_database_close (notmuch);
+
+ delete notmuch->term_gen;
+ notmuch->term_gen = NULL;
+ delete notmuch->query_parser;
+ notmuch->query_parser = NULL;
+ delete notmuch->xapian_db;
+ notmuch->xapian_db = NULL;
+ delete notmuch->value_range_processor;
+ notmuch->value_range_processor = NULL;
+ delete notmuch->date_range_processor;
+ notmuch->date_range_processor = NULL;
+ delete notmuch->last_mod_range_processor;
+ notmuch->last_mod_range_processor = NULL;
+
talloc_free (notmuch);
return status;
@@ -1369,7 +1378,13 @@ notmuch_database_get_version (notmuch_database_t *notmuch)
const char *str;
char *end;
- version_string = notmuch->xapian_db->get_metadata ("version");
+ try {
+ version_string = notmuch->xapian_db->get_metadata ("version");
+ } catch (const Xapian::Error &error) {
+ LOG_XAPIAN_EXCEPTION (notmuch, error);
+ return 0;
+ }
+
if (version_string.empty ())
return 0;
@@ -1387,9 +1402,17 @@ notmuch_database_get_version (notmuch_database_t *notmuch)
notmuch_bool_t
notmuch_database_needs_upgrade (notmuch_database_t *notmuch)
{
- return notmuch->mode == NOTMUCH_DATABASE_MODE_READ_WRITE &&
- ((NOTMUCH_FEATURES_CURRENT & ~notmuch->features) ||
- (notmuch_database_get_version (notmuch) < NOTMUCH_DATABASE_VERSION));
+ unsigned int version;
+
+ if (_notmuch_database_mode (notmuch) != NOTMUCH_DATABASE_MODE_READ_WRITE)
+ return FALSE;
+
+ if (NOTMUCH_FEATURES_CURRENT & ~notmuch->features)
+ return TRUE;
+
+ version = notmuch_database_get_version (notmuch);
+
+ return (version > 0 && version < NOTMUCH_DATABASE_VERSION);
}
static volatile sig_atomic_t do_progress_notify = 0;
@@ -1434,7 +1457,7 @@ notmuch_database_upgrade (notmuch_database_t *notmuch,
if (status)
return status;
- db = static_cast <Xapian::WritableDatabase *> (notmuch->xapian_db);
+ db = notmuch->writable_xapian_db;
target_features = notmuch->features | NOTMUCH_FEATURES_CURRENT;
new_features = NOTMUCH_FEATURES_CURRENT & ~notmuch->features;
@@ -1510,8 +1533,7 @@ notmuch_database_upgrade (notmuch_database_t *notmuch,
goto DONE;
for (;
notmuch_messages_valid (messages);
- notmuch_messages_move_to_next (messages))
- {
+ notmuch_messages_move_to_next (messages)) {
if (do_progress_notify) {
progress_notify (closure, (double) count / total);
do_progress_notify = 0;
@@ -1568,8 +1590,7 @@ notmuch_database_upgrade (notmuch_database_t *notmuch,
for (t = notmuch->xapian_db->allterms_begin ("XTIMESTAMP");
t != t_end;
- t++)
- {
+ t++) {
Xapian::PostingIterator p, p_end;
std::string term = *t;
@@ -1577,8 +1598,7 @@ notmuch_database_upgrade (notmuch_database_t *notmuch,
for (p = notmuch->xapian_db->postlist_begin (term);
p != p_end;
- p++)
- {
+ p++) {
Xapian::Document document;
time_t mtime;
notmuch_directory_t *directory;
@@ -1592,8 +1612,8 @@ notmuch_database_upgrade (notmuch_database_t *notmuch,
mtime = Xapian::sortable_unserialise (
document.get_value (NOTMUCH_VALUE_TIMESTAMP));
- directory = _notmuch_directory_create (notmuch, term.c_str() + 10,
- NOTMUCH_FIND_CREATE, &status);
+ directory = _notmuch_directory_find_or_create (notmuch, term.c_str () + 10,
+ NOTMUCH_FIND_CREATE, &status);
notmuch_directory_set_mtime (directory, mtime);
notmuch_directory_destroy (directory);
@@ -1641,7 +1661,7 @@ notmuch_database_upgrade (notmuch_database_t *notmuch,
if (private_status) {
_notmuch_database_log (notmuch,
- "Upgrade failed while creating ghost messages.\n");
+ "Upgrade failed while creating ghost messages.\n");
status = COERCE_STATUS (private_status, "Unexpected status from _notmuch_message_initialize_ghost");
goto DONE;
}
@@ -1657,7 +1677,7 @@ notmuch_database_upgrade (notmuch_database_t *notmuch,
db->set_metadata ("features", _print_features (local, notmuch->features));
db->set_metadata ("version", STRINGIFY (NOTMUCH_DATABASE_VERSION));
- DONE:
+ DONE:
if (status == NOTMUCH_STATUS_SUCCESS)
db->commit_transaction ();
else
@@ -1686,7 +1706,7 @@ notmuch_database_upgrade (notmuch_database_t *notmuch,
notmuch_status_t
notmuch_database_begin_atomic (notmuch_database_t *notmuch)
{
- if (notmuch->mode == NOTMUCH_DATABASE_MODE_READ_ONLY ||
+ if (_notmuch_database_mode (notmuch) == NOTMUCH_DATABASE_MODE_READ_ONLY ||
notmuch->atomic_nesting > 0)
goto DONE;
@@ -1694,15 +1714,15 @@ notmuch_database_begin_atomic (notmuch_database_t *notmuch)
return NOTMUCH_STATUS_UPGRADE_REQUIRED;
try {
- (static_cast <Xapian::WritableDatabase *> (notmuch->xapian_db))->begin_transaction (false);
+ notmuch->writable_xapian_db->begin_transaction (false);
} catch (const Xapian::Error &error) {
_notmuch_database_log (notmuch, "A Xapian exception occurred beginning transaction: %s.\n",
- error.get_msg().c_str());
+ error.get_msg ().c_str ());
notmuch->exception_reported = true;
return NOTMUCH_STATUS_XAPIAN_EXCEPTION;
}
-DONE:
+ DONE:
notmuch->atomic_nesting++;
return NOTMUCH_STATUS_SUCCESS;
}
@@ -1715,11 +1735,11 @@ notmuch_database_end_atomic (notmuch_database_t *notmuch)
if (notmuch->atomic_nesting == 0)
return NOTMUCH_STATUS_UNBALANCED_ATOMIC;
- if (notmuch->mode == NOTMUCH_DATABASE_MODE_READ_ONLY ||
+ if (_notmuch_database_mode (notmuch) == NOTMUCH_DATABASE_MODE_READ_ONLY ||
notmuch->atomic_nesting > 1)
goto DONE;
- db = static_cast <Xapian::WritableDatabase *> (notmuch->xapian_db);
+ db = notmuch->writable_xapian_db;
try {
db->commit_transaction ();
@@ -1731,7 +1751,7 @@ notmuch_database_end_atomic (notmuch_database_t *notmuch)
db->commit ();
} catch (const Xapian::Error &error) {
_notmuch_database_log (notmuch, "A Xapian exception occurred committing transaction: %s.\n",
- error.get_msg().c_str());
+ error.get_msg ().c_str ());
notmuch->exception_reported = true;
return NOTMUCH_STATUS_XAPIAN_EXCEPTION;
}
@@ -1741,14 +1761,14 @@ notmuch_database_end_atomic (notmuch_database_t *notmuch)
notmuch->atomic_dirty = false;
}
-DONE:
+ DONE:
notmuch->atomic_nesting--;
return NOTMUCH_STATUS_SUCCESS;
}
unsigned long
notmuch_database_get_revision (notmuch_database_t *notmuch,
- const char **uuid)
+ const char **uuid)
{
if (uuid)
*uuid = notmuch->uuid;
@@ -1865,8 +1885,8 @@ _notmuch_database_find_directory_id (notmuch_database_t *notmuch,
return NOTMUCH_STATUS_SUCCESS;
}
- directory = _notmuch_directory_create (notmuch, path, flags, &status);
- if (status || !directory) {
+ directory = _notmuch_directory_find_or_create (notmuch, path, flags, &status);
+ if (status || ! directory) {
*directory_id = -1;
return status;
}
@@ -1920,7 +1940,7 @@ _notmuch_database_filename_to_direntry (void *ctx,
status = _notmuch_database_find_directory_id (notmuch, directory, flags,
&directory_id);
- if (status || directory_id == (unsigned int)-1) {
+ if (status || directory_id == (unsigned int) -1) {
*direntry = NULL;
return status;
}
@@ -1950,11 +1970,10 @@ _notmuch_database_relative_path (notmuch_database_t *notmuch,
relative = path;
if (*relative == '/') {
- while (*relative == '/' && *(relative+1) == '/')
+ while (*relative == '/' && *(relative + 1) == '/')
relative++;
- if (strncmp (relative, db_path, db_path_len) == 0)
- {
+ if (strncmp (relative, db_path, db_path_len) == 0) {
relative += db_path_len;
while (*relative == '/')
relative++;
@@ -1976,11 +1995,11 @@ notmuch_database_get_directory (notmuch_database_t *notmuch,
*directory = NULL;
try {
- *directory = _notmuch_directory_create (notmuch, path,
- NOTMUCH_FIND_LOOKUP, &status);
+ *directory = _notmuch_directory_find_or_create (notmuch, path,
+ NOTMUCH_FIND_LOOKUP, &status);
} catch (const Xapian::Error &error) {
_notmuch_database_log (notmuch, "A Xapian exception occurred getting directory: %s.\n",
- error.get_msg().c_str());
+ error.get_msg ().c_str ());
notmuch->exception_reported = true;
status = NOTMUCH_STATUS_XAPIAN_EXCEPTION;
}
@@ -2023,13 +2042,13 @@ notmuch_database_remove_message (notmuch_database_t *notmuch,
&message);
if (status == NOTMUCH_STATUS_SUCCESS && message) {
- status = _notmuch_message_remove_filename (message, filename);
- if (status == NOTMUCH_STATUS_SUCCESS)
- _notmuch_message_delete (message);
- else if (status == NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID)
- _notmuch_message_sync (message);
+ status = _notmuch_message_remove_filename (message, filename);
+ if (status == NOTMUCH_STATUS_SUCCESS)
+ _notmuch_message_delete (message);
+ else if (status == NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID)
+ _notmuch_message_sync (message);
- notmuch_message_destroy (message);
+ notmuch_message_destroy (message);
}
return status;
@@ -2060,7 +2079,7 @@ notmuch_database_find_message_by_filename (notmuch_database_t *notmuch,
try {
status = _notmuch_database_filename_to_direntry (
local, notmuch, filename, NOTMUCH_FIND_LOOKUP, &direntry);
- if (status || !direntry)
+ if (status || ! direntry)
goto DONE;
term = talloc_asprintf (local, "%s%s", prefix, direntry);
@@ -2077,7 +2096,7 @@ notmuch_database_find_message_by_filename (notmuch_database_t *notmuch,
}
} catch (const Xapian::Error &error) {
_notmuch_database_log (notmuch, "Error: A Xapian exception occurred finding message by filename: %s\n",
- error.get_msg().c_str());
+ error.get_msg ().c_str ());
notmuch->exception_reported = true;
status = NOTMUCH_STATUS_XAPIAN_EXCEPTION;
}
@@ -2122,15 +2141,15 @@ notmuch_database_get_all_tags (notmuch_database_t *db)
notmuch_string_list_t *tags;
try {
- i = db->xapian_db->allterms_begin();
- end = db->xapian_db->allterms_end();
+ i = db->xapian_db->allterms_begin ();
+ end = db->xapian_db->allterms_end ();
tags = _notmuch_database_get_terms_with_prefix (db, i, end,
_find_prefix ("tag"));
_notmuch_string_list_sort (tags);
return _notmuch_tags_create (db, tags);
} catch (const Xapian::Error &error) {
_notmuch_database_log (db, "A Xapian exception occurred getting tags: %s.\n",
- error.get_msg().c_str());
+ error.get_msg ().c_str ());
db->exception_reported = true;
return NULL;
}
diff --git a/lib/directory.cc b/lib/directory.cc
index 4fcb0177..eee8254e 100644
--- a/lib/directory.cc
+++ b/lib/directory.cc
@@ -32,8 +32,8 @@ _create_filenames_for_terms_with_prefix (void *ctx,
notmuch_string_list_t *filename_list;
Xapian::TermIterator i, end;
- i = notmuch->xapian_db->allterms_begin();
- end = notmuch->xapian_db->allterms_end();
+ i = notmuch->xapian_db->allterms_begin ();
+ end = notmuch->xapian_db->allterms_end ();
filename_list = _notmuch_database_get_terms_with_prefix (ctx, i, end,
prefix);
if (unlikely (filename_list == NULL))
@@ -49,6 +49,19 @@ struct _notmuch_directory {
time_t mtime;
};
+#define LOG_XAPIAN_EXCEPTION(directory, error) _log_xapian_exception (__location__, directory, error)
+
+static void
+_log_xapian_exception (const char *where, notmuch_directory_t *dir, const Xapian::Error error) {
+ notmuch_database_t *notmuch = dir->notmuch;
+ _notmuch_database_log (notmuch,
+ "A Xapian exception occurred at %s: %s\n",
+ where,
+ error.get_msg ().c_str ());
+ notmuch->exception_reported = true;
+}
+
+
/* We end up having to call the destructor explicitly because we had
* to use "placement new" in order to initialize C++ objects within a
* block that we allocated with talloc. So C++ is making talloc
@@ -94,12 +107,11 @@ find_directory_document (notmuch_database_t *notmuch,
* NOTMUCH_STATUS_SUCCESS and this returns NULL.
*/
notmuch_directory_t *
-_notmuch_directory_create (notmuch_database_t *notmuch,
- const char *path,
- notmuch_find_flags_t flags,
- notmuch_status_t *status_ret)
+_notmuch_directory_find_or_create (notmuch_database_t *notmuch,
+ const char *path,
+ notmuch_find_flags_t flags,
+ notmuch_status_t *status_ret)
{
- Xapian::WritableDatabase *db;
notmuch_directory_t *directory;
notmuch_private_status_t private_status;
const char *db_path;
@@ -114,7 +126,7 @@ _notmuch_directory_create (notmuch_database_t *notmuch,
path = _notmuch_database_relative_path (notmuch, path);
- if (create && notmuch->mode == NOTMUCH_DATABASE_MODE_READ_ONLY)
+ if (create && _notmuch_database_mode (notmuch) == NOTMUCH_DATABASE_MODE_READ_ONLY)
INTERNAL_ERROR ("Failure to ensure database is writable");
directory = talloc (notmuch, notmuch_directory_t);
@@ -140,7 +152,7 @@ _notmuch_directory_create (notmuch_database_t *notmuch,
directory->document_id = directory->doc.get_docid ();
if (private_status == NOTMUCH_PRIVATE_STATUS_NO_DOCUMENT_FOUND) {
- if (!create) {
+ if (! create) {
notmuch_directory_destroy (directory);
directory = NULL;
*status_ret = NOTMUCH_STATUS_SUCCESS;
@@ -176,10 +188,10 @@ _notmuch_directory_create (notmuch_database_t *notmuch,
directory->doc.add_value (NOTMUCH_VALUE_TIMESTAMP,
Xapian::sortable_serialise (0));
- db = static_cast <Xapian::WritableDatabase *> (notmuch->xapian_db);
-
directory->document_id = _notmuch_database_generate_doc_id (notmuch);
- db->replace_document (directory->document_id, directory->doc);
+ directory->notmuch->
+ writable_xapian_db
+ -> replace_document (directory->document_id, directory->doc);
talloc_free (local);
}
@@ -187,8 +199,8 @@ _notmuch_directory_create (notmuch_database_t *notmuch,
directory->doc.get_value (NOTMUCH_VALUE_TIMESTAMP));
} catch (const Xapian::Error &error) {
_notmuch_database_log (notmuch,
- "A Xapian exception occurred creating a directory: %s.\n",
- error.get_msg().c_str());
+ "A Xapian exception occurred finding/creating a directory: %s.\n",
+ error.get_msg ().c_str ());
notmuch->exception_reported = true;
notmuch_directory_destroy (directory);
directory = NULL;
@@ -213,27 +225,25 @@ notmuch_directory_set_mtime (notmuch_directory_t *directory,
time_t mtime)
{
notmuch_database_t *notmuch = directory->notmuch;
- Xapian::WritableDatabase *db;
notmuch_status_t status;
status = _notmuch_database_ensure_writable (notmuch);
if (status)
return status;
- db = static_cast <Xapian::WritableDatabase *> (notmuch->xapian_db);
-
try {
directory->doc.add_value (NOTMUCH_VALUE_TIMESTAMP,
- Xapian::sortable_serialise (mtime));
+ Xapian::sortable_serialise (mtime));
- db->replace_document (directory->document_id, directory->doc);
+ directory->notmuch
+ ->writable_xapian_db->replace_document (directory->document_id, directory->doc);
directory->mtime = mtime;
} catch (const Xapian::Error &error) {
_notmuch_database_log (notmuch,
- "A Xapian exception occurred setting directory mtime: %s.\n",
- error.get_msg().c_str());
+ "A Xapian exception occurred setting directory mtime: %s.\n",
+ error.get_msg ().c_str ());
notmuch->exception_reported = true;
return NOTMUCH_STATUS_XAPIAN_EXCEPTION;
}
@@ -251,15 +261,19 @@ notmuch_filenames_t *
notmuch_directory_get_child_files (notmuch_directory_t *directory)
{
char *term;
- notmuch_filenames_t *child_files;
+ notmuch_filenames_t *child_files = NULL;
term = talloc_asprintf (directory, "%s%u:",
_find_prefix ("file-direntry"),
directory->document_id);
- child_files = _create_filenames_for_terms_with_prefix (directory,
- directory->notmuch,
- term);
+ try {
+ child_files = _create_filenames_for_terms_with_prefix (directory,
+ directory->notmuch,
+ term);
+ } catch (Xapian::Error &error) {
+ LOG_XAPIAN_EXCEPTION (directory, error);
+ }
talloc_free (term);
@@ -270,14 +284,18 @@ notmuch_filenames_t *
notmuch_directory_get_child_directories (notmuch_directory_t *directory)
{
char *term;
- notmuch_filenames_t *child_directories;
+ notmuch_filenames_t *child_directories = NULL;
term = talloc_asprintf (directory, "%s%u:",
_find_prefix ("directory-direntry"),
directory->document_id);
- child_directories = _create_filenames_for_terms_with_prefix (directory,
- directory->notmuch, term);
+ try {
+ child_directories = _create_filenames_for_terms_with_prefix (directory,
+ directory->notmuch, term);
+ } catch (Xapian::Error &error) {
+ LOG_XAPIAN_EXCEPTION (directory, error);
+ }
talloc_free (term);
@@ -288,25 +306,24 @@ notmuch_status_t
notmuch_directory_delete (notmuch_directory_t *directory)
{
notmuch_status_t status;
- Xapian::WritableDatabase *db;
status = _notmuch_database_ensure_writable (directory->notmuch);
if (status)
return status;
try {
- db = static_cast <Xapian::WritableDatabase *> (directory->notmuch->xapian_db);
- db->delete_document (directory->document_id);
+ directory->notmuch->
+ writable_xapian_db->delete_document (directory->document_id);
} catch (const Xapian::Error &error) {
_notmuch_database_log (directory->notmuch,
"A Xapian exception occurred deleting directory entry: %s.\n",
- error.get_msg().c_str());
+ error.get_msg ().c_str ());
directory->notmuch->exception_reported = true;
status = NOTMUCH_STATUS_XAPIAN_EXCEPTION;
}
notmuch_directory_destroy (directory);
- return NOTMUCH_STATUS_SUCCESS;
+ return status;
}
void
diff --git a/lib/index.cc b/lib/index.cc
index 1fd9e67e..826aa341 100644
--- a/lib/index.cc
+++ b/lib/index.cc
@@ -43,46 +43,46 @@ typedef struct {
* which we discard data. */
static const int first_uuencode_skipping_state = 11;
static const scanner_state_t uuencode_states[] = {
- {0, 'b', 'b', 1, 0},
- {1, 'e', 'e', 2, 0},
- {2, 'g', 'g', 3, 0},
- {3, 'i', 'i', 4, 0},
- {4, 'n', 'n', 5, 0},
- {5, ' ', ' ', 6, 0},
- {6, '0', '7', 7, 0},
- {7, '0', '7', 8, 0},
- {8, '0', '7', 9, 0},
- {9, ' ', ' ', 10, 0},
- {10, '\n', '\n', 11, 10},
- {11, 'M', 'M', 12, 0},
- {12, ' ', '`', 12, 11}
+ { 0, 'b', 'b', 1, 0 },
+ { 1, 'e', 'e', 2, 0 },
+ { 2, 'g', 'g', 3, 0 },
+ { 3, 'i', 'i', 4, 0 },
+ { 4, 'n', 'n', 5, 0 },
+ { 5, ' ', ' ', 6, 0 },
+ { 6, '0', '7', 7, 0 },
+ { 7, '0', '7', 8, 0 },
+ { 8, '0', '7', 9, 0 },
+ { 9, ' ', ' ', 10, 0 },
+ { 10, '\n', '\n', 11, 10 },
+ { 11, 'M', 'M', 12, 0 },
+ { 12, ' ', '`', 12, 11 }
};
/* The following table is intended to implement this DFA (in 'dot'
- format). Note that 2 and 3 are "hidden" states used to step through
- the possible out edges of state 1.
-
-digraph html_filter {
- 0 -> 1 [label="<"];
- 0 -> 0;
- 1 -> 4 [label="'"];
- 1 -> 5 [label="\""];
- 1 -> 0 [label=">"];
- 1 -> 1;
- 4 -> 1 [label="'"];
- 4 -> 4;
- 5 -> 1 [label="\""];
- 5 -> 5;
-}
-*/
+ * format). Note that 2 and 3 are "hidden" states used to step through
+ * the possible out edges of state 1.
+ *
+ * digraph html_filter {
+ * 0 -> 1 [label="<"];
+ * 0 -> 0;
+ * 1 -> 4 [label="'"];
+ * 1 -> 5 [label="\""];
+ * 1 -> 0 [label=">"];
+ * 1 -> 1;
+ * 4 -> 1 [label="'"];
+ * 4 -> 4;
+ * 5 -> 1 [label="\""];
+ * 5 -> 5;
+ * }
+ */
static const int first_html_skipping_state = 1;
static const scanner_state_t html_states[] = {
- {0, '<', '<', 1, 0},
- {1, '\'', '\'', 4, 2}, /* scanning for quote or > */
- {1, '"', '"', 5, 3},
- {1, '>', '>', 0, 1},
- {4, '\'', '\'', 1, 4}, /* inside single quotes */
- {5, '"', '"', 1, 5}, /* inside double quotes */
+ { 0, '<', '<', 1, 0 },
+ { 1, '\'', '\'', 4, 2 }, /* scanning for quote or > */
+ { 1, '"', '"', 5, 3 },
+ { 1, '>', '>', 0, 1 },
+ { 4, '\'', '\'', 1, 4 }, /* inside single quotes */
+ { 5, '"', '"', 1, 5 }, /* inside double quotes */
};
/* Oh, how I wish that gobject didn't require so much noisy boilerplate!
@@ -168,6 +168,7 @@ static GMimeFilter *
filter_copy (GMimeFilter *gmime_filter)
{
NotmuchFilterDiscardNonTerm *filter = (NotmuchFilterDiscardNonTerm *) gmime_filter;
+
return notmuch_filter_discard_non_term_new (filter->content_type);
}
@@ -190,7 +191,7 @@ filter_filter (GMimeFilter *gmime_filter, char *inbuf, size_t inlen, size_t pres
next = filter->state;
while (inptr < inend) {
- /* Each state is defined by a contiguous set of rows of the
+ /* Each state is defined by a contiguous set of rows of the
* state table marked by a common value for '.state'. The
* state numbers must be equal to the index of the first row
* in a given state; thus the loop condition here looks for a
@@ -198,9 +199,9 @@ filter_filter (GMimeFilter *gmime_filter, char *inbuf, size_t inlen, size_t pres
* in the underlying DFA.
*/
do {
- if (*inptr >= states[next].a && *inptr <= states[next].b) {
+ if (*inptr >= states[next].a && *inptr <= states[next].b) {
next = states[next].next_if_match;
- } else {
+ } else {
next = states[next].next_if_not_match;
}
@@ -245,7 +246,7 @@ notmuch_filter_discard_non_term_new (GMimeContentType *content_type)
static GType type = 0;
NotmuchFilterDiscardNonTerm *filter;
- if (!type) {
+ if (! type) {
static const GTypeInfo info = {
.class_size = sizeof (NotmuchFilterDiscardNonTermClass),
.base_init = NULL,
@@ -266,11 +267,11 @@ notmuch_filter_discard_non_term_new (GMimeContentType *content_type)
filter->content_type = content_type;
filter->state = 0;
if (g_mime_content_type_is_type (content_type, "text", "html")) {
- filter->states = html_states;
- filter->first_skipping_state = first_html_skipping_state;
+ filter->states = html_states;
+ filter->first_skipping_state = first_html_skipping_state;
} else {
- filter->states = uuencode_states;
- filter->first_skipping_state = first_uuencode_skipping_state;
+ filter->states = uuencode_states;
+ filter->first_skipping_state = first_uuencode_skipping_state;
}
return (GMimeFilter *) filter;
@@ -356,6 +357,7 @@ static void
_index_content_type (notmuch_message_t *message, GMimeObject *part)
{
GMimeContentType *content_type = g_mime_object_get_content_type (part);
+
if (content_type) {
char *mime_string = g_mime_content_type_get_mime_type (content_type);
if (mime_string) {
@@ -367,9 +369,15 @@ _index_content_type (notmuch_message_t *message, GMimeObject *part)
static void
_index_encrypted_mime_part (notmuch_message_t *message, notmuch_indexopts_t *indexopts,
- GMimeMultipartEncrypted *part,
+ GMimeObject *part,
_notmuch_message_crypto_t *msg_crypto);
+static void
+_index_pkcs7_part (notmuch_message_t *message,
+ notmuch_indexopts_t *indexopts,
+ GMimeObject *part,
+ _notmuch_message_crypto_t *msg_crypto);
+
/* Callback to generate terms for each mime part of a message. */
static void
_index_mime_part (notmuch_message_t *message,
@@ -385,11 +393,20 @@ _index_mime_part (notmuch_message_t *message,
GMimeContentType *content_type;
char *body;
const char *charset;
+ GMimeObject *repaired_part = NULL;
if (! part) {
_notmuch_database_log (notmuch_message_get_database (message),
- "Warning: Not indexing empty mime part.\n");
- return;
+ "Warning: Not indexing empty mime part.\n");
+ goto DONE;
+ }
+
+ repaired_part = _notmuch_repair_mixed_up_mangled (part);
+ if (repaired_part) {
+ /* This was likely "Mixed Up" in transit! We will instead use
+ * the more likely-to-be-correct variant. */
+ notmuch_message_add_property (message, "index.repaired", "mixedup");
+ part = repaired_part;
}
_index_content_type (message, part);
@@ -399,13 +416,12 @@ _index_mime_part (notmuch_message_t *message,
int i;
if (GMIME_IS_MULTIPART_SIGNED (multipart))
- _notmuch_message_add_term (message, "tag", "signed");
+ _notmuch_message_add_term (message, "tag", "signed");
if (GMIME_IS_MULTIPART_ENCRYPTED (multipart))
- _notmuch_message_add_term (message, "tag", "encrypted");
+ _notmuch_message_add_term (message, "tag", "encrypted");
for (i = 0; i < g_mime_multipart_get_count (multipart); i++) {
- notmuch_status_t status;
GMimeObject *child;
if (GMIME_IS_MULTIPART_SIGNED (multipart)) {
/* Don't index the signature, but index its content type. */
@@ -422,9 +438,9 @@ _index_mime_part (notmuch_message_t *message,
_index_content_type (message,
g_mime_multipart_get_part (multipart, i));
if (i == GMIME_MULTIPART_ENCRYPTED_CONTENT) {
- _index_encrypted_mime_part(message, indexopts,
- GMIME_MULTIPART_ENCRYPTED (part),
- msg_crypto);
+ _index_encrypted_mime_part (message, indexopts,
+ part,
+ msg_crypto);
} else {
if (i != GMIME_MULTIPART_ENCRYPTED_VERSION) {
_notmuch_database_log (notmuch_message_get_database (message),
@@ -434,14 +450,16 @@ _index_mime_part (notmuch_message_t *message,
continue;
}
child = g_mime_multipart_get_part (multipart, i);
- status = _notmuch_message_crypto_potential_payload (msg_crypto, child, part, i);
- if (status)
- _notmuch_database_log (notmuch_message_get_database (message),
- "Warning: failed to mark the potential cryptographic payload (%s).\n",
- notmuch_status_to_string (status));
- _index_mime_part (message, indexopts, child, msg_crypto);
+ GMimeObject *toindex = child;
+ if (_notmuch_message_crypto_potential_payload (msg_crypto, child, part, i) &&
+ msg_crypto->decryption_status == NOTMUCH_MESSAGE_DECRYPTED_FULL) {
+ toindex = _notmuch_repair_crypto_payload_skip_legacy_display (child);
+ if (toindex != child)
+ notmuch_message_add_property (message, "index.repaired", "skip-protected-headers-legacy-display");
+ }
+ _index_mime_part (message, indexopts, toindex, msg_crypto);
}
- return;
+ goto DONE;
}
if (GMIME_IS_MESSAGE_PART (part)) {
@@ -451,21 +469,25 @@ _index_mime_part (notmuch_message_t *message,
_index_mime_part (message, indexopts, g_mime_message_get_mime_part (mime_message), msg_crypto);
- return;
+ goto DONE;
+ }
+
+ if (GMIME_IS_APPLICATION_PKCS7_MIME (part)) {
+ _index_pkcs7_part (message, indexopts, part, msg_crypto);
+ goto DONE;
}
if (! (GMIME_IS_PART (part))) {
_notmuch_database_log (notmuch_message_get_database (message),
- "Warning: Not indexing unknown mime part: %s.\n",
- g_type_name (G_OBJECT_TYPE (part)));
- return;
+ "Warning: Not indexing unknown mime part: %s.\n",
+ g_type_name (G_OBJECT_TYPE (part)));
+ goto DONE;
}
disposition = g_mime_object_get_content_disposition (part);
if (disposition &&
strcasecmp (g_mime_content_disposition_get_disposition (disposition),
- GMIME_DISPOSITION_ATTACHMENT) == 0)
- {
+ GMIME_DISPOSITION_ATTACHMENT) == 0) {
const char *filename = g_mime_part_get_filename (GMIME_PART (part));
_notmuch_message_add_term (message, "tag", "attachment");
@@ -473,7 +495,7 @@ _index_mime_part (notmuch_message_t *message,
/* XXX: Would be nice to call out to something here to parse
* the attachment into text and then index that. */
- return;
+ goto DONE;
}
byte_array = g_byte_array_new ();
@@ -519,6 +541,9 @@ _index_mime_part (notmuch_message_t *message,
free (body);
}
+ DONE:
+ if (repaired_part)
+ g_object_unref (repaired_part);
}
/* descend (if desired) into the cleartext part of an encrypted MIME
@@ -526,15 +551,15 @@ _index_mime_part (notmuch_message_t *message,
static void
_index_encrypted_mime_part (notmuch_message_t *message,
notmuch_indexopts_t *indexopts,
- GMimeMultipartEncrypted *encrypted_data,
+ GMimeObject *encrypted_data,
_notmuch_message_crypto_t *msg_crypto)
{
notmuch_status_t status;
GError *err = NULL;
- notmuch_database_t * notmuch = NULL;
+ notmuch_database_t *notmuch = NULL;
GMimeObject *clear = NULL;
- if (!indexopts || (notmuch_indexopts_get_decrypt_policy (indexopts) == NOTMUCH_DECRYPT_FALSE))
+ if (! indexopts || (notmuch_indexopts_get_decrypt_policy (indexopts) == NOTMUCH_DECRYPT_FALSE))
return;
notmuch = notmuch_message_get_database (message);
@@ -544,15 +569,15 @@ _index_encrypted_mime_part (notmuch_message_t *message,
bool get_sk = (notmuch_indexopts_get_decrypt_policy (indexopts) == NOTMUCH_DECRYPT_TRUE);
clear = _notmuch_crypto_decrypt (&attempted, notmuch_indexopts_get_decrypt_policy (indexopts),
message, encrypted_data, get_sk ? &decrypt_result : NULL, &err);
- if (!attempted)
+ if (! attempted)
return;
- if (err || !clear) {
+ if (err || ! clear) {
if (decrypt_result)
g_object_unref (decrypt_result);
if (err) {
_notmuch_database_log (notmuch, "Failed to decrypt during indexing. (%d:%d) [%s]\n",
err->domain, err->code, err->message);
- g_error_free(err);
+ g_error_free (err);
} else {
_notmuch_database_log (notmuch, "Failed to decrypt during indexing. (unknown error)\n");
}
@@ -577,8 +602,14 @@ _index_encrypted_mime_part (notmuch_message_t *message,
}
g_object_unref (decrypt_result);
}
- status = _notmuch_message_crypto_potential_payload (msg_crypto, clear, GMIME_OBJECT (encrypted_data), GMIME_MULTIPART_ENCRYPTED_CONTENT);
- _index_mime_part (message, indexopts, clear, msg_crypto);
+ GMimeObject *toindex = clear;
+ if (_notmuch_message_crypto_potential_payload (msg_crypto, clear, encrypted_data, GMIME_MULTIPART_ENCRYPTED_CONTENT) &&
+ msg_crypto->decryption_status == NOTMUCH_MESSAGE_DECRYPTED_FULL) {
+ toindex = _notmuch_repair_crypto_payload_skip_legacy_display (clear);
+ if (toindex != clear)
+ notmuch_message_add_property (message, "index.repaired", "skip-protected-headers-legacy-display");
+ }
+ _index_mime_part (message, indexopts, toindex, msg_crypto);
g_object_unref (clear);
status = notmuch_message_add_property (message, "index.decryption", "success");
@@ -588,6 +619,57 @@ _index_encrypted_mime_part (notmuch_message_t *message,
}
+static void
+_index_pkcs7_part (notmuch_message_t *message,
+ notmuch_indexopts_t *indexopts,
+ GMimeObject *part,
+ _notmuch_message_crypto_t *msg_crypto)
+{
+ GMimeApplicationPkcs7Mime *pkcs7;
+ GMimeSecureMimeType p7type;
+ GMimeObject *mimeobj = NULL;
+ GMimeSignatureList *sigs = NULL;
+ GError *err = NULL;
+ notmuch_database_t *notmuch = NULL;
+
+ pkcs7 = GMIME_APPLICATION_PKCS7_MIME (part);
+ p7type = g_mime_application_pkcs7_mime_get_smime_type (pkcs7);
+ notmuch = notmuch_message_get_database (message);
+ _index_content_type (message, part);
+
+ if (p7type == GMIME_SECURE_MIME_TYPE_SIGNED_DATA) {
+ sigs = g_mime_application_pkcs7_mime_verify (pkcs7, GMIME_VERIFY_NONE, &mimeobj, &err);
+ if (sigs == NULL) {
+ _notmuch_database_log (notmuch, "Failed to verify PKCS#7 SignedData during indexing. (%d:%d) [%s]\n",
+ err->domain, err->code, err->message);
+ g_error_free (err);
+ goto DONE;
+ }
+ _notmuch_message_add_term (message, "tag", "signed");
+ GMimeObject *toindex = mimeobj;
+ if (_notmuch_message_crypto_potential_payload (msg_crypto, mimeobj, part, 0) &&
+ msg_crypto->decryption_status == NOTMUCH_MESSAGE_DECRYPTED_FULL) {
+ toindex = _notmuch_repair_crypto_payload_skip_legacy_display (mimeobj);
+ if (toindex != mimeobj)
+ notmuch_message_add_property (message, "index.repaired", "skip-protected-headers-legacy-display");
+ }
+ _index_mime_part (message, indexopts, toindex, msg_crypto);
+ } else if (p7type == GMIME_SECURE_MIME_TYPE_ENVELOPED_DATA) {
+ _notmuch_message_add_term (message, "tag", "encrypted");
+ _index_encrypted_mime_part (message, indexopts,
+ part,
+ msg_crypto);
+ } else {
+ _notmuch_database_log (notmuch, "Cannot currently handle PKCS#7 smime-type '%s'\n",
+ g_mime_object_get_content_type_parameter (part, "smime-type"));
+ }
+ DONE:
+ if (mimeobj)
+ g_object_unref (mimeobj);
+ if (sigs)
+ g_object_unref (sigs);
+}
+
static notmuch_status_t
_notmuch_message_index_user_headers (notmuch_message_t *message, GMimeMessage *mime_message)
{
diff --git a/lib/indexopts.c b/lib/indexopts.c
index b78a57b6..82a0026f 100644
--- a/lib/indexopts.c
+++ b/lib/indexopts.c
@@ -24,25 +24,26 @@ notmuch_indexopts_t *
notmuch_database_get_default_indexopts (notmuch_database_t *db)
{
notmuch_indexopts_t *ret = talloc_zero (db, notmuch_indexopts_t);
- if (!ret)
+
+ if (! ret)
return ret;
ret->crypto.decrypt = NOTMUCH_DECRYPT_AUTO;
- char * decrypt_policy;
+ char *decrypt_policy;
notmuch_status_t err = notmuch_database_get_config (db, "index.decrypt", &decrypt_policy);
if (err)
- return ret;
+ return NULL;
if (decrypt_policy) {
- if ((!(strcasecmp(decrypt_policy, "true"))) ||
- (!(strcasecmp(decrypt_policy, "yes"))) ||
- (!(strcasecmp(decrypt_policy, "1"))))
+ if ((! (strcasecmp (decrypt_policy, "true"))) ||
+ (! (strcasecmp (decrypt_policy, "yes"))) ||
+ (! (strcasecmp (decrypt_policy, "1"))))
notmuch_indexopts_set_decrypt_policy (ret, NOTMUCH_DECRYPT_TRUE);
- else if ((!(strcasecmp(decrypt_policy, "false"))) ||
- (!(strcasecmp(decrypt_policy, "no"))) ||
- (!(strcasecmp(decrypt_policy, "0"))))
+ else if ((! (strcasecmp (decrypt_policy, "false"))) ||
+ (! (strcasecmp (decrypt_policy, "no"))) ||
+ (! (strcasecmp (decrypt_policy, "0"))))
notmuch_indexopts_set_decrypt_policy (ret, NOTMUCH_DECRYPT_FALSE);
- else if (!strcasecmp(decrypt_policy, "nostash"))
+ else if (! strcasecmp (decrypt_policy, "nostash"))
notmuch_indexopts_set_decrypt_policy (ret, NOTMUCH_DECRYPT_NOSTASH);
}
@@ -54,7 +55,7 @@ notmuch_status_t
notmuch_indexopts_set_decrypt_policy (notmuch_indexopts_t *indexopts,
notmuch_decryption_policy_t decrypt_policy)
{
- if (!indexopts)
+ if (! indexopts)
return NOTMUCH_STATUS_NULL_POINTER;
indexopts->crypto.decrypt = decrypt_policy;
return NOTMUCH_STATUS_SUCCESS;
@@ -63,7 +64,7 @@ notmuch_indexopts_set_decrypt_policy (notmuch_indexopts_t *indexopts,
notmuch_decryption_policy_t
notmuch_indexopts_get_decrypt_policy (const notmuch_indexopts_t *indexopts)
{
- if (!indexopts)
+ if (! indexopts)
return false;
return indexopts->crypto.decrypt;
}
diff --git a/lib/message-file.c b/lib/message-file.c
index 24c5fda4..311bd478 100644
--- a/lib/message-file.c
+++ b/lib/message-file.c
@@ -64,21 +64,37 @@ _notmuch_message_file_open_ctx (notmuch_database_t *notmuch,
if (unlikely (message == NULL))
return NULL;
- message->filename = talloc_strdup (message, filename);
+ const char *prefix = notmuch_database_get_path (notmuch);
+ if (prefix == NULL)
+ goto FAIL;
+
+ if (*filename == '/') {
+ if (strncmp (filename, prefix, strlen(prefix)) != 0) {
+ _notmuch_database_log (notmuch, "Error opening %s: path outside mail root\n",
+ filename);
+ errno = 0;
+ goto FAIL;
+ }
+ message->filename = talloc_strdup (message, filename);
+ } else {
+ message->filename = talloc_asprintf(message, "%s/%s", prefix, filename);
+ }
+
if (message->filename == NULL)
goto FAIL;
talloc_set_destructor (message, _notmuch_message_file_destructor);
- message->stream = g_mime_stream_gzfile_open (filename);
+ message->stream = g_mime_stream_gzfile_open (message->filename);
if (message->stream == NULL)
goto FAIL;
return message;
FAIL:
- _notmuch_database_log (notmuch, "Error opening %s: %s\n",
- filename, strerror (errno));
+ if (errno)
+ _notmuch_database_log (notmuch, "Error opening %s: %s\n",
+ filename, strerror (errno));
_notmuch_message_file_close (message);
return NULL;
@@ -110,7 +126,7 @@ _is_mbox (GMimeStream *stream)
bool ret = false;
/* Is this mbox? */
- if (g_mime_stream_read (stream, from_buf, sizeof (from_buf)) == sizeof(from_buf) &&
+ if (g_mime_stream_read (stream, from_buf, sizeof (from_buf)) == sizeof (from_buf) &&
strncmp (from_buf, "From ", 5) == 0)
ret = true;
@@ -201,7 +217,8 @@ _notmuch_message_file_get_mime_message (notmuch_message_file_t *message,
*/
static char *
-_extend_header (char *combined, const char *value) {
+_extend_header (char *combined, const char *value)
+{
char *decoded;
decoded = g_mime_utils_header_decode_text (NULL, value);
@@ -226,7 +243,7 @@ _extend_header (char *combined, const char *value) {
} else {
combined = decoded;
}
- DONE:
+ DONE:
return combined;
}
@@ -242,7 +259,7 @@ _notmuch_message_file_get_combined_header (notmuch_message_file_t *message,
return NULL;
- for (int i=0; i < g_mime_header_list_get_count (headers); i++) {
+ for (int i = 0; i < g_mime_header_list_get_count (headers); i++) {
const char *value;
GMimeHeader *g_header = g_mime_header_list_get_header_at (headers, i);
@@ -264,7 +281,7 @@ _notmuch_message_file_get_combined_header (notmuch_message_file_t *message,
const char *
_notmuch_message_file_get_header (notmuch_message_file_t *message,
- const char *header)
+ const char *header)
{
const char *value;
char *decoded;
@@ -366,7 +383,7 @@ _notmuch_message_file_get_headers (notmuch_message_file_t *message_file,
message_id = talloc_asprintf (message_file, "notmuch-sha1-%s", sha1);
free (sha1);
}
- DONE:
+ DONE:
if (ret == NOTMUCH_STATUS_SUCCESS) {
if (from_out)
*from_out = from;
diff --git a/lib/message-id.c b/lib/message-id.c
index e71ce9f4..54012354 100644
--- a/lib/message-id.c
+++ b/lib/message-id.c
@@ -27,7 +27,7 @@ skip_space_and_comments (const char **str)
} else if (*s == ')') {
nesting--;
} else if (*s == '\\') {
- if (*(s+1))
+ if (*(s + 1))
s++;
}
s++;
@@ -90,7 +90,7 @@ _notmuch_message_id_parse (void *ctx, const char *message_id, const char **next)
for (r = result, len = strlen (r); *r; r++, len--)
if (*r == ' ' || *r == '\t')
- memmove (r, r+1, len);
+ memmove (r, r + 1, len);
}
return result;
diff --git a/lib/message-property.cc b/lib/message-property.cc
index 710ba046..ecf7e140 100644
--- a/lib/message-property.cc
+++ b/lib/message-property.cc
@@ -115,7 +115,7 @@ notmuch_status_t
_notmuch_message_remove_all_properties (notmuch_message_t *message, const char *key, bool prefix)
{
notmuch_status_t status;
- const char * term_prefix;
+ const char *term_prefix;
status = _notmuch_database_ensure_writable (notmuch_message_get_database (message));
if (status)
@@ -150,6 +150,7 @@ notmuch_message_properties_t *
notmuch_message_get_properties (notmuch_message_t *message, const char *key, notmuch_bool_t exact)
{
notmuch_string_map_t *map;
+
map = _notmuch_message_property_map (message);
return _notmuch_string_map_iterator_create (map, key, exact);
}
diff --git a/lib/message.cc b/lib/message.cc
index 9e1005a3..fca99082 100644
--- a/lib/message.cc
+++ b/lib/message.cc
@@ -69,10 +69,10 @@ struct maildir_flag_tag {
/* ASCII ordered table of Maildir flags and associated tags */
static struct maildir_flag_tag flag2tag[] = {
- { 'D', "draft", false},
- { 'F', "flagged", false},
- { 'P', "passed", false},
- { 'R', "replied", false},
+ { 'D', "draft", false },
+ { 'F', "flagged", false },
+ { 'P', "passed", false },
+ { 'R', "replied", false },
{ 'S', "unread", true }
};
@@ -90,6 +90,18 @@ _notmuch_message_destructor (notmuch_message_t *message)
return 0;
}
+#define LOG_XAPIAN_EXCEPTION(message, error) _log_xapian_exception (__location__, message, error)
+
+static void
+_log_xapian_exception (const char *where, notmuch_message_t *message, const Xapian::Error error) {
+ notmuch_database_t *notmuch = notmuch_message_get_database (message);
+ _notmuch_database_log (notmuch,
+ "A Xapian exception occurred at %s: %s\n",
+ where,
+ error.get_msg ().c_str ());
+ notmuch->exception_reported = true;
+}
+
static notmuch_message_t *
_notmuch_message_create_for_document (const void *talloc_owner,
notmuch_database_t *notmuch,
@@ -263,7 +275,7 @@ _notmuch_message_create_for_message_id (notmuch_database_t *notmuch,
return NULL;
}
- if (notmuch->mode == NOTMUCH_DATABASE_MODE_READ_ONLY)
+ if (_notmuch_database_mode (notmuch) == NOTMUCH_DATABASE_MODE_READ_ONLY)
INTERNAL_ERROR ("Failure to ensure database is writable.");
try {
@@ -274,8 +286,8 @@ _notmuch_message_create_for_message_id (notmuch_database_t *notmuch,
doc_id = _notmuch_database_generate_doc_id (notmuch);
} catch (const Xapian::Error &error) {
- _notmuch_database_log(notmuch_message_get_database (message), "A Xapian exception occurred creating message: %s\n",
- error.get_msg().c_str());
+ _notmuch_database_log (notmuch_message_get_database (message), "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;
@@ -306,10 +318,10 @@ _notmuch_message_get_term (notmuch_message_t *message,
return NULL;
const std::string &term = *i;
- if (strncmp (term.c_str(), prefix, prefix_len))
+ if (strncmp (term.c_str (), prefix, prefix_len))
return NULL;
- value = talloc_strdup (message, term.c_str() + prefix_len);
+ value = talloc_strdup (message, term.c_str () + prefix_len);
#if DEBUG_DATABASE_SANITY
i++;
@@ -350,32 +362,32 @@ _notmuch_message_ensure_metadata (notmuch_message_t *message, void *field)
return;
const char *thread_prefix = _find_prefix ("thread"),
- *tag_prefix = _find_prefix ("tag"),
- *id_prefix = _find_prefix ("id"),
- *type_prefix = _find_prefix ("type"),
- *filename_prefix = _find_prefix ("file-direntry"),
- *property_prefix = _find_prefix ("property"),
- *reference_prefix = _find_prefix ("reference"),
- *replyto_prefix = _find_prefix ("replyto");
+ *tag_prefix = _find_prefix ("tag"),
+ *id_prefix = _find_prefix ("id"),
+ *type_prefix = _find_prefix ("type"),
+ *filename_prefix = _find_prefix ("file-direntry"),
+ *property_prefix = _find_prefix ("property"),
+ *reference_prefix = _find_prefix ("reference"),
+ *replyto_prefix = _find_prefix ("replyto");
/* We do this all in a single pass because Xapian decompresses the
* term list every time you iterate over it. Thus, while this is
* slightly more costly than looking up individual fields if only
* one field of the message object is actually used, it's a huge
* win as more fields are used. */
- for (int count=0; count < 3; count++) {
+ for (int count = 0; count < 3; count++) {
try {
i = message->doc.termlist_begin ();
end = message->doc.termlist_end ();
/* Get thread */
- if (!message->thread_id)
+ if (! message->thread_id)
message->thread_id =
_notmuch_message_get_term (message, i, end, thread_prefix);
/* Get tags */
assert (strcmp (thread_prefix, tag_prefix) < 0);
- if (!message->tag_list) {
+ if (! message->tag_list) {
message->tag_list =
_notmuch_database_get_terms_with_prefix (message, i, end,
tag_prefix);
@@ -384,7 +396,7 @@ _notmuch_message_ensure_metadata (notmuch_message_t *message, void *field)
/* Get id */
assert (strcmp (tag_prefix, id_prefix) < 0);
- if (!message->message_id)
+ if (! message->message_id)
message->message_id =
_notmuch_message_get_term (message, i, end, id_prefix);
@@ -407,7 +419,7 @@ _notmuch_message_ensure_metadata (notmuch_message_t *message, void *field)
* expand them to full file names when needed in
* _notmuch_message_ensure_filename_list. */
assert (strcmp (type_prefix, filename_prefix) < 0);
- if (!message->filename_term_list && !message->filename_list)
+ if (! message->filename_term_list && ! message->filename_list)
message->filename_term_list =
_notmuch_database_get_terms_with_prefix (message, i, end,
filename_prefix);
@@ -415,14 +427,14 @@ _notmuch_message_ensure_metadata (notmuch_message_t *message, void *field)
/* Get property terms. Mimic the setup with filenames above */
assert (strcmp (filename_prefix, property_prefix) < 0);
- if (!message->property_map && !message->property_term_list)
+ if (! message->property_map && ! message->property_term_list)
message->property_term_list =
_notmuch_database_get_terms_with_prefix (message, i, end,
- property_prefix);
+ property_prefix);
/* get references */
assert (strcmp (property_prefix, reference_prefix) < 0);
- if (!message->reference_list) {
+ if (! message->reference_list) {
message->reference_list =
_notmuch_database_get_terms_with_prefix (message, i, end,
reference_prefix);
@@ -430,14 +442,14 @@ _notmuch_message_ensure_metadata (notmuch_message_t *message, void *field)
/* Get reply to */
assert (strcmp (property_prefix, replyto_prefix) < 0);
- if (!message->in_reply_to)
+ if (! message->in_reply_to)
message->in_reply_to =
_notmuch_message_get_term (message, i, end, replyto_prefix);
/* It's perfectly valid for a message to have no In-Reply-To
* header. For these cases, we return an empty string. */
- if (!message->in_reply_to)
+ if (! message->in_reply_to)
message->in_reply_to = talloc_strdup (message, "");
/* all the way without an exception */
@@ -447,9 +459,6 @@ _notmuch_message_ensure_metadata (notmuch_message_t *message, void *field)
if (status != NOTMUCH_STATUS_SUCCESS)
INTERNAL_ERROR ("unhandled error from notmuch_database_reopen: %s\n",
notmuch_status_to_string (status));
- } catch (const Xapian::Error &error) {
- INTERNAL_ERROR ("A Xapian exception occurred fetching message metadata: %s\n",
- error.get_msg().c_str());
}
}
message->last_view = message->notmuch->view;
@@ -507,8 +516,14 @@ _notmuch_message_get_doc_id (notmuch_message_t *message)
const char *
notmuch_message_get_message_id (notmuch_message_t *message)
{
- _notmuch_message_ensure_metadata (message, message->message_id);
- if (!message->message_id)
+ try {
+ _notmuch_message_ensure_metadata (message, message->message_id);
+ } catch (const Xapian::Error &error) {
+ LOG_XAPIAN_EXCEPTION (message, error);
+ return NULL;
+ }
+
+ if (! message->message_id)
INTERNAL_ERROR ("Message with document ID of %u has no message ID.\n",
message->doc_id);
return message->message_id;
@@ -553,13 +568,11 @@ notmuch_message_get_header (notmuch_message_t *message, const char *header)
* it could just mean we didn't record the header. */
if ((message->notmuch->features &
NOTMUCH_FEATURE_FROM_SUBJECT_ID_VALUES) ||
- ! value.empty())
+ ! value.empty ())
return talloc_strdup (message, value.c_str ());
} catch (Xapian::Error &error) {
- _notmuch_database_log(notmuch_message_get_database (message), "A Xapian exception occurred when reading header: %s\n",
- error.get_msg().c_str());
- message->notmuch->exception_reported = true;
+ LOG_XAPIAN_EXCEPTION (message, error);
return NULL;
}
}
@@ -589,8 +602,13 @@ _notmuch_message_get_in_reply_to (notmuch_message_t *message)
const char *
notmuch_message_get_thread_id (notmuch_message_t *message)
{
- _notmuch_message_ensure_metadata (message, message->thread_id);
- if (!message->thread_id)
+ try {
+ _notmuch_message_ensure_metadata (message, message->thread_id);
+ } catch (Xapian::Error &error) {
+ LOG_XAPIAN_EXCEPTION (message, error);
+ return NULL;
+ }
+ if (! message->thread_id)
INTERNAL_ERROR ("Message with document ID of %u has no thread ID.\n",
message->doc_id);
return message->thread_id;
@@ -604,7 +622,8 @@ _notmuch_message_add_reply (notmuch_message_t *message,
}
size_t
-_notmuch_message_get_thread_depth (notmuch_message_t *message) {
+_notmuch_message_get_thread_depth (notmuch_message_t *message)
+{
return message->thread_depth;
}
@@ -618,7 +637,7 @@ _notmuch_message_label_depths (notmuch_message_t *message,
notmuch_messages_valid (messages);
notmuch_messages_move_to_next (messages)) {
notmuch_message_t *child = notmuch_messages_get (messages);
- _notmuch_message_label_depths (child, depth+1);
+ _notmuch_message_label_depths (child, depth + 1);
}
}
@@ -730,7 +749,7 @@ _notmuch_message_remove_indexed_terms (notmuch_message_t *message)
type_prefix = _find_prefix ("type");
/* Make sure we have the data to restore to Xapian*/
- _notmuch_message_ensure_metadata (message,NULL);
+ _notmuch_message_ensure_metadata (message, NULL);
/* Empirically, it turns out to be faster to remove all the terms,
* and add back the ones we want. */
@@ -750,11 +769,11 @@ _notmuch_message_remove_indexed_terms (notmuch_message_t *message)
const char *tag = notmuch_tags_get (tags);
- if (STRNCMP_LITERAL (tag, "encrypted") != 0 &&
- STRNCMP_LITERAL (tag, "signed") != 0 &&
- STRNCMP_LITERAL (tag, "attachment") != 0) {
+ if (strcmp (tag, "encrypted") != 0 &&
+ strcmp (tag, "signed") != 0 &&
+ strcmp (tag, "attachment") != 0) {
std::string term = tag_prefix + tag;
- message->doc.add_term(term);
+ message->doc.add_term (term);
}
}
@@ -764,10 +783,10 @@ _notmuch_message_remove_indexed_terms (notmuch_message_t *message)
for (list = notmuch_message_get_properties (message, "", false);
notmuch_message_properties_valid (list); notmuch_message_properties_move_to_next (list)) {
std::string term = property_prefix +
- notmuch_message_properties_key(list) + "=" +
- notmuch_message_properties_value(list);
+ notmuch_message_properties_key (list) + "=" +
+ notmuch_message_properties_value (list);
- message->doc.add_term(term);
+ message->doc.add_term (term);
}
notmuch_message_properties_destroy (list);
@@ -777,7 +796,8 @@ _notmuch_message_remove_indexed_terms (notmuch_message_t *message)
/* Return true if p points at "new" or "cur". */
-static bool is_maildir (const char *p)
+static bool
+is_maildir (const char *p)
{
return strcmp (p, "cur") == 0 || strcmp (p, "new") == 0;
}
@@ -972,7 +992,7 @@ _notmuch_message_remove_filename (notmuch_message_t *message,
status = _notmuch_database_filename_to_direntry (
local, message->notmuch, filename, NOTMUCH_FIND_LOOKUP, &direntry);
- if (status || !direntry)
+ if (status || ! direntry)
return status;
/* Unlink this file from its parent directory. */
@@ -1041,7 +1061,7 @@ _notmuch_message_ensure_filename_list (notmuch_message_t *message)
message->filename_list = _notmuch_string_list_create (message);
node = message->filename_term_list->head;
- if (!node) {
+ if (! node) {
/* 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.
@@ -1102,14 +1122,18 @@ _notmuch_message_ensure_filename_list (notmuch_message_t *message)
const char *
notmuch_message_get_filename (notmuch_message_t *message)
{
- _notmuch_message_ensure_filename_list (message);
+ try {
+ _notmuch_message_ensure_filename_list (message);
+ } catch (Xapian::Error &error) {
+ LOG_XAPIAN_EXCEPTION (message, error);
+ return NULL;
+ }
if (message->filename_list == NULL)
return NULL;
if (message->filename_list->head == NULL ||
- message->filename_list->head->string == NULL)
- {
+ message->filename_list->head->string == NULL) {
INTERNAL_ERROR ("message with no filename");
}
@@ -1119,7 +1143,12 @@ notmuch_message_get_filename (notmuch_message_t *message)
notmuch_filenames_t *
notmuch_message_get_filenames (notmuch_message_t *message)
{
- _notmuch_message_ensure_filename_list (message);
+ try {
+ _notmuch_message_ensure_filename_list (message);
+ } catch (Xapian::Error &error) {
+ LOG_XAPIAN_EXCEPTION (message, error);
+ return NULL;
+ }
return _notmuch_filenames_create (message, message->filename_list);
}
@@ -1127,20 +1156,50 @@ notmuch_message_get_filenames (notmuch_message_t *message)
int
notmuch_message_count_files (notmuch_message_t *message)
{
- _notmuch_message_ensure_filename_list (message);
+ try {
+ _notmuch_message_ensure_filename_list (message);
+ } catch (Xapian::Error &error) {
+ LOG_XAPIAN_EXCEPTION (message, error);
+ return -1;
+ }
return _notmuch_string_list_length (message->filename_list);
}
+notmuch_status_t
+notmuch_message_get_flag_st (notmuch_message_t *message,
+ notmuch_message_flag_t flag,
+ notmuch_bool_t *is_set)
+{
+ if (! is_set)
+ return NOTMUCH_STATUS_NULL_POINTER;
+
+ try {
+ if (flag == NOTMUCH_MESSAGE_FLAG_GHOST &&
+ ! NOTMUCH_TEST_BIT (message->lazy_flags, flag))
+ _notmuch_message_ensure_metadata (message, NULL);
+ } catch (Xapian::Error &error) {
+ LOG_XAPIAN_EXCEPTION (message, error);
+ return NOTMUCH_STATUS_XAPIAN_EXCEPTION;
+ }
+
+ *is_set = NOTMUCH_TEST_BIT (message->flags, flag);
+ return NOTMUCH_STATUS_SUCCESS;
+}
+
notmuch_bool_t
notmuch_message_get_flag (notmuch_message_t *message,
notmuch_message_flag_t flag)
{
- if (flag == NOTMUCH_MESSAGE_FLAG_GHOST &&
- ! NOTMUCH_TEST_BIT (message->lazy_flags, flag))
- _notmuch_message_ensure_metadata (message, NULL);
+ notmuch_bool_t is_set;
+ notmuch_status_t status;
+
+ status = notmuch_message_get_flag_st (message, flag, &is_set);
- return NOTMUCH_TEST_BIT (message->flags, flag);
+ if (status)
+ return FALSE;
+ else
+ return is_set;
}
void
@@ -1162,9 +1221,7 @@ notmuch_message_get_date (notmuch_message_t *message)
try {
value = message->doc.get_value (NOTMUCH_VALUE_TIMESTAMP);
} catch (Xapian::Error &error) {
- _notmuch_database_log(notmuch_message_get_database (message), "A Xapian exception occurred when reading date: %s\n",
- error.get_msg().c_str());
- message->notmuch->exception_reported = true;
+ LOG_XAPIAN_EXCEPTION (message, error);
return 0;
}
@@ -1179,7 +1236,12 @@ notmuch_message_get_tags (notmuch_message_t *message)
{
notmuch_tags_t *tags;
- _notmuch_message_ensure_metadata (message, message->tag_list);
+ try {
+ _notmuch_message_ensure_metadata (message, message->tag_list);
+ } catch (Xapian::Error &error) {
+ LOG_XAPIAN_EXCEPTION (message, error);
+ return NULL;
+ }
tags = _notmuch_tags_create (message, message->tag_list);
/* _notmuch_tags_create steals the reference to the tag_list, but
@@ -1188,7 +1250,7 @@ notmuch_message_get_tags (notmuch_message_t *message)
* possible to modify the message tags (which talloc_unlink's the
* current list from the message) while still iterating because
* the iterator will keep the current list alive. */
- if (!talloc_reference (message, message->tag_list))
+ if (! talloc_reference (message, message->tag_list))
return NULL;
return tags;
@@ -1202,11 +1264,11 @@ _notmuch_message_get_author (notmuch_message_t *message)
void
_notmuch_message_set_author (notmuch_message_t *message,
- const char *author)
+ const char *author)
{
if (message->author)
- talloc_free(message->author);
- message->author = talloc_strdup(message, author);
+ talloc_free (message->author);
+ message->author = talloc_strdup (message, author);
return;
}
@@ -1260,9 +1322,7 @@ _notmuch_message_upgrade_last_mod (notmuch_message_t *message)
void
_notmuch_message_sync (notmuch_message_t *message)
{
- Xapian::WritableDatabase *db;
-
- if (message->notmuch->mode == NOTMUCH_DATABASE_MODE_READ_ONLY)
+ if (_notmuch_database_mode (message->notmuch) == NOTMUCH_DATABASE_MODE_READ_ONLY)
return;
if (! message->modified)
@@ -1280,8 +1340,8 @@ _notmuch_message_sync (notmuch_message_t *message)
_notmuch_database_new_revision (
message->notmuch)));
- db = static_cast <Xapian::WritableDatabase *> (message->notmuch->xapian_db);
- db->replace_document (message->doc_id, message->doc);
+ message->notmuch->writable_xapian_db->
+ replace_document (message->doc_id, message->doc);
message->modified = false;
}
@@ -1291,7 +1351,6 @@ notmuch_status_t
_notmuch_message_delete (notmuch_message_t *message)
{
notmuch_status_t status;
- Xapian::WritableDatabase *db;
const char *mid, *tid, *query_string;
notmuch_message_t *ghost;
notmuch_private_status_t private_status;
@@ -1308,8 +1367,7 @@ _notmuch_message_delete (notmuch_message_t *message)
if (status)
return status;
- db = static_cast <Xapian::WritableDatabase *> (notmuch->xapian_db);
- db->delete_document (message->doc_id);
+ message->notmuch->writable_xapian_db->delete_document (message->doc_id);
/* if this was a ghost to begin with, we are done */
private_status = _notmuch_message_has_term (message, "type", "ghost", &is_ghost);
@@ -1339,8 +1397,8 @@ _notmuch_message_delete (notmuch_message_t *message)
_notmuch_message_sync (ghost);
} else if (private_status == NOTMUCH_PRIVATE_STATUS_SUCCESS) {
/* this is deeply weird, and we should not have gotten
- into this state. is there a better error message to
- return here? */
+ * into this state. is there a better error message to
+ * return here? */
status = NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID;
}
@@ -1358,8 +1416,8 @@ _notmuch_message_delete (notmuch_message_t *message)
message = notmuch_messages_get (messages);
status = _notmuch_message_delete (message);
if (status) /* we'll report the last failure we see;
- * if there is more than one failure, we
- * forget about previous ones */
+ * if there is more than one failure, we
+ * forget about previous ones */
last_error = status;
notmuch_message_destroy (message);
notmuch_messages_move_to_next (messages);
@@ -1535,7 +1593,7 @@ _notmuch_message_has_term (notmuch_message_t *message,
Xapian::TermIterator i = message->doc.termlist_begin ();
i.skip_to (term);
if (i != message->doc.termlist_end () &&
- !strcmp ((*i).c_str (), term))
+ ! strcmp ((*i).c_str (), term))
out = true;
} catch (Xapian::Error &error) {
status = NOTMUCH_PRIVATE_STATUS_XAPIAN_EXCEPTION;
@@ -1552,24 +1610,31 @@ notmuch_message_add_tag (notmuch_message_t *message, const char *tag)
notmuch_private_status_t private_status;
notmuch_status_t status;
- status = _notmuch_database_ensure_writable (message->notmuch);
- if (status)
- return status;
+ try {
+ status = _notmuch_database_ensure_writable (message->notmuch);
+ if (status)
+ return status;
- if (tag == NULL)
- return NOTMUCH_STATUS_NULL_POINTER;
+ if (tag == NULL)
+ return NOTMUCH_STATUS_NULL_POINTER;
- if (strlen (tag) > NOTMUCH_TAG_MAX)
- return NOTMUCH_STATUS_TAG_TOO_LONG;
+ if (strlen (tag) > NOTMUCH_TAG_MAX)
+ return NOTMUCH_STATUS_TAG_TOO_LONG;
- private_status = _notmuch_message_add_term (message, "tag", tag);
- if (private_status) {
- INTERNAL_ERROR ("_notmuch_message_add_term return unexpected value: %d\n",
- private_status);
- }
+ private_status = _notmuch_message_add_term (message, "tag", tag);
+ if (private_status) {
+ return COERCE_STATUS (private_status,
+ "_notmuch_message_remove_term return unexpected value: %d\n",
+ private_status);
+ }
- if (! message->frozen)
- _notmuch_message_sync (message);
+ if (! message->frozen)
+ _notmuch_message_sync (message);
+
+ } catch (Xapian::Error &error) {
+ LOG_XAPIAN_EXCEPTION (message, error);
+ return NOTMUCH_STATUS_XAPIAN_EXCEPTION;
+ }
return NOTMUCH_STATUS_SUCCESS;
}
@@ -1580,24 +1645,30 @@ notmuch_message_remove_tag (notmuch_message_t *message, const char *tag)
notmuch_private_status_t private_status;
notmuch_status_t status;
- status = _notmuch_database_ensure_writable (message->notmuch);
- if (status)
- return status;
+ try {
+ status = _notmuch_database_ensure_writable (message->notmuch);
+ if (status)
+ return status;
- if (tag == NULL)
- return NOTMUCH_STATUS_NULL_POINTER;
+ if (tag == NULL)
+ return NOTMUCH_STATUS_NULL_POINTER;
- if (strlen (tag) > NOTMUCH_TAG_MAX)
- return NOTMUCH_STATUS_TAG_TOO_LONG;
+ if (strlen (tag) > NOTMUCH_TAG_MAX)
+ return NOTMUCH_STATUS_TAG_TOO_LONG;
- private_status = _notmuch_message_remove_term (message, "tag", tag);
- if (private_status) {
- INTERNAL_ERROR ("_notmuch_message_remove_term return unexpected value: %d\n",
- private_status);
- }
+ private_status = _notmuch_message_remove_term (message, "tag", tag);
+ if (private_status) {
+ return COERCE_STATUS (private_status,
+ "_notmuch_message_remove_term return unexpected value: %d\n",
+ private_status);
+ }
- if (! message->frozen)
- _notmuch_message_sync (message);
+ if (! message->frozen)
+ _notmuch_message_sync (message);
+ } catch (Xapian::Error &error) {
+ LOG_XAPIAN_EXCEPTION (message, error);
+ return NOTMUCH_STATUS_XAPIAN_EXCEPTION;
+ }
return NOTMUCH_STATUS_SUCCESS;
}
@@ -1635,15 +1706,14 @@ _filename_is_in_maildir (const char *filename)
dir = slash + 1;
if (STRNCMP_LITERAL (dir, "cur/") == 0 ||
- STRNCMP_LITERAL (dir, "new/") == 0)
- {
+ STRNCMP_LITERAL (dir, "new/") == 0) {
return dir;
}
return NULL;
}
-static void
+static notmuch_status_t
_ensure_maildir_flags (notmuch_message_t *message, bool force)
{
const char *flags;
@@ -1658,11 +1728,12 @@ _ensure_maildir_flags (notmuch_message_t *message, bool force)
message->maildir_flags = NULL;
}
}
-
- for (filenames = notmuch_message_get_filenames (message);
+ filenames = notmuch_message_get_filenames (message);
+ if (! filenames)
+ return NOTMUCH_STATUS_XAPIAN_EXCEPTION;
+ for (;
notmuch_filenames_valid (filenames);
- notmuch_filenames_move_to_next (filenames))
- {
+ notmuch_filenames_move_to_next (filenames)) {
filename = notmuch_filenames_get (filenames);
dir = _filename_is_in_maildir (filename);
@@ -1686,13 +1757,37 @@ _ensure_maildir_flags (notmuch_message_t *message, bool force)
}
if (seen_maildir_info)
message->maildir_flags = combined_flags;
+ return NOTMUCH_STATUS_SUCCESS;
}
notmuch_bool_t
notmuch_message_has_maildir_flag (notmuch_message_t *message, char flag)
{
- _ensure_maildir_flags (message, false);
- return message->maildir_flags && (strchr (message->maildir_flags, flag) != NULL);
+ notmuch_status_t status;
+ notmuch_bool_t ret;
+ status = notmuch_message_has_maildir_flag_st (message, flag, &ret);
+ if (status)
+ return FALSE;
+
+ return ret;
+}
+
+notmuch_status_t
+notmuch_message_has_maildir_flag_st (notmuch_message_t *message,
+ char flag,
+ notmuch_bool_t *is_set)
+{
+ notmuch_status_t status;
+
+ if (! is_set)
+ return NOTMUCH_STATUS_NULL_POINTER;
+
+ status = _ensure_maildir_flags (message, false);
+ if (status)
+ return status;
+
+ *is_set = message->maildir_flags && (strchr (message->maildir_flags, flag) != NULL);
+ return NOTMUCH_STATUS_SUCCESS;
}
notmuch_status_t
@@ -1701,7 +1796,9 @@ notmuch_message_maildir_flags_to_tags (notmuch_message_t *message)
notmuch_status_t status;
unsigned i;
- _ensure_maildir_flags (message, true);
+ status = _ensure_maildir_flags (message, true);
+ if (status)
+ return status;
/* If none of the filenames have any maildir info field (not even
* an empty info with no flags set) then there's no information to
* go on, so do nothing. */
@@ -1712,11 +1809,10 @@ notmuch_message_maildir_flags_to_tags (notmuch_message_t *message)
if (status)
return status;
- for (i = 0; i < ARRAY_SIZE(flag2tag); i++) {
+ for (i = 0; i < ARRAY_SIZE (flag2tag); i++) {
if ((strchr (message->maildir_flags, flag2tag[i].flag) != NULL)
^
- flag2tag[i].inverse)
- {
+ flag2tag[i].inverse) {
status = notmuch_message_add_tag (message, flag2tag[i].tag);
} else {
status = notmuch_message_remove_tag (message, flag2tag[i].tag);
@@ -1751,8 +1847,7 @@ _get_maildir_flag_actions (notmuch_message_t *message,
/* First, find flags for all set tags. */
for (tags = notmuch_message_get_tags (message);
notmuch_tags_valid (tags);
- notmuch_tags_move_to_next (tags))
- {
+ notmuch_tags_move_to_next (tags)) {
tag = notmuch_tags_get (tags);
for (i = 0; i < ARRAY_SIZE (flag2tag); i++) {
@@ -1802,7 +1897,7 @@ _get_maildir_flag_actions (notmuch_message_t *message,
* non-ASCII ordering of flags), this function will return NULL
* (meaning that renaming would not be safe and should not occur).
*/
-static char*
+static char *
_new_maildir_filename (void *ctx,
const char *filename,
const char *flags_to_set,
@@ -1822,13 +1917,12 @@ _new_maildir_filename (void *ctx,
info = strstr (filename, ":2,");
if (info == NULL) {
- info = filename + strlen(filename);
+ info = filename + strlen (filename);
} else {
/* Loop through existing flags in filename. */
for (flags = info + 3, last_flag = 0;
*flags;
- last_flag = flag, flags++)
- {
+ last_flag = flag, flags++) {
flag = *flags;
/* Original flags not in ASCII order. Abort. */
@@ -1836,7 +1930,7 @@ _new_maildir_filename (void *ctx,
return NULL;
/* Non-ASCII flag. Abort. */
- if (flag > sizeof(flag_map) - 1)
+ if (flag > sizeof (flag_map) - 1)
return NULL;
/* Repeated flag value. Abort. */
@@ -1870,7 +1964,7 @@ _new_maildir_filename (void *ctx,
/* Messages in new/ without maildir info can be kept in new/ if no
* flags have changed. */
dir = (char *) _filename_is_in_maildir (filename);
- if (dir && STRNCMP_LITERAL (dir, "new/") == 0 && !*info && !flags_changed)
+ if (dir && STRNCMP_LITERAL (dir, "new/") == 0 && ! *info && ! flags_changed)
return talloc_strdup (ctx, filename);
filename_new = (char *) talloc_size (ctx,
@@ -1885,8 +1979,7 @@ _new_maildir_filename (void *ctx,
strcat (filename_new, ":2,");
s = filename_new + strlen (filename_new);
- for (i = 0; i < sizeof (flag_map); i++)
- {
+ for (i = 0; i < sizeof (flag_map); i++) {
if (flag_map[i]) {
*s = i;
s++;
@@ -1915,8 +2008,7 @@ notmuch_message_tags_to_maildir_flags (notmuch_message_t *message)
for (filenames = notmuch_message_get_filenames (message);
notmuch_filenames_valid (filenames);
- notmuch_filenames_move_to_next (filenames))
- {
+ notmuch_filenames_move_to_next (filenames)) {
filename = notmuch_filenames_get (filenames);
if (! _filename_is_in_maildir (filename))
@@ -1975,17 +2067,20 @@ notmuch_message_remove_all_tags (notmuch_message_t *message)
status = _notmuch_database_ensure_writable (message->notmuch);
if (status)
return status;
+ tags = notmuch_message_get_tags (message);
+ if (! tags)
+ return NOTMUCH_STATUS_XAPIAN_EXCEPTION;
- for (tags = notmuch_message_get_tags (message);
+ for (;
notmuch_tags_valid (tags);
- notmuch_tags_move_to_next (tags))
- {
+ notmuch_tags_move_to_next (tags)) {
tag = notmuch_tags_get (tags);
private_status = _notmuch_message_remove_term (message, "tag", tag);
if (private_status) {
- INTERNAL_ERROR ("_notmuch_message_remove_term return unexpected value: %d\n",
- private_status);
+ return COERCE_STATUS (private_status,
+ "_notmuch_message_remove_term return unexpected value: %d\n",
+ private_status);
}
}
@@ -2057,8 +2152,8 @@ _notmuch_message_ensure_property_map (notmuch_message_t *message)
const char *key;
char *value;
- value = strchr(node->string, '=');
- if (!value)
+ value = strchr (node->string, '=');
+ if (! value)
INTERNAL_ERROR ("malformed property term");
*value = '\0';
@@ -2105,9 +2200,11 @@ notmuch_message_reindex (notmuch_message_t *message,
/* Save in case we need to delete message */
orig_thread_id = notmuch_message_get_thread_id (message);
- if (!orig_thread_id) {
- /* XXX TODO: make up new error return? */
- INTERNAL_ERROR ("message without thread-id");
+ if (! orig_thread_id) {
+ /* the following is correct as long as there is only one reason
+ n_m_get_thread_id returns NULL
+ */
+ return NOTMUCH_STATUS_XAPIAN_EXCEPTION;
}
/* strdup it because the metadata may be invalidated */
@@ -2123,7 +2220,7 @@ notmuch_message_reindex (notmuch_message_t *message,
private_status = _notmuch_message_remove_indexed_terms (message);
if (private_status) {
- ret = COERCE_STATUS(private_status, "error removing terms");
+ ret = COERCE_STATUS (private_status, "error removing terms");
goto DONE;
}
@@ -2194,7 +2291,7 @@ notmuch_message_reindex (notmuch_message_t *message,
_notmuch_message_sync (message);
}
- DONE:
+ DONE:
if (message_file)
_notmuch_message_file_close (message_file);
diff --git a/lib/messages.c b/lib/messages.c
index 04fa19f8..eec0a162 100644
--- a/lib/messages.c
+++ b/lib/messages.c
@@ -117,7 +117,7 @@ _notmuch_messages_has_next (notmuch_messages_t *messages)
return false;
if (! messages->is_of_list_type)
- INTERNAL_ERROR("_notmuch_messages_has_next not implimented for msets");
+ INTERNAL_ERROR ("_notmuch_messages_has_next not implemented for msets");
return (messages->iterator->next != NULL);
}
@@ -183,7 +183,7 @@ notmuch_messages_collect_tags (notmuch_messages_t *messages)
keys = g_hash_table_get_keys (htable);
for (l = keys; l; l = l->next) {
- _notmuch_string_list_append (tags, (char *)l->data);
+ _notmuch_string_list_append (tags, (char *) l->data);
}
g_list_free (keys);
diff --git a/lib/notmuch-private.h b/lib/notmuch-private.h
index 6fc5b366..57ec7f72 100644
--- a/lib/notmuch-private.h
+++ b/lib/notmuch-private.h
@@ -53,6 +53,7 @@ NOTMUCH_BEGIN_DECLS
#include "error_util.h"
#include "string-util.h"
#include "crypto.h"
+#include "repair.h"
#ifdef DEBUG
# define DEBUG_DATABASE_SANITY 1
@@ -60,7 +61,7 @@ NOTMUCH_BEGIN_DECLS
# define DEBUG_QUERY 1
#endif
-#define COMPILE_TIME_ASSERT(pred) ((void)sizeof(char[1 - 2*!(pred)]))
+#define COMPILE_TIME_ASSERT(pred) ((void) sizeof (char[1 - 2 * ! (pred)]))
#define STRNCMP_LITERAL(var, literal) \
strncmp ((var), (literal), sizeof (literal) - 1)
@@ -69,11 +70,11 @@ NOTMUCH_BEGIN_DECLS
#define _NOTMUCH_VALID_BIT(bit) \
((bit) >= 0 && ((unsigned long) bit) < CHAR_BIT * sizeof (unsigned long long))
#define NOTMUCH_TEST_BIT(val, bit) \
- (_NOTMUCH_VALID_BIT(bit) ? !!((val) & (1ull << (bit))) : 0)
+ (_NOTMUCH_VALID_BIT (bit) ? ! ! ((val) & (1ull << (bit))) : 0)
#define NOTMUCH_SET_BIT(valp, bit) \
- (_NOTMUCH_VALID_BIT(bit) ? (*(valp) |= (1ull << (bit))) : *(valp))
+ (_NOTMUCH_VALID_BIT (bit) ? (*(valp) |= (1ull << (bit))) : *(valp))
#define NOTMUCH_CLEAR_BIT(valp, bit) \
- (_NOTMUCH_VALID_BIT(bit) ? (*(valp) &= ~(1ull << (bit))) : *(valp))
+ (_NOTMUCH_VALID_BIT (bit) ? (*(valp) &= ~(1ull << (bit))) : *(valp))
#define unused(x) x __attribute__ ((unused))
@@ -83,12 +84,12 @@ NOTMUCH_BEGIN_DECLS
/* these macros gain us a few percent of speed on gcc */
#if (__GNUC__ >= 3)
/* the strange !! is to ensure that __builtin_expect() takes either 0 or 1
- as its first argument */
+ * as its first argument */
#ifndef likely
-#define likely(x) __builtin_expect(!!(x), 1)
+#define likely(x) __builtin_expect (! ! (x), 1)
#endif
#ifndef unlikely
-#define unlikely(x) __builtin_expect(!!(x), 0)
+#define unlikely(x) __builtin_expect (! ! (x), 0)
#endif
#else
#ifndef likely
@@ -124,17 +125,17 @@ typedef enum {
typedef enum _notmuch_private_status {
/* First, copy all the public status values. */
- NOTMUCH_PRIVATE_STATUS_SUCCESS = NOTMUCH_STATUS_SUCCESS,
- NOTMUCH_PRIVATE_STATUS_OUT_OF_MEMORY = NOTMUCH_STATUS_OUT_OF_MEMORY,
- NOTMUCH_PRIVATE_STATUS_READ_ONLY_DATABASE = NOTMUCH_STATUS_READ_ONLY_DATABASE,
- NOTMUCH_PRIVATE_STATUS_XAPIAN_EXCEPTION = NOTMUCH_STATUS_XAPIAN_EXCEPTION,
- NOTMUCH_PRIVATE_STATUS_FILE_NOT_EMAIL = NOTMUCH_STATUS_FILE_NOT_EMAIL,
- NOTMUCH_PRIVATE_STATUS_NULL_POINTER = NOTMUCH_STATUS_NULL_POINTER,
- NOTMUCH_PRIVATE_STATUS_TAG_TOO_LONG = NOTMUCH_STATUS_TAG_TOO_LONG,
- NOTMUCH_PRIVATE_STATUS_UNBALANCED_FREEZE_THAW = NOTMUCH_STATUS_UNBALANCED_FREEZE_THAW,
+ NOTMUCH_PRIVATE_STATUS_SUCCESS = NOTMUCH_STATUS_SUCCESS,
+ NOTMUCH_PRIVATE_STATUS_OUT_OF_MEMORY = NOTMUCH_STATUS_OUT_OF_MEMORY,
+ NOTMUCH_PRIVATE_STATUS_READ_ONLY_DATABASE = NOTMUCH_STATUS_READ_ONLY_DATABASE,
+ NOTMUCH_PRIVATE_STATUS_XAPIAN_EXCEPTION = NOTMUCH_STATUS_XAPIAN_EXCEPTION,
+ NOTMUCH_PRIVATE_STATUS_FILE_NOT_EMAIL = NOTMUCH_STATUS_FILE_NOT_EMAIL,
+ NOTMUCH_PRIVATE_STATUS_NULL_POINTER = NOTMUCH_STATUS_NULL_POINTER,
+ NOTMUCH_PRIVATE_STATUS_TAG_TOO_LONG = NOTMUCH_STATUS_TAG_TOO_LONG,
+ NOTMUCH_PRIVATE_STATUS_UNBALANCED_FREEZE_THAW = NOTMUCH_STATUS_UNBALANCED_FREEZE_THAW,
/* Then add our own private values. */
- NOTMUCH_PRIVATE_STATUS_TERM_TOO_LONG = NOTMUCH_STATUS_LAST_STATUS,
+ NOTMUCH_PRIVATE_STATUS_TERM_TOO_LONG = NOTMUCH_STATUS_LAST_STATUS,
NOTMUCH_PRIVATE_STATUS_NO_DOCUMENT_FOUND,
NOTMUCH_PRIVATE_STATUS_BAD_PREFIX,
@@ -150,14 +151,14 @@ typedef enum _notmuch_private_status {
* Note that the function _internal_error does not return. Evaluating
* to NOTMUCH_STATUS_SUCCESS is done purely to appease the compiler.
*/
-#define COERCE_STATUS(private_status, format, ...) \
- ((private_status >= (notmuch_private_status_t) NOTMUCH_STATUS_LAST_STATUS)\
- ? \
- _internal_error (format " (%s).\n", \
- ##__VA_ARGS__, \
- __location__), \
- (notmuch_status_t) NOTMUCH_PRIVATE_STATUS_SUCCESS \
- : \
+#define COERCE_STATUS(private_status, format, ...) \
+ ((private_status >= (notmuch_private_status_t) NOTMUCH_STATUS_LAST_STATUS) \
+ ? \
+ _internal_error (format " (%s).\n", \
+ ##__VA_ARGS__, \
+ __location__), \
+ (notmuch_status_t) NOTMUCH_PRIVATE_STATUS_SUCCESS \
+ : \
(notmuch_status_t) private_status)
/* Flags shared by various lookup functions. */
@@ -167,7 +168,7 @@ typedef enum _notmuch_find_flags {
NOTMUCH_FIND_LOOKUP = 0,
/* If set, create the necessary document (or documents) if they
* are missing. Requires a read/write database. */
- NOTMUCH_FIND_CREATE = 1<<0,
+ NOTMUCH_FIND_CREATE = 1 << 0,
} notmuch_find_flags_t;
typedef struct _notmuch_doc_id_set notmuch_doc_id_set_t;
@@ -185,7 +186,7 @@ _find_prefix (const char *name);
/* Lookup a prefix value by name, including possibly user defined prefixes
*/
const char *
-_notmuch_database_prefix (notmuch_database_t *notmuch, const char *name);
+_notmuch_database_prefix (notmuch_database_t *notmuch, const char *name);
char *
_notmuch_message_id_compressed (void *ctx, const char *message_id);
@@ -250,14 +251,17 @@ _notmuch_database_filename_to_direntry (void *ctx,
/* directory.cc */
notmuch_directory_t *
-_notmuch_directory_create (notmuch_database_t *notmuch,
- const char *path,
- notmuch_find_flags_t flags,
- notmuch_status_t *status_ret);
+_notmuch_directory_find_or_create (notmuch_database_t *notmuch,
+ const char *path,
+ notmuch_find_flags_t flags,
+ notmuch_status_t *status_ret);
unsigned int
_notmuch_directory_get_document_id (notmuch_directory_t *directory);
+notmuch_database_mode_t
+_notmuch_database_mode (notmuch_database_t *notmuch);
+
/* message.cc */
notmuch_message_t *
@@ -436,7 +440,7 @@ _notmuch_message_file_get_mime_message (notmuch_message_file_t *message,
*/
const char *
_notmuch_message_file_get_header (notmuch_message_file_t *message,
- const char *header);
+ const char *header);
notmuch_status_t
_notmuch_message_file_get_headers (notmuch_message_file_t *message_file,
@@ -568,7 +572,7 @@ void
_notmuch_message_remove_unprefixed_terms (notmuch_message_t *message);
const char *
-_notmuch_message_get_thread_id_only(notmuch_message_t *message);
+_notmuch_message_get_thread_id_only (notmuch_message_t *message);
size_t _notmuch_message_get_thread_depth (notmuch_message_t *message);
@@ -621,10 +625,10 @@ void
_notmuch_string_list_sort (notmuch_string_list_t *list);
const notmuch_string_list_t *
-_notmuch_message_get_references(notmuch_message_t *message);
+_notmuch_message_get_references (notmuch_message_t *message);
/* string-map.c */
-typedef struct _notmuch_string_map notmuch_string_map_t;
+typedef struct _notmuch_string_map notmuch_string_map_t;
typedef struct _notmuch_string_map_iterator notmuch_string_map_iterator_t;
notmuch_string_map_t *
_notmuch_string_map_create (const void *ctx);
@@ -704,7 +708,7 @@ NOTMUCH_END_DECLS
* template function for this to maintain type safety, and redefine
* talloc_steal to use it.
*/
-#if !(__GNUC__ >= 3)
+#if ! (__GNUC__ >= 3)
template <class T> T *
_notmuch_talloc_steal (const void *new_ctx, const T *ptr)
{
diff --git a/lib/notmuch.h b/lib/notmuch.h
index 24708f3c..c66e78b1 100644
--- a/lib/notmuch.h
+++ b/lib/notmuch.h
@@ -57,18 +57,18 @@ NOTMUCH_BEGIN_DECLS
* The library version number. This must agree with the soname
* version in Makefile.local.
*/
-#define LIBNOTMUCH_MAJOR_VERSION 5
-#define LIBNOTMUCH_MINOR_VERSION 2
-#define LIBNOTMUCH_MICRO_VERSION 0
+#define LIBNOTMUCH_MAJOR_VERSION 5
+#define LIBNOTMUCH_MINOR_VERSION 3
+#define LIBNOTMUCH_MICRO_VERSION 0
#if defined (__clang_major__) && __clang_major__ >= 3 \
|| defined (__GNUC__) && __GNUC__ >= 5 \
|| defined (__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ >= 5
-#define NOTMUCH_DEPRECATED(major,minor) \
+#define NOTMUCH_DEPRECATED(major, minor) \
__attribute__ ((deprecated ("function deprecated as of libnotmuch " #major "." #minor)))
#else
-#define NOTMUCH_DEPRECATED(major,minor) __attribute__ ((deprecated))
+#define NOTMUCH_DEPRECATED(major, minor) __attribute__ ((deprecated))
#endif
@@ -95,8 +95,8 @@ NOTMUCH_BEGIN_DECLS
* #endif
* @endcode
*/
-#define LIBNOTMUCH_CHECK_VERSION(major, minor, micro) \
- (LIBNOTMUCH_MAJOR_VERSION > (major) || \
+#define LIBNOTMUCH_CHECK_VERSION(major, minor, micro) \
+ (LIBNOTMUCH_MAJOR_VERSION > (major) || \
(LIBNOTMUCH_MAJOR_VERSION == (major) && LIBNOTMUCH_MINOR_VERSION > (minor)) || \
(LIBNOTMUCH_MAJOR_VERSION == (major) && LIBNOTMUCH_MINOR_VERSION == (minor) && \
LIBNOTMUCH_MICRO_VERSION >= (micro)))
@@ -405,8 +405,8 @@ typedef void (*notmuch_compact_status_cb_t)(const char *message, void *closure);
* 'closure' is passed verbatim to any callback invoked.
*/
notmuch_status_t
-notmuch_database_compact (const char* path,
- const char* backup_path,
+notmuch_database_compact (const char *path,
+ const char *backup_path,
notmuch_compact_status_cb_t status_cb,
void *closure);
@@ -431,6 +431,8 @@ notmuch_database_get_path (notmuch_database_t *database);
/**
* Return the database format version of the given database.
+ *
+ * @retval 0 on error
*/
unsigned int
notmuch_database_get_version (notmuch_database_t *database);
@@ -444,6 +446,9 @@ notmuch_database_get_version (notmuch_database_t *database);
* fail with NOTMUCH_STATUS_UPGRADE_REQUIRED. This always returns
* FALSE for a read-only database because there's no way to upgrade a
* read-only database.
+ *
+ * Also returns FALSE if an error occurs accessing the database.
+ *
*/
notmuch_bool_t
notmuch_database_needs_upgrade (notmuch_database_t *database);
@@ -467,8 +472,8 @@ notmuch_database_needs_upgrade (notmuch_database_t *database);
*/
notmuch_status_t
notmuch_database_upgrade (notmuch_database_t *database,
- void (*progress_notify) (void *closure,
- double progress),
+ void (*progress_notify)(void *closure,
+ double progress),
void *closure);
/**
@@ -525,7 +530,7 @@ notmuch_database_end_atomic (notmuch_database_t *notmuch);
*/
unsigned long
notmuch_database_get_revision (notmuch_database_t *notmuch,
- const char **uuid);
+ const char **uuid);
/**
* Retrieve a directory object from the database for 'path'.
@@ -551,7 +556,7 @@ notmuch_database_get_revision (notmuch_database_t *notmuch,
* directory not retrieved.
*
* NOTMUCH_STATUS_UPGRADE_REQUIRED: The caller must upgrade the
- * database to use this function.
+ * database to use this function.
*/
notmuch_status_t
notmuch_database_get_directory (notmuch_database_t *database,
@@ -614,7 +619,7 @@ notmuch_database_get_directory (notmuch_database_t *database,
* mode so no message can be added.
*
* NOTMUCH_STATUS_UPGRADE_REQUIRED: The caller must upgrade the
- * database to use this function.
+ * database to use this function.
*
* @since libnotmuch 5.1 (notmuch 0.26)
*/
@@ -632,7 +637,7 @@ notmuch_database_index_file (notmuch_database_t *database,
* use notmuch_database_index_file instead.
*
*/
-NOTMUCH_DEPRECATED(5,1)
+NOTMUCH_DEPRECATED (5, 1)
notmuch_status_t
notmuch_database_add_message (notmuch_database_t *database,
const char *filename,
@@ -664,7 +669,7 @@ notmuch_database_add_message (notmuch_database_t *database,
* mode so no message can be removed.
*
* NOTMUCH_STATUS_UPGRADE_REQUIRED: The caller must upgrade the
- * database to use this function.
+ * database to use this function.
*/
notmuch_status_t
notmuch_database_remove_message (notmuch_database_t *database,
@@ -722,7 +727,7 @@ notmuch_database_find_message (notmuch_database_t *database,
* NOTMUCH_STATUS_XAPIAN_EXCEPTION: A Xapian exception occurred
*
* NOTMUCH_STATUS_UPGRADE_REQUIRED: The caller must upgrade the
- * database to use this function.
+ * database to use this function.
*/
notmuch_status_t
notmuch_database_find_message_by_filename (notmuch_database_t *notmuch,
@@ -930,7 +935,7 @@ notmuch_query_search_threads (notmuch_query_t *query,
* use notmuch_query_search_threads instead.
*
*/
-NOTMUCH_DEPRECATED(5,0)
+NOTMUCH_DEPRECATED (5, 0)
notmuch_status_t
notmuch_query_search_threads_st (notmuch_query_t *query, notmuch_threads_t **out);
@@ -986,7 +991,7 @@ notmuch_query_search_messages (notmuch_query_t *query,
*
*/
-NOTMUCH_DEPRECATED(5,0)
+NOTMUCH_DEPRECATED (5, 0)
notmuch_status_t
notmuch_query_search_messages_st (notmuch_query_t *query,
notmuch_messages_t **out);
@@ -1082,7 +1087,7 @@ notmuch_query_count_messages (notmuch_query_t *query, unsigned int *count);
* @deprecated Deprecated since libnotmuch 5.0 (notmuch 0.25). Please
* use notmuch_query_count_messages instead.
*/
-NOTMUCH_DEPRECATED(5,0)
+NOTMUCH_DEPRECATED (5, 0)
notmuch_status_t
notmuch_query_count_messages_st (notmuch_query_t *query, unsigned int *count);
@@ -1100,7 +1105,7 @@ notmuch_query_count_messages_st (notmuch_query_t *query, unsigned int *count);
*
* NOTMUCH_STATUS_OUT_OF_MEMORY: Memory allocation failed. The value
* of *count is not defined
-
+ *
* NOTMUCH_STATUS_SUCCESS: query completed successfully.
*
* NOTMUCH_STATUS_XAPIAN_EXCEPTION: a Xapian exception occurred. The
@@ -1117,7 +1122,7 @@ notmuch_query_count_threads (notmuch_query_t *query, unsigned *count);
* @deprecated Deprecated as of libnotmuch 5.0 (notmuch 0.25). Please
* use notmuch_query_count_threads_st instead.
*/
-NOTMUCH_DEPRECATED(5,0)
+NOTMUCH_DEPRECATED (5, 0)
notmuch_status_t
notmuch_query_count_threads_st (notmuch_query_t *query, unsigned *count);
@@ -1363,9 +1368,8 @@ notmuch_message_get_database (const notmuch_message_t *message);
* message is valid, (which is until the query from which it derived
* is destroyed).
*
- * This function will not return NULL since Notmuch ensures that every
- * message has a unique message ID, (Notmuch will generate an ID for a
- * message if the original file does not contain one).
+ * This function will return NULL if triggers an unhandled Xapian
+ * exception.
*/
const char *
notmuch_message_get_message_id (notmuch_message_t *message);
@@ -1379,8 +1383,8 @@ notmuch_message_get_message_id (notmuch_message_t *message);
* notmuch_message_destroy on 'message' or until a query from which it
* derived is destroyed).
*
- * This function will not return NULL since Notmuch ensures that every
- * message belongs to a single thread.
+ * This function will return NULL if triggers an unhandled Xapian
+ * exception.
*/
const char *
notmuch_message_get_thread_id (notmuch_message_t *message);
@@ -1403,14 +1407,18 @@ notmuch_message_get_thread_id (notmuch_message_t *message);
* NULL. (Note that notmuch_messages_valid will accept that NULL
* value as legitimate, and simply return FALSE for it.)
*
- * The returned list will be destroyed when the thread is destroyed.
+ * This function also returns NULL if it triggers a Xapian exception.
+ *
+ * The returned list will be destroyed when the thread is
+ * destroyed.
*/
notmuch_messages_t *
notmuch_message_get_replies (notmuch_message_t *message);
/**
* Get the total number of files associated with a message.
- * @returns Non-negative integer
+ * @returns Non-negative integer for file count.
+ * @returns Negative integer for error.
* @since libnotmuch 5.0 (notmuch 0.25)
*/
int
@@ -1431,6 +1439,8 @@ notmuch_message_count_files (notmuch_message_t *message);
* this function will arbitrarily return a single one of those
* filenames. See notmuch_message_get_filenames for returning the
* complete list of filenames.
+ *
+ * This function returns NULL if it triggers a Xapian exception.
*/
const char *
notmuch_message_get_filename (notmuch_message_t *message);
@@ -1444,6 +1454,8 @@ notmuch_message_get_filename (notmuch_message_t *message);
*
* Each filename in the iterator is an absolute filename, (the initial
* component will match notmuch_database_get_path() ).
+ *
+ * This function returns NULL if it triggers a Xapian exception.
*/
notmuch_filenames_t *
notmuch_message_get_filenames (notmuch_message_t *message);
@@ -1479,12 +1491,37 @@ typedef enum _notmuch_message_flag {
/**
* Get a value of a flag for the email corresponding to 'message'.
+ *
+ * returns FALSE in case of errors.
+ *
+ * @deprecated Deprecated as of libnotmuch 5.3 (notmuch 0.31). Please
+ * use notmuch_message_get_flag_st instead.
*/
+NOTMUCH_DEPRECATED(5,3)
notmuch_bool_t
notmuch_message_get_flag (notmuch_message_t *message,
notmuch_message_flag_t flag);
/**
+ * Get a value of a flag for the email corresponding to 'message'.
+ *
+ * @param message a message object
+ * @param flag flag to check
+ * @param is_set pointer to boolean to store flag value.
+ *
+ * @retval #NOTMUCH_STATUS_SUCCESS
+ * @retval #NOTMUCH_STATUS_NULL_POINTER is_set is NULL
+ * @retval #NOTMUCH_STATUS_XAPIAN_EXCEPTION Accessing the database
+ * triggered an exception.
+ *
+ * @since libnotmuch 5.3 (notmuch 0.31)
+ */
+notmuch_status_t
+notmuch_message_get_flag_st (notmuch_message_t *message,
+ notmuch_message_flag_t flag,
+ notmuch_bool_t *is_set);
+
+/**
* Set a value of a flag for the email corresponding to 'message'.
*/
void
@@ -1497,9 +1534,11 @@ notmuch_message_set_flag (notmuch_message_t *message,
* For the original textual representation of the Date header from the
* message call notmuch_message_get_header() with a header value of
* "date".
+ *
+ * Returns 0 in case of error.
*/
time_t
-notmuch_message_get_date (notmuch_message_t *message);
+notmuch_message_get_date (notmuch_message_t *message);
/**
* Get the value of the specified header from 'message' as a UTF-8 string.
@@ -1601,8 +1640,10 @@ notmuch_message_remove_tag (notmuch_message_t *message, const char *tag);
* See notmuch_message_freeze for an example showing how to safely
* replace tag values.
*
- * NOTMUCH_STATUS_READ_ONLY_DATABASE: Database was opened in read-only
- * mode so message cannot be modified.
+ * @retval #NOTMUCH_STATUS_READ_ONLY_DATABASE: Database was opened in
+ * read-only mode so message cannot be modified.
+ * @retval #NOTMUCH_STATUS_XAPIAN_EXCEPTION: an exception was thrown
+ * accessing the database.
*/
notmuch_status_t
notmuch_message_remove_all_tags (notmuch_message_t *message);
@@ -1646,11 +1687,33 @@ notmuch_message_maildir_flags_to_tags (notmuch_message_t *message);
* return TRUE if any filename of 'message' has maildir flag 'flag',
* FALSE otherwise.
*
+ * Deprecated wrapper for notmuch_message_has_maildir_flag_st
+ *
+ * @returns FALSE in case of error
+ * @deprecated libnotmuch 5.3 (notmuch 0.31)
*/
+NOTMUCH_DEPRECATED(5, 3)
notmuch_bool_t
notmuch_message_has_maildir_flag (notmuch_message_t *message, char flag);
/**
+ * check message for maildir flag
+ *
+ * @param [in,out] message message to check
+ * @param [in] flag flag to check for
+ * @param [out] is_set pointer to boolean
+ *
+ * @retval #NOTMUCH_STATUS_SUCCESS
+ * @retval #NOTMUCH_STATUS_NULL_POINTER is_set is NULL
+ * @retval #NOTMUCH_STATUS_XAPIAN_EXCEPTION Accessing the database
+ * triggered an exception.
+ */
+notmuch_status_t
+notmuch_message_has_maildir_flag_st (notmuch_message_t *message,
+ char flag,
+ notmuch_bool_t *is_set);
+
+/**
* Rename message filename(s) to encode tags as maildir flags.
*
* Specifically, for each filename corresponding to this message:
@@ -1811,7 +1874,7 @@ notmuch_message_add_property (notmuch_message_t *message, const char *key, const
/**
* Remove a (key,value) pair from a message.
*
- * It is not an error to remove a non-existant (key,value) pair
+ * It is not an error to remove a non-existent (key,value) pair
*
* @returns
* - NOTMUCH_STATUS_ILLEGAL_ARGUMENT: *key* may not contain an '=' character.
@@ -2085,6 +2148,8 @@ notmuch_directory_get_mtime (notmuch_directory_t *directory);
*
* The returned filenames will be the basename-entries only (not
* complete paths).
+ *
+ * Returns NULL if it triggers a Xapian exception
*/
notmuch_filenames_t *
notmuch_directory_get_child_files (notmuch_directory_t *directory);
@@ -2095,6 +2160,8 @@ notmuch_directory_get_child_files (notmuch_directory_t *directory);
*
* The returned filenames will be the basename-entries only (not
* complete paths).
+ *
+ * Returns NULL if it triggers a Xapian exception
*/
notmuch_filenames_t *
notmuch_directory_get_child_directories (notmuch_directory_t *directory);
@@ -2224,6 +2291,7 @@ notmuch_config_list_key (notmuch_config_list_t *config_list);
* next call to notmuch_config_list_value or notmuch config_list_destroy
*
* @since libnotmuch 4.4 (notmuch 0.23)
+ * @retval NULL for errors
*/
const char *
notmuch_config_list_value (notmuch_config_list_t *config_list);
@@ -2257,6 +2325,7 @@ notmuch_config_list_destroy (notmuch_config_list_t *config_list);
* added to the index. At the moment it is a featureless stub.
*
* @since libnotmuch 5.1 (notmuch 0.26)
+ * @retval NULL in case of error
*/
notmuch_indexopts_t *
notmuch_database_get_default_indexopts (notmuch_database_t *db);
@@ -2312,7 +2381,7 @@ notmuch_indexopts_destroy (notmuch_indexopts_t *options);
*/
notmuch_bool_t
notmuch_built_with (const char *name);
-/* @} */
+/**@}*/
#pragma GCC visibility pop
diff --git a/lib/parse-time-vrp.cc b/lib/parse-time-vrp.cc
index dd691494..10809aa3 100644
--- a/lib/parse-time-vrp.cc
+++ b/lib/parse-time-vrp.cc
@@ -24,64 +24,63 @@
#include "parse-time-vrp.h"
#include "parse-time-string.h"
-#define PREFIX "date:"
-
-/* See *ValueRangeProcessor in xapian-core/api/valuerangeproc.cc */
-Xapian::valueno
-ParseTimeValueRangeProcessor::operator() (std::string &begin, std::string &end)
+Xapian::Query
+ParseTimeRangeProcessor::operator() (const std::string &begin, const std::string &end)
{
- time_t t, now;
- std::string b;
-
- /* Require date: prefix in start of the range... */
- if (STRNCMP_LITERAL (begin.c_str (), PREFIX))
- return Xapian::BAD_VALUENO;
-
- /* ...and remove it. */
- begin.erase (0, sizeof (PREFIX) - 1);
- b = begin;
+ double from = DBL_MIN, to = DBL_MAX;
+ time_t parsed_time, now;
+ std::string str;
/* Use the same 'now' for begin and end. */
if (time (&now) == (time_t) -1)
- return Xapian::BAD_VALUENO;
+ throw Xapian::QueryParserError ("unable to get current time");
if (!begin.empty ()) {
- if (parse_time_string (begin.c_str (), &t, &now, PARSE_TIME_ROUND_DOWN))
- return Xapian::BAD_VALUENO;
-
- begin.assign (Xapian::sortable_serialise ((double) t));
+ if (parse_time_string (begin.c_str (), &parsed_time, &now, PARSE_TIME_ROUND_DOWN))
+ throw Xapian::QueryParserError ("Didn't understand date specification '" + begin + "'");
+ else
+ from = (double) parsed_time;
}
if (!end.empty ()) {
- if (end == "!" && ! b.empty ())
- end = b;
-
- if (parse_time_string (end.c_str (), &t, &now, PARSE_TIME_ROUND_UP_INCLUSIVE))
- return Xapian::BAD_VALUENO;
+ if (end == "!" && ! begin.empty ())
+ str = begin;
+ else
+ str = end;
- end.assign (Xapian::sortable_serialise ((double) t));
+ if (parse_time_string (str.c_str (), &parsed_time, &now, PARSE_TIME_ROUND_UP_INCLUSIVE))
+ throw Xapian::QueryParserError ("Didn't understand date specification '" + str + "'");
+ else
+ to = (double) parsed_time;
}
- return valno;
+ return Xapian::Query (Xapian::Query::OP_VALUE_RANGE, slot,
+ Xapian::sortable_serialise (from),
+ Xapian::sortable_serialise (to));
}
-#if HAVE_XAPIAN_FIELD_PROCESSOR
/* XXX TODO: is throwing an exception the right thing to do here? */
-Xapian::Query DateFieldProcessor::operator()(const std::string & str) {
- time_t from, to, now;
+Xapian::Query
+DateFieldProcessor::operator() (const std::string & str)
+{
+ double from = DBL_MIN, to = DBL_MAX;
+ time_t parsed_time, now;
/* Use the same 'now' for begin and end. */
if (time (&now) == (time_t) -1)
- throw Xapian::QueryParserError("Unable to get current time");
+ throw Xapian::QueryParserError ("Unable to get current time");
- if (parse_time_string (str.c_str (), &from, &now, PARSE_TIME_ROUND_DOWN))
+ if (parse_time_string (str.c_str (), &parsed_time, &now, PARSE_TIME_ROUND_DOWN))
throw Xapian::QueryParserError ("Didn't understand date specification '" + str + "'");
+ else
+ from = (double) parsed_time;
- if (parse_time_string (str.c_str (), &to, &now, PARSE_TIME_ROUND_UP_INCLUSIVE))
+ if (parse_time_string (str.c_str (), &parsed_time, &now, PARSE_TIME_ROUND_UP_INCLUSIVE))
throw Xapian::QueryParserError ("Didn't understand date specification '" + str + "'");
+ else
+ to = (double) parsed_time;
- return Xapian::Query(Xapian::Query::OP_AND,
- Xapian::Query(Xapian::Query::OP_VALUE_GE, 0, Xapian::sortable_serialise ((double) from)),
- Xapian::Query(Xapian::Query::OP_VALUE_LE, 0, Xapian::sortable_serialise ((double) to)));
+ return Xapian::Query (Xapian::Query::OP_VALUE_RANGE, slot,
+ Xapian::sortable_serialise (from),
+ Xapian::sortable_serialise (to));
}
-#endif
diff --git a/lib/parse-time-vrp.h b/lib/parse-time-vrp.h
index c024dba2..f495e716 100644
--- a/lib/parse-time-vrp.h
+++ b/lib/parse-time-vrp.h
@@ -26,20 +26,21 @@
#include <xapian.h>
/* see *ValueRangeProcessor in xapian-core/include/xapian/queryparser.h */
-class ParseTimeValueRangeProcessor : public Xapian::ValueRangeProcessor {
-protected:
- Xapian::valueno valno;
+class ParseTimeRangeProcessor : public Xapian::RangeProcessor {
public:
- ParseTimeValueRangeProcessor (Xapian::valueno slot_)
- : valno(slot_) { }
+ ParseTimeRangeProcessor (Xapian::valueno slot_, const std::string prefix_)
+ : Xapian::RangeProcessor(slot_, prefix_, 0) { }
- Xapian::valueno operator() (std::string &begin, std::string &end);
+ Xapian::Query operator() (const std::string &begin, const std::string &end);
};
-#if HAVE_XAPIAN_FIELD_PROCESSOR
class DateFieldProcessor : public Xapian::FieldProcessor {
+private:
+ Xapian::valueno slot;
+public:
+ DateFieldProcessor(Xapian::valueno slot_) : slot(slot_) { };
Xapian::Query operator()(const std::string & str);
};
-#endif
+
#endif /* NOTMUCH_PARSE_TIME_VRP_H */
diff --git a/lib/query-fp.cc b/lib/query-fp.cc
index c39f5915..b980b7f0 100644
--- a/lib/query-fp.cc
+++ b/lib/query-fp.cc
@@ -24,8 +24,6 @@
#include "query-fp.h"
#include <iostream>
-#if HAVE_XAPIAN_FIELD_PROCESSOR
-
Xapian::Query
QueryFieldProcessor::operator() (const std::string & name)
{
@@ -40,4 +38,3 @@ QueryFieldProcessor::operator() (const std::string & name)
return parser.parse_query (expansion, NOTMUCH_QUERY_PARSER_FLAGS);
}
-#endif
diff --git a/lib/query-fp.h b/lib/query-fp.h
index d6e4b313..beaaf405 100644
--- a/lib/query-fp.h
+++ b/lib/query-fp.h
@@ -26,17 +26,18 @@
#include <xapian.h>
#include "notmuch.h"
-#if HAVE_XAPIAN_FIELD_PROCESSOR
class QueryFieldProcessor : public Xapian::FieldProcessor {
- protected:
+protected:
Xapian::QueryParser &parser;
notmuch_database_t *notmuch;
- public:
+public:
QueryFieldProcessor (Xapian::QueryParser &parser_, notmuch_database_t *notmuch_)
- : parser(parser_), notmuch(notmuch_) { };
+ : parser (parser_), notmuch (notmuch_)
+ {
+ };
- Xapian::Query operator()(const std::string & str);
+ Xapian::Query operator() (const std::string & str);
};
-#endif
+
#endif /* NOTMUCH_QUERY_FP_H */
diff --git a/lib/query.cc b/lib/query.cc
index 7fdf992d..792aba21 100644
--- a/lib/query.cc
+++ b/lib/query.cc
@@ -71,12 +71,14 @@ static bool
_debug_query (void)
{
char *env = getenv ("NOTMUCH_DEBUG_QUERY");
+
return (env && strcmp (env, "") != 0);
}
/* Explicit destructor call for placement new */
static int
-_notmuch_query_destructor (notmuch_query_t *query) {
+_notmuch_query_destructor (notmuch_query_t *query)
+{
query->xapian_query.~Query();
query->terms.~set<std::string>();
return 0;
@@ -123,12 +125,12 @@ _notmuch_query_ensure_parsed (notmuch_query_t *query)
try {
query->xapian_query =
query->notmuch->query_parser->
- parse_query (query->query_string, NOTMUCH_QUERY_PARSER_FLAGS);
+ parse_query (query->query_string, NOTMUCH_QUERY_PARSER_FLAGS);
- /* Xapian doesn't support skip_to on terms from a query since
- * they are unordered, so cache a copy of all terms in
- * something searchable.
- */
+ /* Xapian doesn't support skip_to on terms from a query since
+ * they are unordered, so cache a copy of all terms in
+ * something searchable.
+ */
for (Xapian::TermIterator t = query->xapian_query.get_terms_begin ();
t != query->xapian_query.get_terms_end (); ++t)
@@ -137,7 +139,7 @@ _notmuch_query_ensure_parsed (notmuch_query_t *query)
query->parsed = true;
} catch (const Xapian::Error &error) {
- if (!query->notmuch->exception_reported) {
+ if (! query->notmuch->exception_reported) {
_notmuch_database_log (query->notmuch,
"A Xapian exception occurred parsing query: %s\n",
error.get_msg ().c_str ());
@@ -188,7 +190,7 @@ notmuch_query_add_tag_exclude (notmuch_query_t *query, const char *tag)
return status;
term = talloc_asprintf (query, "%s%s", _find_prefix ("tag"), tag);
- if (query->terms.count(term) != 0)
+ if (query->terms.count (term) != 0)
return NOTMUCH_STATUS_IGNORED;
_notmuch_string_list_append (query->exclude_terms, term);
@@ -236,7 +238,7 @@ notmuch_query_search_messages_st (notmuch_query_t *query,
notmuch_status_t
notmuch_query_search_messages (notmuch_query_t *query,
- notmuch_messages_t **out)
+ notmuch_messages_t **out)
{
return _notmuch_query_search_documents (query, "mail", out);
}
@@ -278,8 +280,7 @@ _notmuch_query_search_documents (notmuch_query_t *query,
Xapian::MSetIterator iterator;
if (strcmp (query_string, "") == 0 ||
- strcmp (query_string, "*") == 0)
- {
+ strcmp (query_string, "*") == 0) {
final_query = mail_query;
} else {
final_query = Xapian::Query (Xapian::Query::OP_AND,
@@ -291,15 +292,14 @@ _notmuch_query_search_documents (notmuch_query_t *query,
exclude_query = _notmuch_exclude_tags (query);
if (query->omit_excluded == NOTMUCH_EXCLUDE_TRUE ||
- query->omit_excluded == NOTMUCH_EXCLUDE_ALL)
- {
+ query->omit_excluded == NOTMUCH_EXCLUDE_ALL) {
final_query = Xapian::Query (Xapian::Query::OP_AND_NOT,
final_query, exclude_query);
} else { /* NOTMUCH_EXCLUDE_FLAG */
exclude_query = Xapian::Query (Xapian::Query::OP_AND,
- exclude_query, final_query);
+ exclude_query, final_query);
- enquire.set_weighting_scheme (Xapian::BoolWeight());
+ enquire.set_weighting_scheme (Xapian::BoolWeight ());
enquire.set_query (exclude_query);
mset = enquire.get_mset (0, notmuch->xapian_db->get_doccount ());
@@ -318,7 +318,7 @@ _notmuch_query_search_documents (notmuch_query_t *query,
}
- enquire.set_weighting_scheme (Xapian::BoolWeight());
+ enquire.set_weighting_scheme (Xapian::BoolWeight ());
switch (query->sort) {
case NOTMUCH_SORT_OLDEST_FIRST:
@@ -354,10 +354,10 @@ _notmuch_query_search_documents (notmuch_query_t *query,
} catch (const Xapian::Error &error) {
_notmuch_database_log (notmuch,
"A Xapian exception occurred performing query: %s\n",
- error.get_msg().c_str());
+ error.get_msg ().c_str ());
_notmuch_database_log_append (notmuch,
- "Query string was: %s\n",
- query->query_string);
+ "Query string was: %s\n",
+ query->query_string);
notmuch->exception_reported = true;
talloc_free (messages);
@@ -408,8 +408,7 @@ _notmuch_mset_messages_get (notmuch_messages_t *messages)
&status);
if (message == NULL &&
- status == NOTMUCH_PRIVATE_STATUS_NO_DOCUMENT_FOUND)
- {
+ status == NOTMUCH_PRIVATE_STATUS_NO_DOCUMENT_FOUND) {
INTERNAL_ERROR ("a messages iterator contains a non-existent document ID.\n");
}
@@ -439,8 +438,8 @@ _notmuch_doc_id_set_init (void *ctx,
unsigned char *bitmap;
for (unsigned int i = 0; i < arr->len; i++)
- max = MAX(max, g_array_index (arr, unsigned int, i));
- bitmap = talloc_zero_array (ctx, unsigned char, DOCIDSET_WORD(max) + 1);
+ max = MAX (max, g_array_index (arr, unsigned int, i));
+ bitmap = talloc_zero_array (ctx, unsigned char, DOCIDSET_WORD (max) + 1);
if (bitmap == NULL)
return false;
@@ -450,7 +449,7 @@ _notmuch_doc_id_set_init (void *ctx,
for (unsigned int i = 0; i < arr->len; i++) {
unsigned int doc_id = g_array_index (arr, unsigned int, i);
- bitmap[DOCIDSET_WORD(doc_id)] |= 1 << DOCIDSET_BIT(doc_id);
+ bitmap[DOCIDSET_WORD (doc_id)] |= 1 << DOCIDSET_BIT (doc_id);
}
return true;
@@ -462,7 +461,7 @@ _notmuch_doc_id_set_contains (notmuch_doc_id_set_t *doc_ids,
{
if (doc_id >= doc_ids->bound)
return false;
- return doc_ids->bitmap[DOCIDSET_WORD(doc_id)] & (1 << DOCIDSET_BIT(doc_id));
+ return doc_ids->bitmap[DOCIDSET_WORD (doc_id)] & (1 << DOCIDSET_BIT (doc_id));
}
void
@@ -470,7 +469,7 @@ _notmuch_doc_id_set_remove (notmuch_doc_id_set_t *doc_ids,
unsigned int doc_id)
{
if (doc_id < doc_ids->bound)
- doc_ids->bitmap[DOCIDSET_WORD(doc_id)] &= ~(1 << DOCIDSET_BIT(doc_id));
+ doc_ids->bitmap[DOCIDSET_WORD (doc_id)] &= ~(1 << DOCIDSET_BIT (doc_id));
}
/* Glib objects force use to use a talloc destructor as well, (but not
@@ -489,7 +488,7 @@ _notmuch_threads_destructor (notmuch_threads_t *threads)
notmuch_status_t
notmuch_query_search_threads_st (notmuch_query_t *query, notmuch_threads_t **out)
{
- return notmuch_query_search_threads(query, out);
+ return notmuch_query_search_threads (query, out);
}
notmuch_status_t
@@ -624,8 +623,7 @@ _notmuch_query_count_documents (notmuch_query_t *query, const char *type, unsign
Xapian::MSet mset;
if (strcmp (query_string, "") == 0 ||
- strcmp (query_string, "*") == 0)
- {
+ strcmp (query_string, "*") == 0) {
final_query = mail_query;
} else {
final_query = Xapian::Query (Xapian::Query::OP_AND,
@@ -635,10 +633,10 @@ _notmuch_query_count_documents (notmuch_query_t *query, const char *type, unsign
exclude_query = _notmuch_exclude_tags (query);
final_query = Xapian::Query (Xapian::Query::OP_AND_NOT,
- final_query, exclude_query);
+ final_query, exclude_query);
- enquire.set_weighting_scheme(Xapian::BoolWeight());
- enquire.set_docid_order(Xapian::Enquire::ASCENDING);
+ enquire.set_weighting_scheme (Xapian::BoolWeight ());
+ enquire.set_docid_order (Xapian::Enquire::ASCENDING);
if (_debug_query ()) {
fprintf (stderr, "Exclude query is:\n%s\n",
@@ -657,12 +655,12 @@ _notmuch_query_count_documents (notmuch_query_t *query, const char *type, unsign
mset = enquire.get_mset (0, 1,
notmuch->xapian_db->get_doccount ());
- count = mset.get_matches_estimated();
+ count = mset.get_matches_estimated ();
} catch (const Xapian::Error &error) {
_notmuch_database_log (notmuch,
"A Xapian exception occurred performing query: %s\n",
- error.get_msg().c_str());
+ error.get_msg ().c_str ());
_notmuch_database_log_append (notmuch,
"Query string was: %s\n",
query->query_string);
diff --git a/lib/regexp-fields.cc b/lib/regexp-fields.cc
index 5d4cf80a..0feb50e5 100644
--- a/lib/regexp-fields.cc
+++ b/lib/regexp-fields.cc
@@ -26,7 +26,6 @@
#include "notmuch-private.h"
#include "database-private.h"
-#if HAVE_XAPIAN_FIELD_PROCESSOR
static void
compile_regex (regex_t &regexp, const char *str)
{
@@ -124,12 +123,13 @@ bool
RegexpPostingSource::check (Xapian::docid did, unused (double min_wt))
{
started_ = true;
- if (!it_.check (did) || at_end ())
+ if (! it_.check (did) || at_end ())
return false;
return (regexec (&regexp_, (*it_).c_str (), 0, NULL, 0) == 0);
}
-static inline Xapian::valueno _find_slot (std::string prefix)
+static inline Xapian::valueno
+_find_slot (std::string prefix)
{
if (prefix == "from")
return NOTMUCH_VALUE_FROM;
@@ -145,11 +145,11 @@ RegexpFieldProcessor::RegexpFieldProcessor (std::string prefix,
notmuch_field_flag_t options_,
Xapian::QueryParser &parser_,
notmuch_database_t *notmuch_)
- : slot (_find_slot (prefix)),
- term_prefix (_find_prefix (prefix.c_str ())),
- options (options_),
- parser (parser_),
- notmuch (notmuch_)
+ : slot (_find_slot (prefix)),
+ term_prefix (_find_prefix (prefix.c_str ())),
+ options (options_),
+ parser (parser_),
+ notmuch (notmuch_)
{
};
@@ -158,17 +158,17 @@ RegexpFieldProcessor::operator() (const std::string & str)
{
if (str.empty ()) {
if (options & NOTMUCH_FIELD_PROBABILISTIC) {
- return Xapian::Query(Xapian::Query::OP_AND_NOT,
- Xapian::Query::MatchAll,
- Xapian::Query (Xapian::Query::OP_WILDCARD, term_prefix));
+ return Xapian::Query (Xapian::Query::OP_AND_NOT,
+ Xapian::Query::MatchAll,
+ Xapian::Query (Xapian::Query::OP_WILDCARD, term_prefix));
} else {
return Xapian::Query (term_prefix);
}
}
if (str.at (0) == '/') {
- if (str.length() > 1 && str.at (str.size () - 1) == '/'){
- std::string regexp_str = str.substr(1,str.size () - 2);
+ if (str.length () > 1 && str.at (str.size () - 1) == '/') {
+ std::string regexp_str = str.substr (1, str.size () - 2);
if (slot != Xapian::BAD_VALUENO) {
RegexpPostingSource *postings = new RegexpPostingSource (slot, regexp_str);
return Xapian::Query (postings->release ());
@@ -176,14 +176,14 @@ RegexpFieldProcessor::operator() (const std::string & str)
std::vector<std::string> terms;
regex_t regexp;
- compile_regex(regexp, regexp_str.c_str ());
+ compile_regex (regexp, regexp_str.c_str ());
for (Xapian::TermIterator it = notmuch->xapian_db->allterms_begin (term_prefix);
it != notmuch->xapian_db->allterms_end (); ++it) {
- if (regexec (&regexp, (*it).c_str () + term_prefix.size(),
+ if (regexec (&regexp, (*it).c_str () + term_prefix.size (),
0, NULL, 0) == 0)
- terms.push_back(*it);
+ terms.push_back (*it);
}
- return Xapian::Query (Xapian::Query::OP_OR, terms.begin(), terms.end());
+ return Xapian::Query (Xapian::Query::OP_OR, terms.begin (), terms.end ());
}
} else {
throw Xapian::QueryParserError ("unmatched regex delimiter in '" + str + "'");
@@ -207,4 +207,3 @@ RegexpFieldProcessor::operator() (const std::string & str)
}
}
}
-#endif
diff --git a/lib/regexp-fields.h b/lib/regexp-fields.h
index d5f93445..a8cca243 100644
--- a/lib/regexp-fields.h
+++ b/lib/regexp-fields.h
@@ -24,7 +24,7 @@
#ifndef NOTMUCH_REGEXP_FIELDS_H
#define NOTMUCH_REGEXP_FIELDS_H
-#if HAVE_XAPIAN_FIELD_PROCESSOR
+
#include <sys/types.h>
#include <regex.h>
#include "database-private.h"
@@ -35,7 +35,7 @@
*/
class RegexpPostingSource : public Xapian::PostingSource
{
- protected:
+protected:
const Xapian::valueno slot_;
regex_t regexp_;
Xapian::Database db_;
@@ -46,7 +46,7 @@ class RegexpPostingSource : public Xapian::PostingSource
RegexpPostingSource (const RegexpPostingSource &);
RegexpPostingSource &operator= (const RegexpPostingSource &);
- public:
+public:
RegexpPostingSource (Xapian::valueno slot, const std::string &regexp);
~RegexpPostingSource ();
void init (const Xapian::Database &db);
@@ -62,20 +62,22 @@ class RegexpPostingSource : public Xapian::PostingSource
class RegexpFieldProcessor : public Xapian::FieldProcessor {
- protected:
+protected:
Xapian::valueno slot;
std::string term_prefix;
notmuch_field_flag_t options;
Xapian::QueryParser &parser;
notmuch_database_t *notmuch;
- public:
+public:
RegexpFieldProcessor (std::string prefix, notmuch_field_flag_t options,
Xapian::QueryParser &parser_, notmuch_database_t *notmuch_);
- ~RegexpFieldProcessor () { };
+ ~RegexpFieldProcessor ()
+ {
+ };
- Xapian::Query operator()(const std::string & str);
+ Xapian::Query operator() (const std::string & str);
};
-#endif
+
#endif /* NOTMUCH_REGEXP_FIELDS_H */
diff --git a/lib/sha1.c b/lib/sha1.c
index cb55b49a..d1a76ee6 100644
--- a/lib/sha1.c
+++ b/lib/sha1.c
@@ -55,6 +55,7 @@ char *
_notmuch_sha1_of_file (const char *filename)
{
FILE *file;
+
#define BLOCK_SIZE 4096
unsigned char block[BLOCK_SIZE];
size_t bytes_read;
diff --git a/lib/string-list.c b/lib/string-list.c
index 9c3ae7ef..f3dac675 100644
--- a/lib/string-list.c
+++ b/lib/string-list.c
@@ -67,8 +67,8 @@ _notmuch_string_list_append (notmuch_string_list_t *list,
static int
cmpnode (const void *pa, const void *pb)
{
- notmuch_string_node_t *a = *(notmuch_string_node_t * const *)pa;
- notmuch_string_node_t *b = *(notmuch_string_node_t * const *)pb;
+ notmuch_string_node_t *a = *(notmuch_string_node_t *const *) pa;
+ notmuch_string_node_t *b = *(notmuch_string_node_t *const *) pb;
return strcmp (a->string, b->string);
}
@@ -92,7 +92,7 @@ _notmuch_string_list_sort (notmuch_string_list_t *list)
qsort (nodes, list->length, sizeof (*nodes), cmpnode);
for (i = 0; i < list->length - 1; ++i)
- nodes[i]->next = nodes[i+1];
+ nodes[i]->next = nodes[i + 1];
nodes[i]->next = NULL;
list->head = nodes[0];
list->tail = &nodes[i]->next;
diff --git a/lib/thread-fp.cc b/lib/thread-fp.cc
index 73277006..97a65211 100644
--- a/lib/thread-fp.cc
+++ b/lib/thread-fp.cc
@@ -24,8 +24,6 @@
#include "thread-fp.h"
#include <iostream>
-#if HAVE_XAPIAN_FIELD_PROCESSOR
-
Xapian::Query
ThreadFieldProcessor::operator() (const std::string & str)
{
@@ -64,4 +62,3 @@ ThreadFieldProcessor::operator() (const std::string & str)
}
}
-#endif
diff --git a/lib/thread-fp.h b/lib/thread-fp.h
index 47c066c1..00bf1aa2 100644
--- a/lib/thread-fp.h
+++ b/lib/thread-fp.h
@@ -26,17 +26,18 @@
#include <xapian.h>
#include "notmuch.h"
-#if HAVE_XAPIAN_FIELD_PROCESSOR
class ThreadFieldProcessor : public Xapian::FieldProcessor {
- protected:
+protected:
Xapian::QueryParser &parser;
notmuch_database_t *notmuch;
- public:
+public:
ThreadFieldProcessor (Xapian::QueryParser &parser_, notmuch_database_t *notmuch_)
- : parser(parser_), notmuch(notmuch_) { };
+ : parser (parser_), notmuch (notmuch_)
+ {
+ };
- Xapian::Query operator()(const std::string & str);
+ Xapian::Query operator() (const std::string & str);
};
-#endif
+
#endif /* NOTMUCH_THREAD_FP_H */
diff --git a/lib/thread.cc b/lib/thread.cc
index fd0e1393..17346008 100644
--- a/lib/thread.cc
+++ b/lib/thread.cc
@@ -22,12 +22,12 @@
#include "database-private.h"
#include <gmime/gmime.h>
-#include <glib.h> /* GHashTable */
+#include <glib.h> /* GHashTable */
#ifdef DEBUG_THREADING
-#define THREAD_DEBUG(format, ...) fprintf(stderr, format " (%s).\n", ##__VA_ARGS__, __location__)
+#define THREAD_DEBUG(format, ...) fprintf (stderr, format " (%s).\n", ##__VA_ARGS__, __location__)
#else
-#define THREAD_DEBUG(format, ...) do {} while (0) /* ignored */
+#define THREAD_DEBUG(format, ...) do {} while (0) /* ignored */
#endif
struct _notmuch_thread {
@@ -165,8 +165,8 @@ _resolve_thread_authors_string (notmuch_thread_t *thread)
g_ptr_array_free (thread->matched_authors_array, true);
thread->matched_authors_array = NULL;
- if (!thread->authors)
- thread->authors = talloc_strdup(thread, "");
+ if (! thread->authors)
+ thread->authors = talloc_strdup (thread, "");
}
/* clean up the ugly "Lastname, Firstname" format that some mail systems
@@ -180,14 +180,14 @@ static char *
_thread_cleanup_author (notmuch_thread_t *thread,
const char *author, const char *from)
{
- char *clean_author,*test_author;
+ char *clean_author, *test_author;
const char *comma;
char *blank;
- int fname,lname;
+ int fname, lname;
if (author == NULL)
return NULL;
- clean_author = talloc_strdup(thread, author);
+ clean_author = talloc_strdup (thread, author);
if (clean_author == NULL)
return NULL;
/* check if there's a comma in the name and that there's a
@@ -196,34 +196,34 @@ _thread_cleanup_author (notmuch_thread_t *thread,
* one character long ",\0").
* Otherwise just return the copy of the original author name that
* we just made*/
- comma = strchr(author,',');
- if (comma && strlen(comma) > 1) {
+ comma = strchr (author, ',');
+ if (comma && strlen (comma) > 1) {
/* let's assemble what we think is the correct name */
lname = comma - author;
/* Skip all the spaces after the comma */
- fname = strlen(author) - lname - 1;
+ fname = strlen (author) - lname - 1;
comma += 1;
while (*comma == ' ') {
fname -= 1;
comma += 1;
}
- strncpy(clean_author, comma, fname);
+ strncpy (clean_author, comma, fname);
- *(clean_author+fname) = ' ';
- strncpy(clean_author + fname + 1, author, lname);
- *(clean_author+fname+1+lname) = '\0';
+ *(clean_author + fname) = ' ';
+ strncpy (clean_author + fname + 1, author, lname);
+ *(clean_author + fname + 1 + lname) = '\0';
/* make a temporary copy and see if it matches the email */
- test_author = talloc_strdup(thread,clean_author);
+ test_author = talloc_strdup (thread, clean_author);
- blank=strchr(test_author,' ');
+ blank = strchr (test_author, ' ');
while (blank != NULL) {
*blank = '.';
- blank=strchr(test_author,' ');
+ blank = strchr (test_author, ' ');
}
- if (strcasestr(from, test_author) == NULL)
+ if (strcasestr (from, test_author) == NULL)
/* we didn't identify this as part of the email address
- * so let's punt and return the original author */
+ * so let's punt and return the original author */
strcpy (clean_author, author);
}
return clean_author;
@@ -251,16 +251,14 @@ _thread_add_message (notmuch_thread_t *thread,
if (omit_exclude != NOTMUCH_EXCLUDE_FALSE) {
for (tags = notmuch_message_get_tags (message);
notmuch_tags_valid (tags);
- notmuch_tags_move_to_next (tags))
- {
+ notmuch_tags_move_to_next (tags)) {
tag = notmuch_tags_get (tags);
/* Is message excluded? */
for (notmuch_string_node_t *term = exclude_terms->head;
term != NULL;
- term = term->next)
- {
+ term = term->next) {
/* Check for an empty string, and then ignore initial 'K'. */
- if (*(term->string) && strcmp(tag, (term->string + 1)) == 0) {
+ if (*(term->string) && strcmp (tag, (term->string + 1)) == 0) {
message_excluded = true;
break;
}
@@ -309,8 +307,7 @@ _thread_add_message (notmuch_thread_t *thread,
for (tags = notmuch_message_get_tags (message);
notmuch_tags_valid (tags);
- notmuch_tags_move_to_next (tags))
- {
+ notmuch_tags_move_to_next (tags)) {
tag = notmuch_tags_get (tags);
g_hash_table_insert (thread->tags, xstrdup (tag), NULL);
}
@@ -338,12 +335,12 @@ _thread_set_subject_from_message (notmuch_thread_t *thread,
cleaned_subject = talloc_strndup (thread,
subject + 4,
- strlen(subject) - 4);
+ strlen (subject) - 4);
} else {
cleaned_subject = talloc_strdup (thread, subject);
}
- if (! EMPTY_STRING(cleaned_subject)) {
+ if (! EMPTY_STRING (cleaned_subject)) {
if (thread->subject)
talloc_free (thread->subject);
@@ -354,14 +351,16 @@ _thread_set_subject_from_message (notmuch_thread_t *thread,
/* Add a message to this thread which is known to match the original
* search specification. The 'sort' parameter controls whether the
* oldest or newest matching subject is applied to the thread as a
- * whole. */
-static void
+ * whole. Returns 0 on success.
+ */
+static int
_thread_add_matched_message (notmuch_thread_t *thread,
notmuch_message_t *message,
notmuch_sort_t sort)
{
time_t date;
notmuch_message_t *hashed_message;
+ notmuch_bool_t is_set;
date = notmuch_message_get_date (message);
@@ -373,34 +372,38 @@ _thread_add_matched_message (notmuch_thread_t *thread,
if (date > thread->newest || ! thread->matched_messages) {
thread->newest = date;
- const char *cur_subject = notmuch_thread_get_subject(thread);
- if (sort != NOTMUCH_SORT_OLDEST_FIRST || EMPTY_STRING(cur_subject))
+ const char *cur_subject = notmuch_thread_get_subject (thread);
+ if (sort != NOTMUCH_SORT_OLDEST_FIRST || EMPTY_STRING (cur_subject))
_thread_set_subject_from_message (thread, message);
}
- if (!notmuch_message_get_flag (message, NOTMUCH_MESSAGE_FLAG_EXCLUDED))
+ if (notmuch_message_get_flag_st (message, NOTMUCH_MESSAGE_FLAG_EXCLUDED, &is_set))
+ return -1;
+ if (! is_set)
thread->matched_messages++;
if (g_hash_table_lookup_extended (thread->message_hash,
- notmuch_message_get_message_id (message), NULL,
- (void **) &hashed_message)) {
+ notmuch_message_get_message_id (message), NULL,
+ (void **) &hashed_message)) {
notmuch_message_set_flag (hashed_message,
NOTMUCH_MESSAGE_FLAG_MATCH, 1);
}
_thread_add_matched_author (thread, _notmuch_message_get_author (hashed_message));
+ return 0;
}
static bool
-_parent_via_in_reply_to (notmuch_thread_t *thread, notmuch_message_t *message) {
+_parent_via_in_reply_to (notmuch_thread_t *thread, notmuch_message_t *message)
+{
notmuch_message_t *parent;
const char *in_reply_to;
in_reply_to = _notmuch_message_get_in_reply_to (message);
- THREAD_DEBUG("checking message = %s in_reply_to=%s\n",
- notmuch_message_get_message_id (message), in_reply_to);
+ THREAD_DEBUG ("checking message = %s in_reply_to=%s\n",
+ notmuch_message_get_message_id (message), in_reply_to);
- if (in_reply_to && (! EMPTY_STRING(in_reply_to)) &&
+ if (in_reply_to && (! EMPTY_STRING (in_reply_to)) &&
g_hash_table_lookup_extended (thread->message_hash,
in_reply_to, NULL,
(void **) &parent)) {
@@ -420,32 +423,32 @@ _parent_or_toplevel (notmuch_thread_t *thread, notmuch_message_t *message)
const notmuch_string_list_t *references =
_notmuch_message_get_references (message);
- THREAD_DEBUG("trying to reparent via references: %s\n",
- notmuch_message_get_message_id (message));
+ THREAD_DEBUG ("trying to reparent via references: %s\n",
+ notmuch_message_get_message_id (message));
for (notmuch_string_node_t *ref_node = references->head;
ref_node; ref_node = ref_node->next) {
- THREAD_DEBUG("checking reference=%s\n", ref_node->string);
+ THREAD_DEBUG ("checking reference=%s\n", ref_node->string);
if ((g_hash_table_lookup_extended (thread->message_hash,
ref_node->string, NULL,
(void **) &new_parent))) {
size_t new_depth = _notmuch_message_get_thread_depth (new_parent);
- THREAD_DEBUG("got depth %lu\n", new_depth);
- if (new_depth > max_depth || !parent) {
- THREAD_DEBUG("adding at depth %lu parent=%s\n", new_depth, ref_node->string);
+ THREAD_DEBUG ("got depth %lu\n", new_depth);
+ if (new_depth > max_depth || ! parent) {
+ THREAD_DEBUG ("adding at depth %lu parent=%s\n", new_depth, ref_node->string);
max_depth = new_depth;
parent = new_parent;
}
}
}
if (parent) {
- THREAD_DEBUG("adding reply %s to parent=%s\n",
- notmuch_message_get_message_id (message),
- notmuch_message_get_message_id (parent));
+ THREAD_DEBUG ("adding reply %s to parent=%s\n",
+ notmuch_message_get_message_id (message),
+ notmuch_message_get_message_id (parent));
_notmuch_message_add_reply (parent, message);
} else {
- THREAD_DEBUG("adding as toplevel %s\n",
- notmuch_message_get_message_id (message));
+ THREAD_DEBUG ("adding as toplevel %s\n",
+ notmuch_message_get_message_id (message));
_notmuch_message_list_add_message (thread->toplevel_list, message);
}
}
@@ -479,22 +482,21 @@ _resolve_thread_relationships (notmuch_thread_t *thread)
*/
if (first_node) {
message = first_node->message;
- THREAD_DEBUG("checking first message %s\n",
- notmuch_message_get_message_id (message));
+ THREAD_DEBUG ("checking first message %s\n",
+ notmuch_message_get_message_id (message));
- if (_notmuch_message_list_empty (maybe_toplevel_list) ||
+ if (_notmuch_message_list_empty (maybe_toplevel_list) ||
! _parent_via_in_reply_to (thread, message)) {
- THREAD_DEBUG("adding first message as toplevel = %s\n",
- notmuch_message_get_message_id (message));
+ THREAD_DEBUG ("adding first message as toplevel = %s\n",
+ notmuch_message_get_message_id (message));
_notmuch_message_list_add_message (maybe_toplevel_list, message);
}
}
for (notmuch_messages_t *messages = _notmuch_messages_create (maybe_toplevel_list);
notmuch_messages_valid (messages);
- notmuch_messages_move_to_next (messages))
- {
+ notmuch_messages_move_to_next (messages)) {
notmuch_message_t *message = notmuch_messages_get (messages);
_notmuch_message_label_depths (message, 0);
}
@@ -616,8 +618,7 @@ _notmuch_thread_create (void *ctx,
for (;
notmuch_messages_valid (messages);
- notmuch_messages_move_to_next (messages))
- {
+ notmuch_messages_move_to_next (messages)) {
unsigned int doc_id;
message = notmuch_messages_get (messages);
@@ -629,7 +630,10 @@ _notmuch_thread_create (void *ctx,
if ( _notmuch_doc_id_set_contains (match_set, doc_id)) {
_notmuch_doc_id_set_remove (match_set, doc_id);
- _thread_add_matched_message (thread, message, sort);
+ if (_thread_add_matched_message (thread, message, sort)) {
+ thread = NULL;
+ goto DONE;
+ }
}
_notmuch_message_close (message);