[PATCH] lib: Invalidate message metadata in _notmuch_message_gen_terms

2014-07-31 Thread Austin Clements
Previously, we invalidated stored message metadata in
_notmuch_message_add_term and _notmuch_message_remove_term, but not in
_notmuch_message_gen_terms.  This doesn't currently result in any bugs
because of our limited uses of _notmuch_message_gen_terms, but it may
could cause trouble in the future.
---
 lib/message.cc | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/lib/message.cc b/lib/message.cc
index 1618e81..cde6a1c 100644
--- a/lib/message.cc
+++ b/lib/message.cc
@@ -1049,6 +1049,8 @@ _notmuch_message_gen_terms (notmuch_message_t *message,
/* Create a gap between this an the next terms so they don't
 * appear to be a phrase. */
message->termpos = term_gen->get_termpos () + 100;
+
+   _notmuch_message_invalidate_metadata (message, prefix_name);
 }

 term_gen->set_termpos (message->termpos);
-- 
2.0.0



[PATCH] lib: Fix slight misinformation in the database schema doc

2014-07-31 Thread Austin Clements
The database schema documentation made it sound like each mail
document had exactly one on-disk message file, which hasn't been true
for a long time.
---
 lib/database.cc | 9 ++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/lib/database.cc b/lib/database.cc
