[RFC patch 5/5] WIP: index user headers

David Bremner david at tethera.net
Sat Nov 17 06:09:01 PST 2018


---
 lib/database.cc          | 37 +++++++++++++++++++++++++++++--------
 lib/index.cc             | 34 ++++++++++++++++++++++++++++++++++
 lib/message.cc           |  5 ++++-
 lib/notmuch-private.h    |  4 ++++
 test/T720-user-header.sh | 17 +++++++++++++++++
 5 files changed, 88 insertions(+), 9 deletions(-)

diff --git a/lib/database.cc b/lib/database.cc
index b2654ab7..c25d867f 100644
--- a/lib/database.cc
+++ b/lib/database.cc
@@ -293,8 +293,6 @@ prefix_t prefix_table[] = {
 						NOTMUCH_FIELD_PROCESSOR},
 };
 
-#define CONFIG_HEADER_PREFIX "index.header."
-
 static void
 _setup_query_field_default (const prefix_t *prefix, notmuch_database_t *notmuch)
 {
@@ -308,7 +306,6 @@ static notmuch_status_t
 _setup_user_query_fields (notmuch_database_t *notmuch)
 {
     notmuch_config_list_t *list;
-    void *local = talloc_new(notmuch);
     notmuch_status_t status;
 
     size_t prefix_capacity = 4;
@@ -318,7 +315,7 @@ _setup_user_query_fields (notmuch_database_t *notmuch)
     if (notmuch->user_prefix == NULL)
 	return NOTMUCH_STATUS_OUT_OF_MEMORY;
     
-    status = notmuch_database_get_config_list (notmuch, "index.header.", &list);
+    status = notmuch_database_get_config_list (notmuch, CONFIG_HEADER_PREFIX, &list);
     if (status)
 	return status;
     for (; notmuch_config_list_valid (list); notmuch_config_list_move_to_next (list)) {
@@ -333,11 +330,11 @@ _setup_user_query_fields (notmuch_database_t *notmuch)
 	const char *key = notmuch_config_list_key (list)
 	    + sizeof (CONFIG_HEADER_PREFIX) - 1;
 
-	char *prefix = talloc_asprintf(local, "XU:%s", key);
+	char *prefix = talloc_asprintf(notmuch, "XU:%s", key);
 	for (char *p = prefix + 1; *p; p++)
 	    *p = toupper (*p);
 
-	query_field->name = key;
+	query_field->name = talloc_strdup(notmuch, key);
 	query_field->prefix = prefix;
 	query_field->flags = NOTMUCH_FIELD_PROBABILISTIC | NOTMUCH_FIELD_EXTERNAL;
 
@@ -346,8 +343,6 @@ _setup_user_query_fields (notmuch_database_t *notmuch)
 	prefix_index++;
     }
 
-    talloc_free (local);
-
     notmuch_config_list_destroy (list);
 
     return NOTMUCH_STATUS_SUCCESS;
@@ -399,6 +394,32 @@ _find_prefix (const char *name)
     return "";
 }
 
+const char *
+_maybe_user_prefix (notmuch_database_t *notmuch, const char *name)
+{
+
+    unsigned int i;
+
+    /*XXX TODO: reduce code duplication */
+    for (i = 0; i < ARRAY_SIZE (prefix_table); i++) {
+	if (strcmp (name, prefix_table[i].name) == 0)
+	    return prefix_table[i].prefix;
+    }
+
+    if (notmuch->user_prefix) {
+	unsigned int i;
+
+	for (i = 0; notmuch->user_prefix[i].name; i++) {
+	    if (strcmp (name, notmuch->user_prefix[i].name) == 0)
+		return notmuch->user_prefix[i].prefix;
+	}
+    }
+
+    return NULL;
+}
+
+
+
 static const struct {
     /* NOTMUCH_FEATURE_* value. */
     _notmuch_features value;
diff --git a/lib/index.cc b/lib/index.cc
index efd9da4c..6324b5a0 100644
--- a/lib/index.cc
+++ b/lib/index.cc
@@ -595,6 +595,38 @@ _index_encrypted_mime_part (notmuch_message_t *message,
 
 }
 
+static notmuch_status_t
+_notmuch_message_index_user_headers (notmuch_message_t *message, GMimeMessage *mime_message) {
+    notmuch_database_t *notmuch = notmuch_message_get_database (message);
+
+    notmuch_config_list_t *list;
+    notmuch_status_t status;
+
+    status = notmuch_database_get_config_list (notmuch, CONFIG_HEADER_PREFIX, &list);
+    if (status)
+	return status;
+    for (; notmuch_config_list_valid (list); notmuch_config_list_move_to_next (list)) {
+
+	const char *prefix_name = notmuch_config_list_key (list)
+	    + sizeof (CONFIG_HEADER_PREFIX) - 1;
+
+	const char *header_name = notmuch_config_list_value (list);
+
+	/* this is gmime 3.0 specific, I think */
+	
+	const char *header = g_mime_object_get_header (GMIME_OBJECT (mime_message), header_name);
+	if (header == NULL)
+	    return NOTMUCH_STATUS_SUCCESS;
+
+	
+	_notmuch_message_gen_terms (message, prefix_name, header);
+    }
+
+    return NOTMUCH_STATUS_SUCCESS;
+
+}
+
+
 notmuch_status_t
 _notmuch_message_index_file (notmuch_message_t *message,
 			     notmuch_indexopts_t *indexopts,
@@ -625,6 +657,8 @@ _notmuch_message_index_file (notmuch_message_t *message,
     subject = g_mime_message_get_subject (mime_message);
     _notmuch_message_gen_terms (message, "subject", subject);
 
+    status = _notmuch_message_index_user_headers (message, mime_message);
+
     _index_mime_part (message, indexopts, g_mime_message_get_mime_part (mime_message));
 
     return NOTMUCH_STATUS_SUCCESS;
diff --git a/lib/message.cc b/lib/message.cc
index 6f2f6345..f428e210 100644
--- a/lib/message.cc
+++ b/lib/message.cc
@@ -1434,7 +1434,10 @@ _notmuch_message_gen_terms (notmuch_message_t *message,
     term_gen->set_document (message->doc);
 
     if (prefix_name) {
-	const char *prefix = _find_prefix (prefix_name);
+	const char *prefix = _maybe_user_prefix (message->notmuch, prefix_name);
+
+	if (prefix == NULL)
+	    return NOTMUCH_PRIVATE_STATUS_BAD_PREFIX;
 
 	term_gen->set_termpos (message->termpos);
 	term_gen->index_text (text, 1, prefix);
diff --git a/lib/notmuch-private.h b/lib/notmuch-private.h
index 09f828ab..098be4eb 100644
--- a/lib/notmuch-private.h
+++ b/lib/notmuch-private.h
@@ -136,6 +136,7 @@ typedef enum _notmuch_private_status {
     /* Then add our own private values. */
     NOTMUCH_PRIVATE_STATUS_TERM_TOO_LONG = NOTMUCH_STATUS_LAST_STATUS,
     NOTMUCH_PRIVATE_STATUS_NO_DOCUMENT_FOUND,
+    NOTMUCH_PRIVATE_STATUS_BAD_PREFIX,
 
     NOTMUCH_PRIVATE_STATUS_LAST_STATUS
 } notmuch_private_status_t;
@@ -181,6 +182,9 @@ typedef struct _notmuch_doc_id_set notmuch_doc_id_set_t;
 const char *
 _find_prefix (const char *name);
 
+const char *
+_maybe_user_prefix (notmuch_database_t *notmuch, const char *name);
+
 char *
 _notmuch_message_id_compressed (void *ctx, const char *message_id);
 
diff --git a/test/T720-user-header.sh b/test/T720-user-header.sh
index ab4d4712..c02861cc 100755
--- a/test/T720-user-header.sh
+++ b/test/T720-user-header.sh
@@ -56,4 +56,21 @@ Query((Tmail AND (XU:LISTnotmuchmail at 1 PHRASE 2 XU:LISTorg at 2)))
 EOF
 test_expect_equal_file EXPECTED OUTPUT
 
+test_begin_subtest "index user header"
+notmuch config set index.header.list "List-Id"
+notmuch reindex '*'
+notmuch search --output=files list:notmuch | notmuch_search_files_sanitize | sort > OUTPUT
+cat <<EOF > EXPECTED
+MAIL_DIR/bar/baz/05:2,
+MAIL_DIR/bar/baz/23:2,
+MAIL_DIR/bar/baz/24:2,
+MAIL_DIR/bar/cur/20:2,
+MAIL_DIR/bar/new/21:2,
+MAIL_DIR/bar/new/22:2,
+MAIL_DIR/foo/cur/08:2,
+MAIL_DIR/foo/new/03:2,
+MAIL_DIR/new/04:2,
+EOF
+test_expect_equal_file EXPECTED OUTPUT
+
 test_done
-- 
2.19.1



More information about the notmuch mailing list