index d90a924..c70ce63 100644
--- a/lib/database.cc
+++ b/lib/database.cc
@@ -55,9 +55,12 @@ typedef struct {
  *
  * Mail document
  * -
- * A mail document is associated with a particular email message file
- * on disk. It is indexed with the following prefixed terms which the
- * database uses to construct threads, etc.:
+ * A mail document is associated with a particular email message. It
+ * is stored in one or more files on disk (though only one has its
+ * content indexed) and is uniquely identified  by its "id" field
+ * (which is generally the message ID). It is indexed with the
+ * following prefixed terms which the database uses to construct
+ * threads, etc.:
  *
  *Single terms of given prefix:
  *
-- 
2.0.0



[PATCH v3 13/13] lib: Update doc of notmuch_database_{needs_upgrade, upgrade}

2014-07-31 Thread Austin Clements
Clients are no longer required to call these functions after opening a
database in read/write mode (which is good, because almost none of
them do!).
---
 lib/notmuch.h | 21 -
 1 file changed, 12 insertions(+), 9 deletions(-)

diff --git a/lib/notmuch.h b/lib/notmuch.h
index cbf2ba5..d771eb2 100644
--- a/lib/notmuch.h
+++ b/lib/notmuch.h
@@ -352,22 +352,25 @@ unsigned int
 notmuch_database_get_version (notmuch_database_t *database);

 /**
- * Does this database need to be upgraded before writing to it?
+ * Is the database behind the latest supported database version?
  *
- * If this function returns TRUE then no functions that modify the
- * database (notmuch_database_add_message, notmuch_message_add_tag,
- * notmuch_directory_set_mtime, etc.) will work unless the function
- * notmuch_database_upgrade is called successfully first.
+ * If this function returns TRUE, then the caller may call
+ * notmuch_database_upgrade to upgrade the database.  If the caller
+ * does not upgrade an out-of-date database, then some functions may
+ * fail with NOTMUCH_STATUS_UPGRADE_REQUIRED.
  */
 notmuch_bool_t
 notmuch_database_needs_upgrade (notmuch_database_t *database);

 /**
- * Upgrade the current database.
+ * Upgrade the current database to the latest supported version.
  *
- * After opening a database in read-write mode, the client should
- * check if an upgrade is needed (notmuch_database_needs_upgrade) and
- * if so, upgrade with this function before making any modifications.
+ * This ensures that all current notmuch functionality will be
+ * available on the database.  After opening a database in read-write
+ * mode, it is recommended that clients check if an upgrade is needed
+ * (notmuch_database_needs_upgrade) and if so, upgrade with this
+ * function before making any modifications.  If
+ * notmuch_database_needs_upgrade returns FALSE, this will be a no-op.
  *
  * The optional progress_notify callback can be used by the caller to
  * provide progress indication to the user. If non-NULL it will be
-- 
2.0.0



[PATCH v3 12/13] lib: Return an error from operations that require an upgrade

2014-07-31 Thread Austin Clements
Previously, there was no protection against a caller invoking an
operation on an old database version that would effectively corrupt
the database by treating it like a newer version.

According to notmuch.h, any caller that opens the database in
read/write mode is supposed to check if the database needs upgrading
and perform an upgrade if it does.  This would protect against this,
but nobody (even the CLI) actually does this.

However, with features, it's easy to protect against incompatible
operations on a fine-grained basis.  This lightweight change allows
callers to safely operate on old database versions, while preventing
specific operations that would corrupt the database with an
informative error message.
---
 lib/database.cc  |  5 +
 lib/directory.cc |  5 +
 lib/message.cc   |  8 
 lib/notmuch.h| 16 
 4 files changed, 34 insertions(+)

diff --git a/lib/database.cc b/lib/database.cc
index 04b3790..d90a924 100644
--- a/lib/database.cc
+++ b/lib/database.cc
@@ -310,6 +310,8 @@ notmuch_status_to_string (notmuch_status_t status)
return "Unbalanced number of calls to 
notmuch_database_begin_atomic/end_atomic";
 case NOTMUCH_STATUS_UNSUPPORTED_OPERATION:
return "Unsupported operation";
+case NOTMUCH_STATUS_UPGRADE_REQUIRED:
+   return "Operation requires a database upgrade";
 default:
 case NOTMUCH_STATUS_LAST_STATUS:
return "Unknown error status value";
@@ -2219,6 +2221,9 @@ notmuch_database_find_message_by_filename 
(notmuch_database_t *notmuch,
 if (message_ret == NULL)
return NOTMUCH_STATUS_NULL_POINTER;

+if (! (notmuch->features & NOTMUCH_FEATURE_FILE_TERMS))
+   return NOTMUCH_STATUS_UPGRADE_REQUIRED;
+
 /* return NULL on any failure */
 *message_ret = NULL;

diff --git a/lib/directory.cc b/lib/directory.cc
index 6a3ffed..8daaec8 100644
--- a/lib/directory.cc
+++ b/lib/directory.cc
@@ -105,6 +105,11 @@ _notmuch_directory_create (notmuch_database_t *notmuch,
 const char *db_path;
 notmuch_bool_t create = (flags & NOTMUCH_FIND_CREATE);

+if (! (notmuch->features & NOTMUCH_FEATURE_DIRECTORY_DOCS)) {
+   *status_ret = NOTMUCH_STATUS_UPGRADE_REQUIRED;
+   return NULL;
+}
+
 *status_ret = NOTMUCH_STATUS_SUCCESS;

 path = _notmuch_database_relative_path (notmuch, path);
diff --git a/lib/message.cc b/lib/message.cc
index 4fc427f..1618e81 100644
--- a/lib/message.cc
+++ b/lib/message.cc
@@ -653,6 +653,10 @@ _notmuch_message_add_filename (notmuch_message_t *message,
 if (filename == NULL)
INTERNAL_ERROR ("Message filename cannot be NULL.");

+if (! (message->notmuch->features & NOTMUCH_FEATURE_FILE_TERMS) ||
+   ! (message->notmuch->features & NOTMUCH_FEATURE_BOOL_FOLDER))
+   return NOTMUCH_STATUS_UPGRADE_REQUIRED;
+
 relative = _notmuch_database_relative_path (message->notmuch, filename);

 status = _notmuch_database_split_path (local, relative, &directory, NULL);
@@ -697,6 +701,10 @@ _notmuch_message_remove_filename (notmuch_message_t 
*message,
 notmuch_private_status_t private_status;
 notmuch_status_t status;

+if (! (message->notmuch->features & NOTMUCH_FEATURE_FILE_TERMS) ||
+   ! (message->notmuch->features & NOTMUCH_FEATURE_BOOL_FOLDER))
+   return NOTMUCH_STATUS_UPGRADE_REQUIRED;
+
 status = _notmuch_database_filename_to_direntry (
local, message->notmuch, filename, NOTMUCH_FIND_LOOKUP, &direntry);
 if (status || !direntry)
diff --git a/lib/notmuch.h b/lib/notmuch.h
index 3c5ec98..cbf2ba5 100644
--- a/lib/notmuch.h
+++ b/lib/notmuch.h
@@ -160,6 +160,10 @@ typedef enum _notmuch_status {
  */
 NOTMUCH_STATUS_UNSUPPORTED_OPERATION,
 /**
+ * The operation requires a database upgrade.
+ */
+NOTMUCH_STATUS_UPGRADE_REQUIRED,
+/**
  * Not an actual status value. Just a way to find out how many
  * valid status values there are.
  */
@@ -438,6 +442,9 @@ notmuch_database_end_atomic (notmuch_database_t *notmuch);
  *
  * NOTMUCH_STATUS_XAPIAN_EXCEPTION: A Xapian exception occurred;
  * directory not retrieved.
+ *
+ * NOTMUCH_STATUS_UPGRADE_REQUIRED: The caller must upgrade the
+ * database to use this function.
  */
 notmuch_status_t
 notmuch_database_get_directory (notmuch_database_t *database,
@@ -490,6 +497,9 @@ notmuch_database_get_directory (notmuch_database_t 
*database,
  *
  * NOTMUCH_STATUS_READ_ONLY_DATABASE: Database was opened in read-only
  * mode so no message can be added.
+ *
+ * NOTMUCH_STATUS_UPGRADE_REQUIRED: The caller must upgrade the
+ * database to use this function.
  */
 notmuch_status_t
 notmuch_database_add_message (notmuch_database_t *database,
@@ -520,6 +530,9 @@ notmuch_database_add_message (notmuch_database_t *database,
  *
  * NOTMUCH_STATUS_READ_ONLY_DATABASE: Database was opened in read-only
  * mode so no message can be removed.
+ *
+ * NOTMUCH_STATUS_UPGRADE_REQUIRED: The caller must upgrade the
+ * databa

[PATCH v3 11/13] lib: Support empty header values in database

2014-07-31 Thread Austin Clements
Commit 567bcbc2 introduced support for storing various headers in
document values.  However, doing so in a backwards-compatible way
meant that genuinely empty header values could not be distinguished
from the old behavior of not storing the headers at all, so these
required parsing the original message.

Now that we have database features, new databases can declare that all
messages have header values, so if we have this feature flag, we can
use the stored header value even if it's the empty string.

This requires slight cleanup to notmuch_message_get_header, since the
code previously couldn't distinguish between empty headers and headers
that are never stored in the database (previously this distinction
didn't matter).
---
 lib/message.cc | 45 +++--
 1 file changed, 27 insertions(+), 18 deletions(-)

diff --git a/lib/message.cc b/lib/message.cc
index e6a5a5a..4fc427f 100644
--- a/lib/message.cc
+++ b/lib/message.cc
@@ -412,26 +412,35 @@ _notmuch_message_ensure_message_file (notmuch_message_t 
*message)
 const char *
 notmuch_message_get_header (notmuch_message_t *message, const char *header)
 {
-try {
-   std::string value;
-
-   /* Fetch header from the appropriate xapian value field if
-* available */
-   if (strcasecmp (header, "from") == 0)
-   value = message->doc.get_value (NOTMUCH_VALUE_FROM);
-   else if (strcasecmp (header, "subject") == 0)
-   value = message->doc.get_value (NOTMUCH_VALUE_SUBJECT);
-   else if (strcasecmp (header, "message-id") == 0)
-   value = message->doc.get_value (NOTMUCH_VALUE_MESSAGE_ID);
-
-   if (!value.empty())
+Xapian::valueno slot = Xapian::BAD_VALUENO;
+
+/* Fetch header from the appropriate xapian value field if
+ * available */
+if (strcasecmp (header, "from") == 0)
+   slot = NOTMUCH_VALUE_FROM;
+else if (strcasecmp (header, "subject") == 0)
+   slot = NOTMUCH_VALUE_SUBJECT;
+else if (strcasecmp (header, "message-id") == 0)
+   slot = NOTMUCH_VALUE_MESSAGE_ID;
+
+if (slot != Xapian::BAD_VALUENO) {
+   try {
+   std::string value = message->doc.get_value (slot);
+
+   /* If we have NOTMUCH_FEATURE_FROM_SUBJECT_ID_VALUES, then
+* empty values indicate empty headers.  If we don't, then
+* it could just mean we didn't record the header. */
+   if ((message->notmuch->features &
+NOTMUCH_FEATURE_FROM_SUBJECT_ID_VALUES) ||
+   ! value.empty())
return talloc_strdup (message, value.c_str ());

-} catch (Xapian::Error &error) {
-   fprintf (stderr, "A Xapian exception occurred when reading header: 
%s\n",
-error.get_msg().c_str());
-   message->notmuch->exception_reported = TRUE;
-   return NULL;
+   } catch (Xapian::Error &error) {
+   fprintf (stderr, "A Xapian exception occurred when reading header: 
%s\n",
+error.get_msg().c_str());
+   message->notmuch->exception_reported = TRUE;
+   return NULL;
+   }
 }

 /* Otherwise fall back to parsing the file */
-- 
2.0.0



[PATCH v3 10/13] lib: Report progress for combined upgrade operation

2014-07-31 Thread Austin Clements
Previously, some parts of upgrade didn't report progress and for
others it was possible for the progress meter to restart at 0 part way
through the upgrade because each stage was reported separately.

Fix this by computing the total amount of work that needs to be done
up-front and updating completed work monotonically.
---
 lib/database.cc | 17 +++--
 1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/lib/database.cc b/lib/database.cc
index 31e6a93..04b3790 100644
--- a/lib/database.cc
+++ b/lib/database.cc
@@ -1234,6 +1234,19 @@ notmuch_database_upgrade (notmuch_database_t *notmuch,
timer_is_active = TRUE;
 }

+/* Figure out how much total work we need to do. */
+if (new_features &
+   (NOTMUCH_FEATURE_FILE_TERMS | NOTMUCH_FEATURE_BOOL_FOLDER)) {
+   notmuch_query_t *query = notmuch_query_create (notmuch, "");
+   total += notmuch_query_count_messages (query);
+   notmuch_query_destroy (query);
+}
+if (new_features & NOTMUCH_FEATURE_DIRECTORY_DOCS) {
+   t_end = db->allterms_end ("XTIMESTAMP");
+   for (t = db->allterms_begin ("XTIMESTAMP"); t != t_end; t++)
+   ++total;
+}
+
 /* Perform the upgrade in a transaction. */
 db->begin_transaction (true);

@@ -1249,8 +1262,6 @@ notmuch_database_upgrade (notmuch_database_t *notmuch,
notmuch_message_t *message;
char *filename;

-   total = notmuch_query_count_messages (query);
-
for (messages = notmuch_query_search_messages (query);
 notmuch_messages_valid (messages);
 notmuch_messages_move_to_next (messages))
@@ -1333,6 +1344,8 @@ notmuch_database_upgrade (notmuch_database_t *notmuch,

db->delete_document (*p);
}
+
+   ++count;
}
 }

-- 
2.0.0



[PATCH v3 09/13] lib: Reorganize upgrade around document types

2014-07-31 Thread Austin Clements
Rather than potentially making multiple passes over the same type of
data in the database, reorganize upgrade around each type of data that
may be upgraded.  This eliminates code duplication, will make
multi-version upgrades faster, and will let us improve progress
reporting.
---
 lib/database.cc | 72 +
 1 file changed, 26 insertions(+), 46 deletions(-)

diff --git a/lib/database.cc b/lib/database.cc
index 69d775f..31e6a93 100644
--- a/lib/database.cc
+++ b/lib/database.cc
@@ -1241,11 +1241,9 @@ notmuch_database_upgrade (notmuch_database_t *notmuch,
  * format. */
 notmuch->features = target_features;

-/* Before version 1, each message document had its filename in the
- * data field. Copy that into the new format by calling
- * notmuch_message_add_filename.
- */
-if (new_features & NOTMUCH_FEATURE_FILE_TERMS) {
+/* Perform per-message upgrades. */
+if (new_features &
+   (NOTMUCH_FEATURE_FILE_TERMS | NOTMUCH_FEATURE_BOOL_FOLDER)) {
notmuch_query_t *query = notmuch_query_create (notmuch, "");
notmuch_messages_t *messages;
notmuch_message_t *message;
@@ -1264,13 +1262,27 @@ notmuch_database_upgrade (notmuch_database_t *notmuch,

message = notmuch_messages_get (messages);

-   filename = _notmuch_message_talloc_copy_data (message);
-   if (filename && *filename != '\0') {
-   _notmuch_message_add_filename (message, filename);
-   _notmuch_message_clear_data (message);
-   _notmuch_message_sync (message);
+   /* Before version 1, each message document had its
+* filename in the data field. Copy that into the new
+* format by calling notmuch_message_add_filename.
+*/
+   if (new_features & NOTMUCH_FEATURE_FILE_TERMS) {
+   filename = _notmuch_message_talloc_copy_data (message);
+   if (filename && *filename != '\0') {
+   _notmuch_message_add_filename (message, filename);
+   _notmuch_message_clear_data (message);
+   }
+   talloc_free (filename);
}
-   talloc_free (filename);
+
+   /* Prior to version 2, the "folder:" prefix was
+* probabilistic and stemmed. Change it to the current
+* boolean prefix. Add "path:" prefixes while at it.
+*/
+   if (new_features & NOTMUCH_FEATURE_BOOL_FOLDER)
+   _notmuch_message_upgrade_folder (message);
+
+   _notmuch_message_sync (message);

notmuch_message_destroy (message);

@@ -1280,7 +1292,9 @@ notmuch_database_upgrade (notmuch_database_t *notmuch,
notmuch_query_destroy (query);
 }

-/* Also, before version 1 we stored directory timestamps in
+/* Perform per-directory upgrades. */
+
+/* Before version 1 we stored directory timestamps in
  * XTIMESTAMP documents instead of the current XDIRECTORY
  * documents. So copy those as well. */
 if (new_features & NOTMUCH_FEATURE_DIRECTORY_DOCS) {
@@ -1322,40 +1336,6 @@ notmuch_database_upgrade (notmuch_database_t *notmuch,
}
 }

-/*
- * Prior to version 2, the "folder:" prefix was probabilistic and
- * stemmed. Change it to the current boolean prefix. Add "path:"
- * prefixes while at it.
- */
-if (new_features & NOTMUCH_FEATURE_BOOL_FOLDER) {
-   notmuch_query_t *query = notmuch_query_create (notmuch, "");
-   notmuch_messages_t *messages;
-   notmuch_message_t *message;
-
-   count = 0;
-   total = notmuch_query_count_messages (query);
-
-   for (messages = notmuch_query_search_messages (query);
-notmuch_messages_valid (messages);
-notmuch_messages_move_to_next (messages)) {
-   if (do_progress_notify) {
-   progress_notify (closure, (double) count / total);
-   do_progress_notify = 0;
-   }
-
-   message = notmuch_messages_get (messages);
-
-   _notmuch_message_upgrade_folder (message);
-   _notmuch_message_sync (message);
-
-   notmuch_message_destroy (message);
-
-   count++;
-   }
-
-   notmuch_query_destroy (query);
-}
-
 db->set_metadata ("features", _print_features (local, notmuch->features));
 db->set_metadata ("version", STRINGIFY (NOTMUCH_DATABASE_VERSION));

-- 
2.0.0



[PATCH v3 08/13] lib: Use database features to drive upgrade

2014-07-31 Thread Austin Clements
Previously, we had database version information hard-coded in the
upgrade code.  Slightly re-organize the upgrade process around the set
of new database features to be enabled by the upgrade.
---
 lib/database.cc | 24 +---
 1 file changed, 13 insertions(+), 11 deletions(-)

diff --git a/lib/database.cc b/lib/database.cc
index faeab51..69d775f 100644
--- a/lib/database.cc
+++ b/lib/database.cc
@@ -1195,11 +1195,12 @@ notmuch_database_upgrade (notmuch_database_t *notmuch,
  void *closure)
 {
 void *local = talloc_new (NULL);
+Xapian::TermIterator t, t_end;
 Xapian::WritableDatabase *db;
 struct sigaction action;
 struct itimerval timerval;
 notmuch_bool_t timer_is_active = FALSE;
-unsigned int version;
+unsigned int target_features, new_features;
 notmuch_status_t status;
 unsigned int count = 0, total = 0;

@@ -1209,9 +1210,10 @@ notmuch_database_upgrade (notmuch_database_t *notmuch,

 db = static_cast  (notmuch->xapian_db);

-version = notmuch_database_get_version (notmuch);
+target_features = notmuch->features | NOTMUCH_FEATURES_CURRENT;
+new_features = NOTMUCH_FEATURES_CURRENT & ~notmuch->features;

-if (version >= NOTMUCH_DATABASE_VERSION)
+if (! new_features)
return NOTMUCH_STATUS_SUCCESS;

 if (progress_notify) {
@@ -1237,18 +1239,17 @@ notmuch_database_upgrade (notmuch_database_t *notmuch,

 /* Set the target features so we write out changes in the desired
  * format. */
-notmuch->features |= NOTMUCH_FEATURES_CURRENT;
+notmuch->features = target_features;

 /* Before version 1, each message document had its filename in the
  * data field. Copy that into the new format by calling
  * notmuch_message_add_filename.
  */
-if (version < 1) {
+if (new_features & NOTMUCH_FEATURE_FILE_TERMS) {
notmuch_query_t *query = notmuch_query_create (notmuch, "");
notmuch_messages_t *messages;
notmuch_message_t *message;
char *filename;
-   Xapian::TermIterator t, t_end;

total = notmuch_query_count_messages (query);

@@ -1277,11 +1278,12 @@ notmuch_database_upgrade (notmuch_database_t *notmuch,
}

notmuch_query_destroy (query);
+}

-   /* Also, before version 1 we stored directory timestamps in
-* XTIMESTAMP documents instead of the current XDIRECTORY
-* documents. So copy those as well. */
-
+/* Also, before version 1 we stored directory timestamps in
+ * XTIMESTAMP documents instead of the current XDIRECTORY
+ * documents. So copy those as well. */
+if (new_features & NOTMUCH_FEATURE_DIRECTORY_DOCS) {
t_end = notmuch->xapian_db->allterms_end ("XTIMESTAMP");

for (t = notmuch->xapian_db->allterms_begin ("XTIMESTAMP");
@@ -1325,7 +1327,7 @@ notmuch_database_upgrade (notmuch_database_t *notmuch,
  * stemmed. Change it to the current boolean prefix. Add "path:"
  * prefixes while at it.
  */
-if (version < 2) {
+if (new_features & NOTMUCH_FEATURE_BOOL_FOLDER) {
notmuch_query_t *query = notmuch_query_create (notmuch, "");
notmuch_messages_t *messages;
notmuch_message_t *message;
-- 
2.0.0



[PATCH v3 07/13] lib: Simplify upgrade code using a transaction

2014-07-31 Thread Austin Clements
Previously, the upgrade was organized as two passes -- an upgrade
pass, and a separate cleanup pass -- so the database was always in a
valid state.  This change substantially simplifies this code by
performing the upgrade in a transaction and combining both passes in
to one.  This 1) eliminates a lot of duplicate code between the
passes, 2) speeds up the upgrade process, 3) makes progress reporting
more accurate, 4) eliminates the potential for stale data if the
upgrade is interrupted during the cleanup pass, and 5) makes it easier
to reason about the safety of the upgrade code.
---
 lib/database.cc | 67 ++---
 1 file changed, 7 insertions(+), 60 deletions(-)

diff --git a/lib/database.cc b/lib/database.cc
index 29a56db..faeab51 100644
--- a/lib/database.cc
+++ b/lib/database.cc
@@ -1232,6 +1232,9 @@ notmuch_database_upgrade (notmuch_database_t *notmuch,
timer_is_active = TRUE;
 }

+/* Perform the upgrade in a transaction. */
+db->begin_transaction (true);
+
 /* Set the target features so we write out changes in the desired
  * format. */
 notmuch->features |= NOTMUCH_FEATURES_CURRENT;
@@ -1263,6 +1266,7 @@ notmuch_database_upgrade (notmuch_database_t *notmuch,
filename = _notmuch_message_talloc_copy_data (message);
if (filename && *filename != '\0') {
_notmuch_message_add_filename (message, filename);
+   _notmuch_message_clear_data (message);
_notmuch_message_sync (message);
}
talloc_free (filename);
@@ -1310,6 +1314,8 @@ notmuch_database_upgrade (notmuch_database_t *notmuch,
   NOTMUCH_FIND_CREATE, 
&status);
notmuch_directory_set_mtime (directory, mtime);
notmuch_directory_destroy (directory);
+
+   db->delete_document (*p);
}
}
 }
@@ -1350,67 +1356,8 @@ notmuch_database_upgrade (notmuch_database_t *notmuch,

 db->set_metadata ("features", _print_features (local, notmuch->features));
 db->set_metadata ("version", STRINGIFY (NOTMUCH_DATABASE_VERSION));
-db->flush ();
-
-/* Now that the upgrade is complete we can remove the old data
- * and documents that are no longer needed. */
-if (version < 1) {
-   notmuch_query_t *query = notmuch_query_create (notmuch, "");
-   notmuch_messages_t *messages;
-   notmuch_message_t *message;
-   char *filename;
-
-   for (messages = notmuch_query_search_messages (query);
-notmuch_messages_valid (messages);
-notmuch_messages_move_to_next (messages))
-   {
-   if (do_progress_notify) {
-   progress_notify (closure, (double) count / total);
-   do_progress_notify = 0;
-   }
-
-   message = notmuch_messages_get (messages);
-
-   filename = _notmuch_message_talloc_copy_data (message);
-   if (filename && *filename != '\0') {
-   _notmuch_message_clear_data (message);
-   _notmuch_message_sync (message);
-   }
-   talloc_free (filename);
-
-   notmuch_message_destroy (message);
-   }

-   notmuch_query_destroy (query);
-}
-
-if (version < 1) {
-   Xapian::TermIterator t, t_end;
-
-   t_end = notmuch->xapian_db->allterms_end ("XTIMESTAMP");
-
-   for (t = notmuch->xapian_db->allterms_begin ("XTIMESTAMP");
-t != t_end;
-t++)
-   {
-   Xapian::PostingIterator p, p_end;
-   std::string term = *t;
-
-   p_end = notmuch->xapian_db->postlist_end (term);
-
-   for (p = notmuch->xapian_db->postlist_begin (term);
-p != p_end;
-p++)
-   {
-   if (do_progress_notify) {
-   progress_notify (closure, (double) count / total);
-   do_progress_notify = 0;
-   }
-
-   db->delete_document (*p);
-   }
-   }
-}
+db->commit_transaction ();

 if (timer_is_active) {
/* Now stop the timer. */
-- 
2.0.0



[PATCH v3 06/13] test: Tests for future version and unknown feature handling

2014-07-31 Thread Austin Clements
---
 test/T550-db-features.sh | 48 
 1 file changed, 48 insertions(+)
 create mode 100755 test/T550-db-features.sh

diff --git a/test/T550-db-features.sh b/test/T550-db-features.sh
new file mode 100755
index 000..5569768
--- /dev/null
+++ b/test/T550-db-features.sh
@@ -0,0 +1,48 @@
+#!/usr/bin/env bash
+test_description="database version and feature compatibility"
+
+. ./test-lib.sh
+
+test_begin_subtest "future database versions abort open"
+${TEST_DIRECTORY}/make-db-version ${MAIL_DIR}  ""
+output=$(notmuch search x 2>&1 | sed 's/\(database at\) .*/\1 FILENAME/')
+rm -rf ${MAIL_DIR}/.notmuch
+test_expect_equal "$output" "\
+Error: Notmuch database at FILENAME
+   has a newer database format version () than supported by this
+   version of notmuch (3)."
+
+test_begin_subtest "unknown 'rw' feature aborts read/write open"
+${TEST_DIRECTORY}/make-db-version ${MAIL_DIR} 3 $'test feature\trw'
+output=$(notmuch new 2>&1 | sed 's/\(database at\) .*/\1 FILENAME/')
+rm -rf ${MAIL_DIR}/.notmuch
+test_expect_equal "$output" "\
+Error: Notmuch database at FILENAME
+   requires features (test feature)
+   not supported by this version of notmuch."
+
+test_begin_subtest "unknown 'rw' feature aborts read-only open"
+${TEST_DIRECTORY}/make-db-version ${MAIL_DIR} 3 $'test feature\trw'
+output=$(notmuch search x 2>&1 | sed 's/\(database at\) .*/\1 FILENAME/')
+rm -rf ${MAIL_DIR}/.notmuch
+test_expect_equal "$output" "\
+Error: Notmuch database at FILENAME
+   requires features (test feature)
+   not supported by this version of notmuch."
+
+test_begin_subtest "unknown 'w' feature aborts read/write open"
+${TEST_DIRECTORY}/make-db-version ${MAIL_DIR} 3 $'test feature\tw'
+output=$(notmuch new 2>&1 | sed 's/\(database at\) .*/\1 FILENAME/')
+rm -rf ${MAIL_DIR}/.notmuch
+test_expect_equal "$output" "\
+Error: Notmuch database at FILENAME
+   requires features (test feature)
+   not supported by this version of notmuch."
+
+test_begin_subtest "unknown 'w' feature does not abort read-only open"
+${TEST_DIRECTORY}/make-db-version ${MAIL_DIR} 3 $'test feature\tw'
+output=$(notmuch search x 2>&1 | sed 's/\(database at\) .*/\1 FILENAME/')
+rm -rf ${MAIL_DIR}/.notmuch
+test_expect_equal "$output" ""
+
+test_done
-- 
2.0.0



[PATCH v3 05/13] test: Tool to build DB with specific version and features

2014-07-31 Thread Austin Clements
This will let us test basic version and feature handling.
---
 test/.gitignore |  1 +
 test/Makefile.local |  4 
 test/make-db-version.cc | 35 +++
 3 files changed, 40 insertions(+)
 create mode 100644 test/make-db-version.cc

diff --git a/test/.gitignore b/test/.gitignore
index b3b706d..0f7d5bf 100644
--- a/test/.gitignore
+++ b/test/.gitignore
@@ -5,5 +5,6 @@ parse-time
 random-corpus
 smtp-dummy
 symbol-test
+make-db-version
 test-results
 tmp.*
diff --git a/test/Makefile.local b/test/Makefile.local
index 916dd0b..a2d58fc 100644
--- a/test/Makefile.local
+++ b/test/Makefile.local
@@ -35,6 +35,9 @@ $(dir)/symbol-test: $(dir)/symbol-test.o lib/$(LINKER_NAME)
 $(dir)/parse-time: $(dir)/parse-time.o parse-time-string/parse-time-string.o
$(call quiet,CC) $^ -o $@

+$(dir)/make-db-version: $(dir)/make-db-version.o
+   $(call quiet,CXX) $^ -o $@ $(XAPIAN_LDFLAGS)
+
 .PHONY: test check

 test_main_srcs=$(dir)/arg-test.c \
@@ -43,6 +46,7 @@ test_main_srcs=$(dir)/arg-test.c \
  $(dir)/parse-time.c \
  $(dir)/smtp-dummy.c \
  $(dir)/symbol-test.cc \
+ $(dir)/make-db-version.cc \

 test_srcs=$(test_main_srcs) $(dir)/database-test.c

diff --git a/test/make-db-version.cc b/test/make-db-version.cc
new file mode 100644
index 000..fa80cac
--- /dev/null
+++ b/test/make-db-version.cc
@@ -0,0 +1,35 @@
+/* Create an empty notmuch database with a specific version and
+ * features. */
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+int main(int argc, char **argv)
+{
+if (argc != 4) {
+   fprintf (stderr, "Usage: %s mailpath version features\n", argv[0]);
+   exit (2);
+}
+
+std::string nmpath (argv[1]);
+nmpath += "/.notmuch";
+if (mkdir (nmpath.c_str (), 0777) < 0) {
+   perror (("failed to create " + nmpath).c_str ());
+   exit (1);
+}
+
+try {
+   Xapian::WritableDatabase db (
+   nmpath + "/xapian", Xapian::DB_CREATE_OR_OPEN);
+   db.set_metadata ("version", argv[2]);
+   db.set_metadata ("features", argv[3]);
+   db.commit ();
+} catch (const Xapian::Error &e) {
+   fprintf (stderr, "%s\n", e.get_description ().c_str ());
+   exit (1);
+}
+}
-- 
2.0.0



[PATCH v3 04/13] lib: Database version 3: Introduce fine-grained "features"

2014-07-31 Thread Austin Clements
Previously, our database schema was versioned by a single number.
Each database schema change had to occur "atomically" in Notmuch's
development history: before some commit, Notmuch used version N, after
that commit, it used version N+1.  Hence, each new schema version
could introduce only one change, the task of developing a schema
change fell on a single person, and it all had to happen and be
perfect in a single commit series.  This made introducing a new schema
version hard.  We've seen only two schema changes in the history of
Notmuch.

This commit introduces database schema version 3; hopefully the last
schema version we'll need for a while.  With this version, we switch
from a single version number to "features": a set of named,
independent aspects of the database schema.

Features should make backwards compatibility easier.  For many things,
it should be easy to support databases both with and without a
feature, which will allow us to make upgrades optional and will enable
"unstable" features that can be developed and tested over time.

Features also make forwards compatibility easier.  The features
recorded in a database include "compatibility flags," which can
indicate to an older version of Notmuch when it must support a given
feature to open the database for read or for write.  This lets us
replace the old vague "I don't recognize this version, so something
might go wrong, but I promise to try my best" warnings upon opening a
database with an unknown version with precise errors.  If a database
is safe to open for read/write despite unknown features, an older
version will know that and issue no message at all.  If the database
is not safe to open for read/write because of unknown features, an
older version will know that, too, and can tell the user exactly which
required features it lacks support for.
---
 lib/database-private.h |  57 ++-
 lib/database.cc| 190 -
 2 files changed, 213 insertions(+), 34 deletions(-)

diff --git a/lib/database-private.h b/lib/database-private.h
index d3e65fd..2ffab33 100644
--- a/lib/database-private.h
+++ b/lib/database-private.h
@@ -41,11 +41,15 @@ struct _notmuch_database {

 char *path;

-notmuch_bool_t needs_upgrade;
 notmuch_database_mode_t mode;
 int atomic_nesting;
 Xapian::Database *xapian_db;

+/* Bit mask of features used by this database.  Features are
+ * named, independent aspects of the database schema.  This is a
+ * bitwise-OR of NOTMUCH_FEATURE_* values (below). */
+unsigned int features;
+
 unsigned int last_doc_id;
 uint64_t last_thread_id;

@@ -55,6 +59,57 @@ struct _notmuch_database {
 Xapian::ValueRangeProcessor *date_range_processor;
 };

+/* Bit masks for _notmuch_database::features. */
+enum {
+/* If set, file names are stored in "file-direntry" terms.  If
+ * unset, file names are stored in document data.
+ *
+ * Introduced: version 1.  Implementation support: both for read;
+ * required for write. */
+NOTMUCH_FEATURE_FILE_TERMS = 1 << 0,
+
+/* If set, directory timestamps are stored in documents with
+ * XDIRECTORY terms and relative paths.  If unset, directory
+ * timestamps are stored in documents with XTIMESTAMP terms and
+ * absolute paths.
+ *
+ * Introduced: version 1.  Implementation support: required. */
+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*
+ * have these values, but if the value is empty, it must be
+ * retrieved from the message file.
+ *
+ * Introduced: optional in version 1, required as of version 3.
+ * Implementation support: both.
+ */
+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.  Implementation support: required. */
+NOTMUCH_FEATURE_BOOL_FOLDER = 1 << 3,
+};
+
+/* Prior to database version 3, features were implied by the database
+ * version number, so hard-code them for earlier versions. */
+#define NOTMUCH_FEATURES_V0 (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)
+
+/* Current database features.  If any of these are missing from a
+ * database, request an upgrade.
+ * NOTMUCH_FEATURE_FROM_SUBJECT_ID_VALUES is not included because
+ * upgrade doesn't currently introduce the feature (though brand new
+ * databases will have it). */
+#define NOTMUCH_FEATURES_CURRENT \
+(NOTMUCH_FEATURE_FILE_TERMS | NOTMUCH_FEATURE_DIRECTORY_DOCS | \
+ NOTMUCH_FEATURE_BOOL_FOLDER)
+
 /* Return the list of te

[PATCH v3 03/13] new: Don't report version after upgrade

2014-07-31 Thread Austin Clements
The version number has always been pretty meaningless to the user and
it's about to become even more meaningless with the introduction of
"features".  Hopefully, the database will remain on version 3 for some
time to come; however, the introduction of new features over time in
version 3 will necessitate upgrades within version 3.  It would be
confusing if we always tell the user they've been "upgraded to version
3".  If the user wants to know what's new, they should read the news.
---
 notmuch-new.c| 3 +--
 test/T530-upgrade.sh | 2 +-
 2 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/notmuch-new.c b/notmuch-new.c
index d269c7c..b7590a8 100644
--- a/notmuch-new.c
+++ b/notmuch-new.c
@@ -1023,8 +1023,7 @@ notmuch_new_command (notmuch_config_t *config, int argc, 
char *argv[])
  add_files_state.verbosity >= 
VERBOSITY_NORMAL ? upgrade_print_progress : NULL,
  &add_files_state);
if (add_files_state.verbosity >= VERBOSITY_NORMAL)
-   printf ("Your notmuch database has now been upgraded to 
database format version %u.\n",
-   notmuch_database_get_version (notmuch));
+   printf ("Your notmuch database has now been upgraded.\n");
}

add_files_state.total_files = 0;
diff --git a/test/T530-upgrade.sh b/test/T530-upgrade.sh
index 7d5d5aa..c4c4ac8 100755
--- a/test/T530-upgrade.sh
+++ b/test/T530-upgrade.sh
@@ -33,7 +33,7 @@ test_expect_equal "$output" "\
 Welcome to a new version of notmuch! Your database will now be upgraded.
 This process is safe to interrupt.
 Backing up tags to FILENAME
-Your notmuch database has now been upgraded to database format version 2.
+Your notmuch database has now been upgraded.
 No new mail."

 test_begin_subtest "tag backup matches pre-upgrade dump"
-- 
2.0.0



[PATCH v3 02/13] util: Const version of strtok_len

2014-07-31 Thread Austin Clements
Because of limitations in the C type system, we can't a strtok_len
that can work on both const string and non-const strings.  The C
library solves this by taking a const char* and returning a char*
in functions like this (e.g., strchr), but that's not const-safe.
Solve it by introducing strtok_len_c, a version of strtok_len for
const strings.
---
 util/string-util.c | 8 
 util/string-util.h | 3 +++
 2 files changed, 11 insertions(+)

diff --git a/util/string-util.c b/util/string-util.c
index 3e7066c..a90501e 100644
--- a/util/string-util.c
+++ b/util/string-util.c
@@ -37,6 +37,14 @@ strtok_len (char *s, const char *delim, size_t *len)
 return *len ? s : NULL;
 }

+const char *
+strtok_len_c (const char *s, const char *delim, size_t *len)
+{
+/* strtok_len is already const-safe, but we can't express both
+ * versions in the C type system. */
+return strtok_len ((char*)s, delim, len);
+}
+
 char *
 sanitize_string (const void *ctx, const char *str)
 {
diff --git a/util/string-util.h b/util/string-util.h
index ccad17f..e409cb3 100644
--- a/util/string-util.h
+++ b/util/string-util.h
@@ -23,6 +23,9 @@ extern "C" {

 char *strtok_len (char *s, const char *delim, size_t *len);

+/* Const version of strtok_len. */
+const char *strtok_len_c (const char *s, const char *delim, size_t *len);
+
 /* Return a talloced string with str sanitized.
  *
  * Whitespace characters (tabs and newlines) are replaced with spaces,
-- 
2.0.0



[PATCH v3 01/13] test: Include generated dependencies for test sources

2014-07-31 Thread Austin Clements
Previously the build system was generating automatic header
dependencies for test sources, but only smtp-dummy was in SRCS, so
only its dependencies were being included.  Add all of the test
sources to SRCS so that the root Makefile.local includes their
dependencies.
---
 test/Makefile.local | 19 ---
 1 file changed, 12 insertions(+), 7 deletions(-)

diff --git a/test/Makefile.local b/test/Makefile.local
index 1c85b18..916dd0b 100644
--- a/test/Makefile.local
+++ b/test/Makefile.local
@@ -37,12 +37,17 @@ $(dir)/parse-time: $(dir)/parse-time.o 
parse-time-string/parse-time-string.o

 .PHONY: test check

-TEST_BINARIES=$(dir)/arg-test \
- $(dir)/hex-xcode \
- $(dir)/random-corpus \
- $(dir)/parse-time \
- $(dir)/smtp-dummy \
- $(dir)/symbol-test
+test_main_srcs=$(dir)/arg-test.c \
+ $(dir)/hex-xcode.c \
+ $(dir)/random-corpus.c \
+ $(dir)/parse-time.c \
+ $(dir)/smtp-dummy.c \
+ $(dir)/symbol-test.cc \
+
+test_srcs=$(test_main_srcs) $(dir)/database-test.c
+
+TEST_BINARIES := $(test_main_srcs:.c=)
+TEST_BINARIES := $(TEST_BINARIES:.cc=)

 test-binaries: $(TEST_BINARIES)

@@ -51,7 +56,7 @@ test: all test-binaries

 check: test

-SRCS := $(SRCS) $(smtp_dummy_srcs)
+SRCS := $(SRCS) $(test_srcs)
 CLEAN += $(TEST_BINARIES) $(addsuffix .o,$(TEST_BINARIES)) \
 $(dir)/database-test.o \
 $(dir)/corpus.mail $(dir)/test-results $(dir)/tmp.*
-- 
2.0.0



[PATCH v3 00/13] Implement and use database "features"

2014-07-31 Thread Austin Clements
This is v3 of id:1406652492-27803-1-git-send-email-amdragon at mit.edu.
This fixes one issue and tidies up another thing in
notmuch_database_upgrade I found while working on change tracking
support.  Most of the patches are logically identical to v2, but the
changes ripple through the patch context, so I'm sending a new series.

First, this updates notmuch->features before starting the upgrade,
rather than after, so that functions called by upgrade will use the
new database features instead of the old (this didn't matter in this
series because nothing modified the database differently depending on
features).  Second, this combines multiple _notmuch_message_sync calls
into one, which cleans up the code, should further improve upgrade
performance, and makes way for additional per-message upgrades.

The diff from v2 is below (excluding patch 2, which David pushed).

diff --git a/lib/database.cc b/lib/database.cc
index b323691..d90a924 100644
--- a/lib/database.cc
+++ b/lib/database.cc
@@ -1252,6 +1252,10 @@ notmuch_database_upgrade (notmuch_database_t *notmuch,
 /* Perform the upgrade in a transaction. */
 db->begin_transaction (true);

+/* Set the target features so we write out changes in the desired
+ * format. */
+notmuch->features = target_features;
+
 /* Perform per-message upgrades. */
 if (new_features &
(NOTMUCH_FEATURE_FILE_TERMS | NOTMUCH_FEATURE_BOOL_FOLDER)) {
@@ -1280,7 +1284,6 @@ notmuch_database_upgrade (notmuch_database_t *notmuch,
if (filename && *filename != '\0') {
_notmuch_message_add_filename (message, filename);
_notmuch_message_clear_data (message);
-   _notmuch_message_sync (message);
}
talloc_free (filename);
}
@@ -1289,10 +1292,10 @@ notmuch_database_upgrade (notmuch_database_t *notmuch,
 * probabilistic and stemmed. Change it to the current
 * boolean prefix. Add "path:" prefixes while at it.
 */
-   if (new_features & NOTMUCH_FEATURE_BOOL_FOLDER) {
+   if (new_features & NOTMUCH_FEATURE_BOOL_FOLDER)
_notmuch_message_upgrade_folder (message);
-   _notmuch_message_sync (message);
-   }
+
+   _notmuch_message_sync (message);

notmuch_message_destroy (message);

@@ -1348,7 +1351,6 @@ notmuch_database_upgrade (notmuch_database_t *notmuch,
}
 }

-notmuch->features = target_features;
 db->set_metadata ("features", _print_features (local, notmuch->features));
 db->set_metadata ("version", STRINGIFY (NOTMUCH_DATABASE_VERSION));



[PATCH RFC] Emacs: Add address completion mechanism implemented in elisp

2014-07-31 Thread David Bremner
Michal Sojka  writes:

> notmuch-company.el hooks itself into message-mode and uses
> company-mode to offer the completion to the user. The file is put into
> the contrib directory which means that the use has to install it
> himself. This is because company-mode is not a part of Emacs and
> bytecompiling notmuch-company.el fails due to used --quick option that
> causes user installed packages to be ignored. 

what about for now just putting 

;; -*-no-byte-compile: t; -*-

at the top of the file?  It seems usable uncompiled to me.

Then somebody who really wants it compiled can figure out how to do the
conditional compilation.

> It would probably make sense to implement another completion frontend
> based only on Emacs built-in functionality and integrate it with
> notmuch-addresses.el.

Agreed.

> +  "`company-mode' completion back-end for `nevermore (nm)'."

missed "nevermore" ;)


>  
> +(defun notmuch-flatten-thread-set (thread-set)
> +  "Convert the result of 'notmuch show' to the plain list of messages."
> +(defun notmuch-flatten-thread (thread)
> +
> +(defun notmuch-flatten-thread-node (thread-node)


what about putting those functions in notmuch-query.el?


> +(defun notmuch-async-harvest ()
> +  "Collect possible addresses for completion. It queries the


logically it seems like this might belong in notmuch-address.el,
even if none of the functions in  in it currently use


d


[PATCH] lib: Invalidate message metadata in _notmuch_message_gen_terms

2014-07-31 Thread Austin Clements
Previously, we invalidated stored message metadata in
_notmuch_message_add_term and _notmuch_message_remove_term, but not in
_notmuch_message_gen_terms.  This doesn't currently result in any bugs
because of our limited uses of _notmuch_message_gen_terms, but it may
could cause trouble in the future.
---
 lib/message.cc | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/lib/message.cc b/lib/message.cc
index 1618e81..cde6a1c 100644
--- a/lib/message.cc
+++ b/lib/message.cc
@@ -1049,6 +1049,8 @@ _notmuch_message_gen_terms (notmuch_message_t *message,
/* Create a gap between this an the next terms so they don't
 * appear to be a phrase. */
message->termpos = term_gen->get_termpos () + 100;
+
+   _notmuch_message_invalidate_metadata (message, prefix_name);
 }
 
 term_gen->set_termpos (message->termpos);
-- 
2.0.0

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH] lib: Fix slight misinformation in the database schema doc

2014-07-31 Thread Austin Clements
The database schema documentation made it sound like each mail
document had exactly one on-disk message file, which hasn't been true
for a long time.
---
 lib/database.cc | 9 ++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/lib/database.cc b/lib/database.cc
index d90a924..c70ce63 100644
--- a/lib/database.cc
+++ b/lib/database.cc
@@ -55,9 +55,12 @@ typedef struct {
  *
  * Mail document
  * -
- * A mail document is associated with a particular email message file
- * on disk. It is indexed with the following prefixed terms which the
- * database uses to construct threads, etc.:
+ * A mail document is associated with a particular email message. It
+ * is stored in one or more files on disk (though only one has its
+ * content indexed) and is uniquely identified  by its "id" field
+ * (which is generally the message ID). It is indexed with the
+ * following prefixed terms which the database uses to construct
+ * threads, etc.:
  *
  *Single terms of given prefix:
  *
-- 
2.0.0

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


Custom Tag Images

2014-07-31 Thread MaDhAt2r

Hello Everyone.

 If this is not the place to address this issue, could you please
 direct me to the proper forum.

 Info: Using Emacs 24.3.1 on ArchLinux

 I am interested in setting up custom image for some of the tags I use.

 I have tried to use a svg file by setting it in the following ways:

 (defun notmuch-tag-list-icon ()
   "Return SVG data representing a list.
 This can be used with `notmuch-tag-format-image-data'."

 " 
 
 http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\";>
 http://www.w3.org/2000/svg\"; 
xmlns:xlink=\"http://www.w3.org/1999/xlink\"; width=\"16\" height=\"16\" 
viewBox=\"0 0 16 16\">
 
 
 
 
  ")

 and setting it like I do the default images. e.g.
 (setq notmuch-tag-formats '(
 ("flagged" (notmuch-tag-format-image-data tag 
(notmuch-tag-star-icon)))
 ("lists" (notmuch-tag-format-image-data tag 
(notmuch-tag-list-icon)))
 ))

 I have also tried via the customize image setting and using the path to
 the file.

 Both ways produce nothing but a colored rectangle.

 I have downloaded the file in question from http://IcoMoon.io

 Am I missing something obvious here, or is this svg perhaps formatted
 incorrectly for notmuch emacs?

 Any pointers in the right direction are greatly appreciated.

 Thanks.


Custom Tag Images

2014-07-31 Thread MaDhAt2r

Hello Everyone.

 If this is not the place to address this issue, could you please
 direct me to the proper forum.

 Info: Using Emacs 24.3.1 on ArchLinux

 I am interested in setting up custom image for some of the tags I use.

 I have tried to use a svg file by setting it in the following ways:

 (defun notmuch-tag-list-icon ()
   "Return SVG data representing a list.
 This can be used with `notmuch-tag-format-image-data'."

 " 
 
 http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\";>
 http://www.w3.org/2000/svg\"; 
xmlns:xlink=\"http://www.w3.org/1999/xlink\"; width=\"16\" height=\"16\" 
viewBox=\"0 0 16 16\">
 
 
 
 
  ")

 and setting it like I do the default images. e.g.
 (setq notmuch-tag-formats '(
 ("flagged" (notmuch-tag-format-image-data tag 
(notmuch-tag-star-icon)))
 ("lists" (notmuch-tag-format-image-data tag 
(notmuch-tag-list-icon)))
 ))

 I have also tried via the customize image setting and using the path to
 the file.

 Both ways produce nothing but a colored rectangle.

 I have downloaded the file in question from http://IcoMoon.io

 Am I missing something obvious here, or is this svg perhaps formatted
 incorrectly for notmuch emacs?

 Any pointers in the right direction are greatly appreciated.

 Thanks.


[PATCH v3 13/13] lib: Update doc of notmuch_database_{needs_upgrade, upgrade}

2014-07-31 Thread Austin Clements
Clients are no longer required to call these functions after opening a
database in read/write mode (which is good, because almost none of
them do!).
---
 lib/notmuch.h | 21 -
 1 file changed, 12 insertions(+), 9 deletions(-)

diff --git a/lib/notmuch.h b/lib/notmuch.h
index cbf2ba5..d771eb2 100644
--- a/lib/notmuch.h
+++ b/lib/notmuch.h
@@ -352,22 +352,25 @@ unsigned int
 notmuch_database_get_version (notmuch_database_t *database);
 
 /**
- * Does this database need to be upgraded before writing to it?
+ * Is the database behind the latest supported database version?
  *
- * If this function returns TRUE then no functions that modify the
- * database (notmuch_database_add_message, notmuch_message_add_tag,
- * notmuch_directory_set_mtime, etc.) will work unless the function
- * notmuch_database_upgrade is called successfully first.
+ * If this function returns TRUE, then the caller may call
+ * notmuch_database_upgrade to upgrade the database.  If the caller
+ * does not upgrade an out-of-date database, then some functions may
+ * fail with NOTMUCH_STATUS_UPGRADE_REQUIRED.
  */
 notmuch_bool_t
 notmuch_database_needs_upgrade (notmuch_database_t *database);
 
 /**
- * Upgrade the current database.
+ * Upgrade the current database to the latest supported version.
  *
- * After opening a database in read-write mode, the client should
- * check if an upgrade is needed (notmuch_database_needs_upgrade) and
- * if so, upgrade with this function before making any modifications.
+ * This ensures that all current notmuch functionality will be
+ * available on the database.  After opening a database in read-write
+ * mode, it is recommended that clients check if an upgrade is needed
+ * (notmuch_database_needs_upgrade) and if so, upgrade with this
+ * function before making any modifications.  If
+ * notmuch_database_needs_upgrade returns FALSE, this will be a no-op.
  *
  * The optional progress_notify callback can be used by the caller to
  * provide progress indication to the user. If non-NULL it will be
-- 
2.0.0

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH v3 04/13] lib: Database version 3: Introduce fine-grained "features"

2014-07-31 Thread Austin Clements
Previously, our database schema was versioned by a single number.
Each database schema change had to occur "atomically" in Notmuch's
development history: before some commit, Notmuch used version N, after
that commit, it used version N+1.  Hence, each new schema version
could introduce only one change, the task of developing a schema
change fell on a single person, and it all had to happen and be
perfect in a single commit series.  This made introducing a new schema
version hard.  We've seen only two schema changes in the history of
Notmuch.

This commit introduces database schema version 3; hopefully the last
schema version we'll need for a while.  With this version, we switch
from a single version number to "features": a set of named,
independent aspects of the database schema.

Features should make backwards compatibility easier.  For many things,
it should be easy to support databases both with and without a
feature, which will allow us to make upgrades optional and will enable
"unstable" features that can be developed and tested over time.

Features also make forwards compatibility easier.  The features
recorded in a database include "compatibility flags," which can
indicate to an older version of Notmuch when it must support a given
feature to open the database for read or for write.  This lets us
replace the old vague "I don't recognize this version, so something
might go wrong, but I promise to try my best" warnings upon opening a
database with an unknown version with precise errors.  If a database
is safe to open for read/write despite unknown features, an older
version will know that and issue no message at all.  If the database
is not safe to open for read/write because of unknown features, an
older version will know that, too, and can tell the user exactly which
required features it lacks support for.
---
 lib/database-private.h |  57 ++-
 lib/database.cc| 190 -
 2 files changed, 213 insertions(+), 34 deletions(-)

diff --git a/lib/database-private.h b/lib/database-private.h
index d3e65fd..2ffab33 100644
--- a/lib/database-private.h
+++ b/lib/database-private.h
@@ -41,11 +41,15 @@ struct _notmuch_database {
 
 char *path;
 
-notmuch_bool_t needs_upgrade;
 notmuch_database_mode_t mode;
 int atomic_nesting;
 Xapian::Database *xapian_db;
 
+/* Bit mask of features used by this database.  Features are
+ * named, independent aspects of the database schema.  This is a
+ * bitwise-OR of NOTMUCH_FEATURE_* values (below). */
+unsigned int features;
+
 unsigned int last_doc_id;
 uint64_t last_thread_id;
 
@@ -55,6 +59,57 @@ struct _notmuch_database {
 Xapian::ValueRangeProcessor *date_range_processor;
 };
 
+/* Bit masks for _notmuch_database::features. */
+enum {
+/* If set, file names are stored in "file-direntry" terms.  If
+ * unset, file names are stored in document data.
+ *
+ * Introduced: version 1.  Implementation support: both for read;
+ * required for write. */
+NOTMUCH_FEATURE_FILE_TERMS = 1 << 0,
+
+/* If set, directory timestamps are stored in documents with
+ * XDIRECTORY terms and relative paths.  If unset, directory
+ * timestamps are stored in documents with XTIMESTAMP terms and
+ * absolute paths.
+ *
+ * Introduced: version 1.  Implementation support: required. */
+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*
+ * have these values, but if the value is empty, it must be
+ * retrieved from the message file.
+ *
+ * Introduced: optional in version 1, required as of version 3.
+ * Implementation support: both.
+ */
+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.  Implementation support: required. */
+NOTMUCH_FEATURE_BOOL_FOLDER = 1 << 3,
+};
+
+/* Prior to database version 3, features were implied by the database
+ * version number, so hard-code them for earlier versions. */
+#define NOTMUCH_FEATURES_V0 (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)
+
+/* Current database features.  If any of these are missing from a
+ * database, request an upgrade.
+ * NOTMUCH_FEATURE_FROM_SUBJECT_ID_VALUES is not included because
+ * upgrade doesn't currently introduce the feature (though brand new
+ * databases will have it). */
+#define NOTMUCH_FEATURES_CURRENT \
+(NOTMUCH_FEATURE_FILE_TERMS | NOTMUCH_FEATURE_DIRECTORY_DOCS | \
+ NOTMUCH_FEATURE_BOOL_FOLDER)
+
 /* Return the list 

[PATCH v3 10/13] lib: Report progress for combined upgrade operation

2014-07-31 Thread Austin Clements
Previously, some parts of upgrade didn't report progress and for
others it was possible for the progress meter to restart at 0 part way
through the upgrade because each stage was reported separately.

Fix this by computing the total amount of work that needs to be done
up-front and updating completed work monotonically.
---
 lib/database.cc | 17 +++--
 1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/lib/database.cc b/lib/database.cc
index 31e6a93..04b3790 100644
--- a/lib/database.cc
+++ b/lib/database.cc
@@ -1234,6 +1234,19 @@ notmuch_database_upgrade (notmuch_database_t *notmuch,
timer_is_active = TRUE;
 }
 
+/* Figure out how much total work we need to do. */
+if (new_features &
+   (NOTMUCH_FEATURE_FILE_TERMS | NOTMUCH_FEATURE_BOOL_FOLDER)) {
+   notmuch_query_t *query = notmuch_query_create (notmuch, "");
+   total += notmuch_query_count_messages (query);
+   notmuch_query_destroy (query);
+}
+if (new_features & NOTMUCH_FEATURE_DIRECTORY_DOCS) {
+   t_end = db->allterms_end ("XTIMESTAMP");
+   for (t = db->allterms_begin ("XTIMESTAMP"); t != t_end; t++)
+   ++total;
+}
+
 /* Perform the upgrade in a transaction. */
 db->begin_transaction (true);
 
@@ -1249,8 +1262,6 @@ notmuch_database_upgrade (notmuch_database_t *notmuch,
notmuch_message_t *message;
char *filename;
 
-   total = notmuch_query_count_messages (query);
-
for (messages = notmuch_query_search_messages (query);
 notmuch_messages_valid (messages);
 notmuch_messages_move_to_next (messages))
@@ -1333,6 +1344,8 @@ notmuch_database_upgrade (notmuch_database_t *notmuch,
 
db->delete_document (*p);
}
+
+   ++count;
}
 }
 
-- 
2.0.0

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH v3 08/13] lib: Use database features to drive upgrade

2014-07-31 Thread Austin Clements
Previously, we had database version information hard-coded in the
upgrade code.  Slightly re-organize the upgrade process around the set
of new database features to be enabled by the upgrade.
---
 lib/database.cc | 24 +---
 1 file changed, 13 insertions(+), 11 deletions(-)

diff --git a/lib/database.cc b/lib/database.cc
index faeab51..69d775f 100644
--- a/lib/database.cc
+++ b/lib/database.cc
@@ -1195,11 +1195,12 @@ notmuch_database_upgrade (notmuch_database_t *notmuch,
  void *closure)
 {
 void *local = talloc_new (NULL);
+Xapian::TermIterator t, t_end;
 Xapian::WritableDatabase *db;
 struct sigaction action;
 struct itimerval timerval;
 notmuch_bool_t timer_is_active = FALSE;
-unsigned int version;
+unsigned int target_features, new_features;
 notmuch_status_t status;
 unsigned int count = 0, total = 0;
 
@@ -1209,9 +1210,10 @@ notmuch_database_upgrade (notmuch_database_t *notmuch,
 
 db = static_cast  (notmuch->xapian_db);
 
-version = notmuch_database_get_version (notmuch);
+target_features = notmuch->features | NOTMUCH_FEATURES_CURRENT;
+new_features = NOTMUCH_FEATURES_CURRENT & ~notmuch->features;
 
-if (version >= NOTMUCH_DATABASE_VERSION)
+if (! new_features)
return NOTMUCH_STATUS_SUCCESS;
 
 if (progress_notify) {
@@ -1237,18 +1239,17 @@ notmuch_database_upgrade (notmuch_database_t *notmuch,
 
 /* Set the target features so we write out changes in the desired
  * format. */
-notmuch->features |= NOTMUCH_FEATURES_CURRENT;
+notmuch->features = target_features;
 
 /* Before version 1, each message document had its filename in the
  * data field. Copy that into the new format by calling
  * notmuch_message_add_filename.
  */
-if (version < 1) {
+if (new_features & NOTMUCH_FEATURE_FILE_TERMS) {
notmuch_query_t *query = notmuch_query_create (notmuch, "");
notmuch_messages_t *messages;
notmuch_message_t *message;
char *filename;
-   Xapian::TermIterator t, t_end;
 
total = notmuch_query_count_messages (query);
 
@@ -1277,11 +1278,12 @@ notmuch_database_upgrade (notmuch_database_t *notmuch,
}
 
notmuch_query_destroy (query);
+}
 
-   /* Also, before version 1 we stored directory timestamps in
-* XTIMESTAMP documents instead of the current XDIRECTORY
-* documents. So copy those as well. */
-
+/* Also, before version 1 we stored directory timestamps in
+ * XTIMESTAMP documents instead of the current XDIRECTORY
+ * documents. So copy those as well. */
+if (new_features & NOTMUCH_FEATURE_DIRECTORY_DOCS) {
t_end = notmuch->xapian_db->allterms_end ("XTIMESTAMP");
 
for (t = notmuch->xapian_db->allterms_begin ("XTIMESTAMP");
@@ -1325,7 +1327,7 @@ notmuch_database_upgrade (notmuch_database_t *notmuch,
  * stemmed. Change it to the current boolean prefix. Add "path:"
  * prefixes while at it.
  */
-if (version < 2) {
+if (new_features & NOTMUCH_FEATURE_BOOL_FOLDER) {
notmuch_query_t *query = notmuch_query_create (notmuch, "");
notmuch_messages_t *messages;
notmuch_message_t *message;
-- 
2.0.0

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH v3 07/13] lib: Simplify upgrade code using a transaction

2014-07-31 Thread Austin Clements
Previously, the upgrade was organized as two passes -- an upgrade
pass, and a separate cleanup pass -- so the database was always in a
valid state.  This change substantially simplifies this code by
performing the upgrade in a transaction and combining both passes in
to one.  This 1) eliminates a lot of duplicate code between the
passes, 2) speeds up the upgrade process, 3) makes progress reporting
more accurate, 4) eliminates the potential for stale data if the
upgrade is interrupted during the cleanup pass, and 5) makes it easier
to reason about the safety of the upgrade code.
---
 lib/database.cc | 67 ++---
 1 file changed, 7 insertions(+), 60 deletions(-)

diff --git a/lib/database.cc b/lib/database.cc
index 29a56db..faeab51 100644
--- a/lib/database.cc
+++ b/lib/database.cc
@@ -1232,6 +1232,9 @@ notmuch_database_upgrade (notmuch_database_t *notmuch,
timer_is_active = TRUE;
 }
 
+/* Perform the upgrade in a transaction. */
+db->begin_transaction (true);
+
 /* Set the target features so we write out changes in the desired
  * format. */
 notmuch->features |= NOTMUCH_FEATURES_CURRENT;
@@ -1263,6 +1266,7 @@ notmuch_database_upgrade (notmuch_database_t *notmuch,
filename = _notmuch_message_talloc_copy_data (message);
if (filename && *filename != '\0') {
_notmuch_message_add_filename (message, filename);
+   _notmuch_message_clear_data (message);
_notmuch_message_sync (message);
}
talloc_free (filename);
@@ -1310,6 +1314,8 @@ notmuch_database_upgrade (notmuch_database_t *notmuch,
   NOTMUCH_FIND_CREATE, 
&status);
notmuch_directory_set_mtime (directory, mtime);
notmuch_directory_destroy (directory);
+
+   db->delete_document (*p);
}
}
 }
@@ -1350,67 +1356,8 @@ notmuch_database_upgrade (notmuch_database_t *notmuch,
 
 db->set_metadata ("features", _print_features (local, notmuch->features));
 db->set_metadata ("version", STRINGIFY (NOTMUCH_DATABASE_VERSION));
-db->flush ();
-
-/* Now that the upgrade is complete we can remove the old data
- * and documents that are no longer needed. */
-if (version < 1) {
-   notmuch_query_t *query = notmuch_query_create (notmuch, "");
-   notmuch_messages_t *messages;
-   notmuch_message_t *message;
-   char *filename;
-
-   for (messages = notmuch_query_search_messages (query);
-notmuch_messages_valid (messages);
-notmuch_messages_move_to_next (messages))
-   {
-   if (do_progress_notify) {
-   progress_notify (closure, (double) count / total);
-   do_progress_notify = 0;
-   }
-
-   message = notmuch_messages_get (messages);
-
-   filename = _notmuch_message_talloc_copy_data (message);
-   if (filename && *filename != '\0') {
-   _notmuch_message_clear_data (message);
-   _notmuch_message_sync (message);
-   }
-   talloc_free (filename);
-
-   notmuch_message_destroy (message);
-   }
 
-   notmuch_query_destroy (query);
-}
-
-if (version < 1) {
-   Xapian::TermIterator t, t_end;
-
-   t_end = notmuch->xapian_db->allterms_end ("XTIMESTAMP");
-
-   for (t = notmuch->xapian_db->allterms_begin ("XTIMESTAMP");
-t != t_end;
-t++)
-   {
-   Xapian::PostingIterator p, p_end;
-   std::string term = *t;
-
-   p_end = notmuch->xapian_db->postlist_end (term);
-
-   for (p = notmuch->xapian_db->postlist_begin (term);
-p != p_end;
-p++)
-   {
-   if (do_progress_notify) {
-   progress_notify (closure, (double) count / total);
-   do_progress_notify = 0;
-   }
-
-   db->delete_document (*p);
-   }
-   }
-}
+db->commit_transaction ();
 
 if (timer_is_active) {
/* Now stop the timer. */
-- 
2.0.0

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH v3 06/13] test: Tests for future version and unknown feature handling

2014-07-31 Thread Austin Clements
---
 test/T550-db-features.sh | 48 
 1 file changed, 48 insertions(+)
 create mode 100755 test/T550-db-features.sh

diff --git a/test/T550-db-features.sh b/test/T550-db-features.sh
new file mode 100755
index 000..5569768
--- /dev/null
+++ b/test/T550-db-features.sh
@@ -0,0 +1,48 @@
+#!/usr/bin/env bash
+test_description="database version and feature compatibility"
+
+. ./test-lib.sh
+
+test_begin_subtest "future database versions abort open"
+${TEST_DIRECTORY}/make-db-version ${MAIL_DIR}  ""
+output=$(notmuch search x 2>&1 | sed 's/\(database at\) .*/\1 FILENAME/')
+rm -rf ${MAIL_DIR}/.notmuch
+test_expect_equal "$output" "\
+Error: Notmuch database at FILENAME
+   has a newer database format version () than supported by this
+   version of notmuch (3)."
+
+test_begin_subtest "unknown 'rw' feature aborts read/write open"
+${TEST_DIRECTORY}/make-db-version ${MAIL_DIR} 3 $'test feature\trw'
+output=$(notmuch new 2>&1 | sed 's/\(database at\) .*/\1 FILENAME/')
+rm -rf ${MAIL_DIR}/.notmuch
+test_expect_equal "$output" "\
+Error: Notmuch database at FILENAME
+   requires features (test feature)
+   not supported by this version of notmuch."
+
+test_begin_subtest "unknown 'rw' feature aborts read-only open"
+${TEST_DIRECTORY}/make-db-version ${MAIL_DIR} 3 $'test feature\trw'
+output=$(notmuch search x 2>&1 | sed 's/\(database at\) .*/\1 FILENAME/')
+rm -rf ${MAIL_DIR}/.notmuch
+test_expect_equal "$output" "\
+Error: Notmuch database at FILENAME
+   requires features (test feature)
+   not supported by this version of notmuch."
+
+test_begin_subtest "unknown 'w' feature aborts read/write open"
+${TEST_DIRECTORY}/make-db-version ${MAIL_DIR} 3 $'test feature\tw'
+output=$(notmuch new 2>&1 | sed 's/\(database at\) .*/\1 FILENAME/')
+rm -rf ${MAIL_DIR}/.notmuch
+test_expect_equal "$output" "\
+Error: Notmuch database at FILENAME
+   requires features (test feature)
+   not supported by this version of notmuch."
+
+test_begin_subtest "unknown 'w' feature does not abort read-only open"
+${TEST_DIRECTORY}/make-db-version ${MAIL_DIR} 3 $'test feature\tw'
+output=$(notmuch search x 2>&1 | sed 's/\(database at\) .*/\1 FILENAME/')
+rm -rf ${MAIL_DIR}/.notmuch
+test_expect_equal "$output" ""
+
+test_done
-- 
2.0.0

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH v3 11/13] lib: Support empty header values in database

2014-07-31 Thread Austin Clements
Commit 567bcbc2 introduced support for storing various headers in
document values.  However, doing so in a backwards-compatible way
meant that genuinely empty header values could not be distinguished
from the old behavior of not storing the headers at all, so these
required parsing the original message.

Now that we have database features, new databases can declare that all
messages have header values, so if we have this feature flag, we can
use the stored header value even if it's the empty string.

This requires slight cleanup to notmuch_message_get_header, since the
code previously couldn't distinguish between empty headers and headers
that are never stored in the database (previously this distinction
didn't matter).
---
 lib/message.cc | 45 +++--
 1 file changed, 27 insertions(+), 18 deletions(-)

diff --git a/lib/message.cc b/lib/message.cc
index e6a5a5a..4fc427f 100644
--- a/lib/message.cc
+++ b/lib/message.cc
@@ -412,26 +412,35 @@ _notmuch_message_ensure_message_file (notmuch_message_t 
*message)
 const char *
 notmuch_message_get_header (notmuch_message_t *message, const char *header)
 {
-try {
-   std::string value;
-
-   /* Fetch header from the appropriate xapian value field if
-* available */
-   if (strcasecmp (header, "from") == 0)
-   value = message->doc.get_value (NOTMUCH_VALUE_FROM);
-   else if (strcasecmp (header, "subject") == 0)
-   value = message->doc.get_value (NOTMUCH_VALUE_SUBJECT);
-   else if (strcasecmp (header, "message-id") == 0)
-   value = message->doc.get_value (NOTMUCH_VALUE_MESSAGE_ID);
-
-   if (!value.empty())
+Xapian::valueno slot = Xapian::BAD_VALUENO;
+
+/* Fetch header from the appropriate xapian value field if
+ * available */
+if (strcasecmp (header, "from") == 0)
+   slot = NOTMUCH_VALUE_FROM;
+else if (strcasecmp (header, "subject") == 0)
+   slot = NOTMUCH_VALUE_SUBJECT;
+else if (strcasecmp (header, "message-id") == 0)
+   slot = NOTMUCH_VALUE_MESSAGE_ID;
+
+if (slot != Xapian::BAD_VALUENO) {
+   try {
+   std::string value = message->doc.get_value (slot);
+
+   /* If we have NOTMUCH_FEATURE_FROM_SUBJECT_ID_VALUES, then
+* empty values indicate empty headers.  If we don't, then
+* it could just mean we didn't record the header. */
+   if ((message->notmuch->features &
+NOTMUCH_FEATURE_FROM_SUBJECT_ID_VALUES) ||
+   ! value.empty())
return talloc_strdup (message, value.c_str ());
 
-} catch (Xapian::Error &error) {
-   fprintf (stderr, "A Xapian exception occurred when reading header: 
%s\n",
-error.get_msg().c_str());
-   message->notmuch->exception_reported = TRUE;
-   return NULL;
+   } catch (Xapian::Error &error) {
+   fprintf (stderr, "A Xapian exception occurred when reading header: 
%s\n",
+error.get_msg().c_str());
+   message->notmuch->exception_reported = TRUE;
+   return NULL;
+   }
 }
 
 /* Otherwise fall back to parsing the file */
-- 
2.0.0

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH v3 03/13] new: Don't report version after upgrade

2014-07-31 Thread Austin Clements
The version number has always been pretty meaningless to the user and
it's about to become even more meaningless with the introduction of
"features".  Hopefully, the database will remain on version 3 for some
time to come; however, the introduction of new features over time in
version 3 will necessitate upgrades within version 3.  It would be
confusing if we always tell the user they've been "upgraded to version
3".  If the user wants to know what's new, they should read the news.
---
 notmuch-new.c| 3 +--
 test/T530-upgrade.sh | 2 +-
 2 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/notmuch-new.c b/notmuch-new.c
index d269c7c..b7590a8 100644
--- a/notmuch-new.c
+++ b/notmuch-new.c
@@ -1023,8 +1023,7 @@ notmuch_new_command (notmuch_config_t *config, int argc, 
char *argv[])
  add_files_state.verbosity >= 
VERBOSITY_NORMAL ? upgrade_print_progress : NULL,
  &add_files_state);
if (add_files_state.verbosity >= VERBOSITY_NORMAL)
-   printf ("Your notmuch database has now been upgraded to 
database format version %u.\n",
-   notmuch_database_get_version (notmuch));
+   printf ("Your notmuch database has now been upgraded.\n");
}
 
add_files_state.total_files = 0;
diff --git a/test/T530-upgrade.sh b/test/T530-upgrade.sh
index 7d5d5aa..c4c4ac8 100755
--- a/test/T530-upgrade.sh
+++ b/test/T530-upgrade.sh
@@ -33,7 +33,7 @@ test_expect_equal "$output" "\
 Welcome to a new version of notmuch! Your database will now be upgraded.
 This process is safe to interrupt.
 Backing up tags to FILENAME
-Your notmuch database has now been upgraded to database format version 2.
+Your notmuch database has now been upgraded.
 No new mail."
 
 test_begin_subtest "tag backup matches pre-upgrade dump"
-- 
2.0.0

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH v3 05/13] test: Tool to build DB with specific version and features

2014-07-31 Thread Austin Clements
This will let us test basic version and feature handling.
---
 test/.gitignore |  1 +
 test/Makefile.local |  4 
 test/make-db-version.cc | 35 +++
 3 files changed, 40 insertions(+)
 create mode 100644 test/make-db-version.cc

diff --git a/test/.gitignore b/test/.gitignore
index b3b706d..0f7d5bf 100644
--- a/test/.gitignore
+++ b/test/.gitignore
@@ -5,5 +5,6 @@ parse-time
 random-corpus
 smtp-dummy
 symbol-test
+make-db-version
 test-results
 tmp.*
diff --git a/test/Makefile.local b/test/Makefile.local
index 916dd0b..a2d58fc 100644
--- a/test/Makefile.local
+++ b/test/Makefile.local
@@ -35,6 +35,9 @@ $(dir)/symbol-test: $(dir)/symbol-test.o lib/$(LINKER_NAME)
 $(dir)/parse-time: $(dir)/parse-time.o parse-time-string/parse-time-string.o
$(call quiet,CC) $^ -o $@
 
+$(dir)/make-db-version: $(dir)/make-db-version.o
+   $(call quiet,CXX) $^ -o $@ $(XAPIAN_LDFLAGS)
+
 .PHONY: test check
 
 test_main_srcs=$(dir)/arg-test.c \
@@ -43,6 +46,7 @@ test_main_srcs=$(dir)/arg-test.c \
  $(dir)/parse-time.c \
  $(dir)/smtp-dummy.c \
  $(dir)/symbol-test.cc \
+ $(dir)/make-db-version.cc \
 
 test_srcs=$(test_main_srcs) $(dir)/database-test.c
 
diff --git a/test/make-db-version.cc b/test/make-db-version.cc
new file mode 100644
index 000..fa80cac
--- /dev/null
+++ b/test/make-db-version.cc
@@ -0,0 +1,35 @@
+/* Create an empty notmuch database with a specific version and
+ * features. */
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+int main(int argc, char **argv)
+{
+if (argc != 4) {
+   fprintf (stderr, "Usage: %s mailpath version features\n", argv[0]);
+   exit (2);
+}
+
+std::string nmpath (argv[1]);
+nmpath += "/.notmuch";
+if (mkdir (nmpath.c_str (), 0777) < 0) {
+   perror (("failed to create " + nmpath).c_str ());
+   exit (1);
+}
+
+try {
+   Xapian::WritableDatabase db (
+   nmpath + "/xapian", Xapian::DB_CREATE_OR_OPEN);
+   db.set_metadata ("version", argv[2]);
+   db.set_metadata ("features", argv[3]);
+   db.commit ();
+} catch (const Xapian::Error &e) {
+   fprintf (stderr, "%s\n", e.get_description ().c_str ());
+   exit (1);
+}
+}
-- 
2.0.0

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH v3 12/13] lib: Return an error from operations that require an upgrade

2014-07-31 Thread Austin Clements
Previously, there was no protection against a caller invoking an
operation on an old database version that would effectively corrupt
the database by treating it like a newer version.

According to notmuch.h, any caller that opens the database in
read/write mode is supposed to check if the database needs upgrading
and perform an upgrade if it does.  This would protect against this,
but nobody (even the CLI) actually does this.

However, with features, it's easy to protect against incompatible
operations on a fine-grained basis.  This lightweight change allows
callers to safely operate on old database versions, while preventing
specific operations that would corrupt the database with an
informative error message.
---
 lib/database.cc  |  5 +
 lib/directory.cc |  5 +
 lib/message.cc   |  8 
 lib/notmuch.h| 16 
 4 files changed, 34 insertions(+)

diff --git a/lib/database.cc b/lib/database.cc
index 04b3790..d90a924 100644
--- a/lib/database.cc
+++ b/lib/database.cc
@@ -310,6 +310,8 @@ notmuch_status_to_string (notmuch_status_t status)
return "Unbalanced number of calls to 
notmuch_database_begin_atomic/end_atomic";
 case NOTMUCH_STATUS_UNSUPPORTED_OPERATION:
return "Unsupported operation";
+case NOTMUCH_STATUS_UPGRADE_REQUIRED:
+   return "Operation requires a database upgrade";
 default:
 case NOTMUCH_STATUS_LAST_STATUS:
return "Unknown error status value";
@@ -2219,6 +2221,9 @@ notmuch_database_find_message_by_filename 
(notmuch_database_t *notmuch,
 if (message_ret == NULL)
return NOTMUCH_STATUS_NULL_POINTER;
 
+if (! (notmuch->features & NOTMUCH_FEATURE_FILE_TERMS))
+   return NOTMUCH_STATUS_UPGRADE_REQUIRED;
+
 /* return NULL on any failure */
 *message_ret = NULL;
 
diff --git a/lib/directory.cc b/lib/directory.cc
index 6a3ffed..8daaec8 100644
--- a/lib/directory.cc
+++ b/lib/directory.cc
@@ -105,6 +105,11 @@ _notmuch_directory_create (notmuch_database_t *notmuch,
 const char *db_path;
 notmuch_bool_t create = (flags & NOTMUCH_FIND_CREATE);
 
+if (! (notmuch->features & NOTMUCH_FEATURE_DIRECTORY_DOCS)) {
+   *status_ret = NOTMUCH_STATUS_UPGRADE_REQUIRED;
+   return NULL;
+}
+
 *status_ret = NOTMUCH_STATUS_SUCCESS;
 
 path = _notmuch_database_relative_path (notmuch, path);
diff --git a/lib/message.cc b/lib/message.cc
index 4fc427f..1618e81 100644
--- a/lib/message.cc
+++ b/lib/message.cc
@@ -653,6 +653,10 @@ _notmuch_message_add_filename (notmuch_message_t *message,
 if (filename == NULL)
INTERNAL_ERROR ("Message filename cannot be NULL.");
 
+if (! (message->notmuch->features & NOTMUCH_FEATURE_FILE_TERMS) ||
+   ! (message->notmuch->features & NOTMUCH_FEATURE_BOOL_FOLDER))
+   return NOTMUCH_STATUS_UPGRADE_REQUIRED;
+
 relative = _notmuch_database_relative_path (message->notmuch, filename);
 
 status = _notmuch_database_split_path (local, relative, &directory, NULL);
@@ -697,6 +701,10 @@ _notmuch_message_remove_filename (notmuch_message_t 
*message,
 notmuch_private_status_t private_status;
 notmuch_status_t status;
 
+if (! (message->notmuch->features & NOTMUCH_FEATURE_FILE_TERMS) ||
+   ! (message->notmuch->features & NOTMUCH_FEATURE_BOOL_FOLDER))
+   return NOTMUCH_STATUS_UPGRADE_REQUIRED;
+
 status = _notmuch_database_filename_to_direntry (
local, message->notmuch, filename, NOTMUCH_FIND_LOOKUP, &direntry);
 if (status || !direntry)
diff --git a/lib/notmuch.h b/lib/notmuch.h
index 3c5ec98..cbf2ba5 100644
--- a/lib/notmuch.h
+++ b/lib/notmuch.h
@@ -160,6 +160,10 @@ typedef enum _notmuch_status {
  */
 NOTMUCH_STATUS_UNSUPPORTED_OPERATION,
 /**
+ * The operation requires a database upgrade.
+ */
+NOTMUCH_STATUS_UPGRADE_REQUIRED,
+/**
  * Not an actual status value. Just a way to find out how many
  * valid status values there are.
  */
@@ -438,6 +442,9 @@ notmuch_database_end_atomic (notmuch_database_t *notmuch);
  *
  * NOTMUCH_STATUS_XAPIAN_EXCEPTION: A Xapian exception occurred;
  * directory not retrieved.
+ *
+ * NOTMUCH_STATUS_UPGRADE_REQUIRED: The caller must upgrade the
+ * database to use this function.
  */
 notmuch_status_t
 notmuch_database_get_directory (notmuch_database_t *database,
@@ -490,6 +497,9 @@ notmuch_database_get_directory (notmuch_database_t 
*database,
  *
  * NOTMUCH_STATUS_READ_ONLY_DATABASE: Database was opened in read-only
  * mode so no message can be added.
+ *
+ * NOTMUCH_STATUS_UPGRADE_REQUIRED: The caller must upgrade the
+ * database to use this function.
  */
 notmuch_status_t
 notmuch_database_add_message (notmuch_database_t *database,
@@ -520,6 +530,9 @@ notmuch_database_add_message (notmuch_database_t *database,
  *
  * NOTMUCH_STATUS_READ_ONLY_DATABASE: Database was opened in read-only
  * mode so no message can be removed.
+ *
+ * NOTMUCH_STATUS_UPGRADE_REQUIRED: The caller must upgrade the
+ *

[PATCH v3 01/13] test: Include generated dependencies for test sources

2014-07-31 Thread Austin Clements
Previously the build system was generating automatic header
dependencies for test sources, but only smtp-dummy was in SRCS, so
only its dependencies were being included.  Add all of the test
sources to SRCS so that the root Makefile.local includes their
dependencies.
---
 test/Makefile.local | 19 ---
 1 file changed, 12 insertions(+), 7 deletions(-)

diff --git a/test/Makefile.local b/test/Makefile.local
index 1c85b18..916dd0b 100644
--- a/test/Makefile.local
+++ b/test/Makefile.local
@@ -37,12 +37,17 @@ $(dir)/parse-time: $(dir)/parse-time.o 
parse-time-string/parse-time-string.o
 
 .PHONY: test check
 
-TEST_BINARIES=$(dir)/arg-test \
- $(dir)/hex-xcode \
- $(dir)/random-corpus \
- $(dir)/parse-time \
- $(dir)/smtp-dummy \
- $(dir)/symbol-test
+test_main_srcs=$(dir)/arg-test.c \
+ $(dir)/hex-xcode.c \
+ $(dir)/random-corpus.c \
+ $(dir)/parse-time.c \
+ $(dir)/smtp-dummy.c \
+ $(dir)/symbol-test.cc \
+
+test_srcs=$(test_main_srcs) $(dir)/database-test.c
+
+TEST_BINARIES := $(test_main_srcs:.c=)
+TEST_BINARIES := $(TEST_BINARIES:.cc=)
 
 test-binaries: $(TEST_BINARIES)
 
@@ -51,7 +56,7 @@ test: all test-binaries
 
 check: test
 
-SRCS := $(SRCS) $(smtp_dummy_srcs)
+SRCS := $(SRCS) $(test_srcs)
 CLEAN += $(TEST_BINARIES) $(addsuffix .o,$(TEST_BINARIES)) \
 $(dir)/database-test.o \
 $(dir)/corpus.mail $(dir)/test-results $(dir)/tmp.*
-- 
2.0.0

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH v3 09/13] lib: Reorganize upgrade around document types

2014-07-31 Thread Austin Clements
Rather than potentially making multiple passes over the same type of
data in the database, reorganize upgrade around each type of data that
may be upgraded.  This eliminates code duplication, will make
multi-version upgrades faster, and will let us improve progress
reporting.
---
 lib/database.cc | 72 +
 1 file changed, 26 insertions(+), 46 deletions(-)

diff --git a/lib/database.cc b/lib/database.cc
index 69d775f..31e6a93 100644
--- a/lib/database.cc
+++ b/lib/database.cc
@@ -1241,11 +1241,9 @@ notmuch_database_upgrade (notmuch_database_t *notmuch,
  * format. */
 notmuch->features = target_features;
 
-/* Before version 1, each message document had its filename in the
- * data field. Copy that into the new format by calling
- * notmuch_message_add_filename.
- */
-if (new_features & NOTMUCH_FEATURE_FILE_TERMS) {
+/* Perform per-message upgrades. */
+if (new_features &
+   (NOTMUCH_FEATURE_FILE_TERMS | NOTMUCH_FEATURE_BOOL_FOLDER)) {
notmuch_query_t *query = notmuch_query_create (notmuch, "");
notmuch_messages_t *messages;
notmuch_message_t *message;
@@ -1264,13 +1262,27 @@ notmuch_database_upgrade (notmuch_database_t *notmuch,
 
message = notmuch_messages_get (messages);
 
-   filename = _notmuch_message_talloc_copy_data (message);
-   if (filename && *filename != '\0') {
-   _notmuch_message_add_filename (message, filename);
-   _notmuch_message_clear_data (message);
-   _notmuch_message_sync (message);
+   /* Before version 1, each message document had its
+* filename in the data field. Copy that into the new
+* format by calling notmuch_message_add_filename.
+*/
+   if (new_features & NOTMUCH_FEATURE_FILE_TERMS) {
+   filename = _notmuch_message_talloc_copy_data (message);
+   if (filename && *filename != '\0') {
+   _notmuch_message_add_filename (message, filename);
+   _notmuch_message_clear_data (message);
+   }
+   talloc_free (filename);
}
-   talloc_free (filename);
+
+   /* Prior to version 2, the "folder:" prefix was
+* probabilistic and stemmed. Change it to the current
+* boolean prefix. Add "path:" prefixes while at it.
+*/
+   if (new_features & NOTMUCH_FEATURE_BOOL_FOLDER)
+   _notmuch_message_upgrade_folder (message);
+
+   _notmuch_message_sync (message);
 
notmuch_message_destroy (message);
 
@@ -1280,7 +1292,9 @@ notmuch_database_upgrade (notmuch_database_t *notmuch,
notmuch_query_destroy (query);
 }
 
-/* Also, before version 1 we stored directory timestamps in
+/* Perform per-directory upgrades. */
+
+/* Before version 1 we stored directory timestamps in
  * XTIMESTAMP documents instead of the current XDIRECTORY
  * documents. So copy those as well. */
 if (new_features & NOTMUCH_FEATURE_DIRECTORY_DOCS) {
@@ -1322,40 +1336,6 @@ notmuch_database_upgrade (notmuch_database_t *notmuch,
}
 }
 
-/*
- * Prior to version 2, the "folder:" prefix was probabilistic and
- * stemmed. Change it to the current boolean prefix. Add "path:"
- * prefixes while at it.
- */
-if (new_features & NOTMUCH_FEATURE_BOOL_FOLDER) {
-   notmuch_query_t *query = notmuch_query_create (notmuch, "");
-   notmuch_messages_t *messages;
-   notmuch_message_t *message;
-
-   count = 0;
-   total = notmuch_query_count_messages (query);
-
-   for (messages = notmuch_query_search_messages (query);
-notmuch_messages_valid (messages);
-notmuch_messages_move_to_next (messages)) {
-   if (do_progress_notify) {
-   progress_notify (closure, (double) count / total);
-   do_progress_notify = 0;
-   }
-
-   message = notmuch_messages_get (messages);
-
-   _notmuch_message_upgrade_folder (message);
-   _notmuch_message_sync (message);
-
-   notmuch_message_destroy (message);
-
-   count++;
-   }
-
-   notmuch_query_destroy (query);
-}
-
 db->set_metadata ("features", _print_features (local, notmuch->features));
 db->set_metadata ("version", STRINGIFY (NOTMUCH_DATABASE_VERSION));
 
-- 
2.0.0

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH v3 02/13] util: Const version of strtok_len

2014-07-31 Thread Austin Clements
Because of limitations in the C type system, we can't a strtok_len
that can work on both const string and non-const strings.  The C
library solves this by taking a const char* and returning a char*
in functions like this (e.g., strchr), but that's not const-safe.
Solve it by introducing strtok_len_c, a version of strtok_len for
const strings.
---
 util/string-util.c | 8 
 util/string-util.h | 3 +++
 2 files changed, 11 insertions(+)

diff --git a/util/string-util.c b/util/string-util.c
index 3e7066c..a90501e 100644
--- a/util/string-util.c
+++ b/util/string-util.c
@@ -37,6 +37,14 @@ strtok_len (char *s, const char *delim, size_t *len)
 return *len ? s : NULL;
 }
 
+const char *
+strtok_len_c (const char *s, const char *delim, size_t *len)
+{
+/* strtok_len is already const-safe, but we can't express both
+ * versions in the C type system. */
+return strtok_len ((char*)s, delim, len);
+}
+
 char *
 sanitize_string (const void *ctx, const char *str)
 {
diff --git a/util/string-util.h b/util/string-util.h
index ccad17f..e409cb3 100644
--- a/util/string-util.h
+++ b/util/string-util.h
@@ -23,6 +23,9 @@ extern "C" {
 
 char *strtok_len (char *s, const char *delim, size_t *len);
 
+/* Const version of strtok_len. */
+const char *strtok_len_c (const char *s, const char *delim, size_t *len);
+
 /* Return a talloced string with str sanitized.
  *
  * Whitespace characters (tabs and newlines) are replaced with spaces,
-- 
2.0.0

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH v3 00/13] Implement and use database "features"

2014-07-31 Thread Austin Clements
This is v3 of id:1406652492-27803-1-git-send-email-amdra...@mit.edu.
This fixes one issue and tidies up another thing in
notmuch_database_upgrade I found while working on change tracking
support.  Most of the patches are logically identical to v2, but the
changes ripple through the patch context, so I'm sending a new series.

First, this updates notmuch->features before starting the upgrade,
rather than after, so that functions called by upgrade will use the
new database features instead of the old (this didn't matter in this
series because nothing modified the database differently depending on
features).  Second, this combines multiple _notmuch_message_sync calls
into one, which cleans up the code, should further improve upgrade
performance, and makes way for additional per-message upgrades.

The diff from v2 is below (excluding patch 2, which David pushed).

diff --git a/lib/database.cc b/lib/database.cc
index b323691..d90a924 100644
--- a/lib/database.cc
+++ b/lib/database.cc
@@ -1252,6 +1252,10 @@ notmuch_database_upgrade (notmuch_database_t *notmuch,
 /* Perform the upgrade in a transaction. */
 db->begin_transaction (true);
 
+/* Set the target features so we write out changes in the desired
+ * format. */
+notmuch->features = target_features;
+
 /* Perform per-message upgrades. */
 if (new_features &
(NOTMUCH_FEATURE_FILE_TERMS | NOTMUCH_FEATURE_BOOL_FOLDER)) {
@@ -1280,7 +1284,6 @@ notmuch_database_upgrade (notmuch_database_t *notmuch,
if (filename && *filename != '\0') {
_notmuch_message_add_filename (message, filename);
_notmuch_message_clear_data (message);
-   _notmuch_message_sync (message);
}
talloc_free (filename);
}
@@ -1289,10 +1292,10 @@ notmuch_database_upgrade (notmuch_database_t *notmuch,
 * probabilistic and stemmed. Change it to the current
 * boolean prefix. Add "path:" prefixes while at it.
 */
-   if (new_features & NOTMUCH_FEATURE_BOOL_FOLDER) {
+   if (new_features & NOTMUCH_FEATURE_BOOL_FOLDER)
_notmuch_message_upgrade_folder (message);
-   _notmuch_message_sync (message);
-   }
+
+   _notmuch_message_sync (message);
 
notmuch_message_destroy (message);
 
@@ -1348,7 +1351,6 @@ notmuch_database_upgrade (notmuch_database_t *notmuch,
}
 }
 
-notmuch->features = target_features;
 db->set_metadata ("features", _print_features (local, notmuch->features));
 db->set_metadata ("version", STRINGIFY (NOTMUCH_DATABASE_VERSION));

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


Re: [PATCH RFC] Emacs: Add address completion mechanism implemented in elisp

2014-07-31 Thread David Bremner
Michal Sojka  writes:

> notmuch-company.el hooks itself into message-mode and uses
> company-mode to offer the completion to the user. The file is put into
> the contrib directory which means that the use has to install it
> himself. This is because company-mode is not a part of Emacs and
> bytecompiling notmuch-company.el fails due to used --quick option that
> causes user installed packages to be ignored. 

what about for now just putting 

;; -*-no-byte-compile: t; -*-

at the top of the file?  It seems usable uncompiled to me.

Then somebody who really wants it compiled can figure out how to do the
conditional compilation.

> It would probably make sense to implement another completion frontend
> based only on Emacs built-in functionality and integrate it with
> notmuch-addresses.el.

Agreed.

> +  "`company-mode' completion back-end for `nevermore (nm)'."

missed "nevermore" ;)


>  
> +(defun notmuch-flatten-thread-set (thread-set)
> +  "Convert the result of 'notmuch show' to the plain list of messages."
> +(defun notmuch-flatten-thread (thread)
> +
> +(defun notmuch-flatten-thread-node (thread-node)


what about putting those functions in notmuch-query.el?


> +(defun notmuch-async-harvest ()
> +  "Collect possible addresses for completion. It queries the


logically it seems like this might belong in notmuch-address.el,
even if none of the functions in  in it currently use


d
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


Custom Tag Images

2014-07-31 Thread MaDhAt2r

Hello Everyone.

If this is not the place to address this issue, could you please
direct me to the proper forum.

Info: Using Emacs 24.3.1 on ArchLinux

I am interested in setting up custom image for some of the tags I use.

I have tried to use a svg file by setting it in the following ways:

(defun notmuch-tag-list-icon ()
  "Return SVG data representing a list.
This can be used with `notmuch-tag-format-image-data'."

" 

http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\";>
http://www.w3.org/2000/svg\"; 
xmlns:xlink=\"http://www.w3.org/1999/xlink\"; width=\"16\" height=\"16\" 
viewBox=\"0 0 16 16\">




 ")

and setting it like I do the default images. e.g.
(setq notmuch-tag-formats '(
("flagged" (notmuch-tag-format-image-data tag 
(notmuch-tag-star-icon)))
("lists" (notmuch-tag-format-image-data tag 
(notmuch-tag-list-icon)))
))

I have also tried via the customize image setting and using the path to
the file.

Both ways produce nothing but a colored rectangle.

I have downloaded the file in question from http://IcoMoon.io

Am I missing something obvious here, or is this svg perhaps formatted
incorrectly for notmuch emacs?

Any pointers in the right direction are greatly appreciated.

Thanks.


[PATCH RFC] Emacs: Add address completion mechanism implemented in elisp

2014-07-31 Thread Michal Sojka
On Thu, Jul 31 2014, Trevor Jim wrote:
> BTW I have been refactoring my async process code. You might consider
> it for your patch.

I'll look at that. I figured out that I might also reuse
notmuch-parser.el. I'll post here my findings later.

-Michal


[PATCH] emacs: Clarify that notmuch-poll-script is deprecated

2014-07-31 Thread David Bremner
Austin Clements  writes:

> notmuch-poll-script has long since been deprecated in favor of
> post-new hooks, but this wasn't obvious from the documentation.
> Update the documentation to make this clear.  Since
> notmuch-poll-script could, to some extend, be used to control the path
> of the notmuch binary and that use is now clearly discouraged, promote
> notmuch-command to a real defcustom instead of just a variable.

pushed

d


[PATCH v2 02/14] util: Make string-util.h C++-compatible

2014-07-31 Thread David Bremner
Austin Clements  writes:

> ---
>  util/string-util.h | 8 
>  1 file changed, 8 insertions(+)

pushed this one patch.

d


[PATCH] config: read user.name from $NAME if set

2014-07-31 Thread David Bremner
Mark Oteiza  writes:

> Try to read the config parameter user.name from $NAME before taking the
> user name from /etc/passwd.

pushed

d


[PATCH] config: read database.path from $MAILDIR if set

2014-07-31 Thread David Bremner
Mark Oteiza  writes:

> Try to read the config parameter database.path from $MAILDIR before
> falling back to $HOME/mail

pushed.

d


[PATCH] config: read database.path from $MAILDIR if set

2014-07-31 Thread David Bremner
David Bremner  writes:

> Mark Oteiza  writes:
>
>> Try to read the config parameter database.path from $MAILDIR before
>> falling back to $HOME/mail
>> ---
>
> This patch doesn't apply to git master. I'm not really sure happened,
> maybe you generated it against some old version?

Ah, nevermind it needed to have your other patch applied first.
I guess it would be better to make a serious when a few patches touch
the same code.

d


[PATCH] config: read database.path from $MAILDIR if set

2014-07-31 Thread David Bremner
Mark Oteiza  writes:

> Try to read the config parameter database.path from $MAILDIR before
> falling back to $HOME/mail
> ---

This patch doesn't apply to git master. I'm not really sure happened,
maybe you generated it against some old version?

d


Re: [PATCH] emacs: Clarify that notmuch-poll-script is deprecated

2014-07-31 Thread David Bremner
Austin Clements  writes:

> notmuch-poll-script has long since been deprecated in favor of
> post-new hooks, but this wasn't obvious from the documentation.
> Update the documentation to make this clear.  Since
> notmuch-poll-script could, to some extend, be used to control the path
> of the notmuch binary and that use is now clearly discouraged, promote
> notmuch-command to a real defcustom instead of just a variable.

pushed

d
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


Re: [PATCH] config: read database.path from $MAILDIR if set

2014-07-31 Thread David Bremner
Mark Oteiza  writes:

> Try to read the config parameter database.path from $MAILDIR before
> falling back to $HOME/mail

pushed.

d
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


Re: [PATCH v2 02/14] util: Make string-util.h C++-compatible

2014-07-31 Thread David Bremner
Austin Clements  writes:

> ---
>  util/string-util.h | 8 
>  1 file changed, 8 insertions(+)

pushed this one patch.

d
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


Re: [PATCH] config: read user.name from $NAME if set

2014-07-31 Thread David Bremner
Mark Oteiza  writes:

> Try to read the config parameter user.name from $NAME before taking the
> user name from /etc/passwd.

pushed

d
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


Re: [PATCH] config: read database.path from $MAILDIR if set

2014-07-31 Thread David Bremner
David Bremner  writes:

> Mark Oteiza  writes:
>
>> Try to read the config parameter database.path from $MAILDIR before
>> falling back to $HOME/mail
>> ---
>
> This patch doesn't apply to git master. I'm not really sure happened,
> maybe you generated it against some old version?

Ah, nevermind it needed to have your other patch applied first.
I guess it would be better to make a serious when a few patches touch
the same code.

d
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


Re: [PATCH] config: read database.path from $MAILDIR if set

2014-07-31 Thread David Bremner
Mark Oteiza  writes:

> Try to read the config parameter database.path from $MAILDIR before
> falling back to $HOME/mail
> ---

This patch doesn't apply to git master. I'm not really sure happened,
maybe you generated it against some old version?

d
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


Re: [PATCH RFC] Emacs: Add address completion mechanism implemented in elisp

2014-07-31 Thread Michal Sojka
On Thu, Jul 31 2014, Trevor Jim wrote:
> BTW I have been refactoring my async process code. You might consider
> it for your patch.

I'll look at that. I figured out that I might also reuse
notmuch-parser.el. I'll post here my findings later.

-Michal
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch