X-Git-Url: https://git.notmuchmail.org/git?p=notmuch;a=blobdiff_plain;f=notmuch-index-message.cc;h=0aa374c8133308e3a60de1ad59bf31131c63bf49;hp=b8fa205b9cc474d5fc11d795d308f9933ae15007;hb=9ab2447e89906f826bb4efbd232c23db9b64b528;hpb=5cbdcbbec58248ef803ba8f3f035e1c49b7ad0a8 diff --git a/notmuch-index-message.cc b/notmuch-index-message.cc index b8fa205b..0aa374c8 100644 --- a/notmuch-index-message.cc +++ b/notmuch-index-message.cc @@ -33,6 +33,9 @@ using namespace std; #define ARRAY_SIZE(arr) (sizeof (arr) / sizeof (arr[0])) +/* Xapian complains if we provide a term longer than this. */ +#define NOTMUCH_MAX_TERM 245 + /* These prefix values are specifically chosen to be compatible * with sup, (http://sup.rubyforge.org), written by * William Morgan , and released @@ -109,7 +112,8 @@ add_term (Xapian::Document doc, term = g_strdup_printf ("%s%s", prefix, value); - doc.add_term (term); + if (strlen (term) <= NOTMUCH_MAX_TERM) + doc.add_term (term); g_free (term); } @@ -204,6 +208,101 @@ skip_re_in_subject (const char *subject) return s; } +static void +find_messages_by_term (Xapian::Database db, + const char *prefix_name, + const char *value, + Xapian::PostingIterator *begin, + Xapian::PostingIterator *end) +{ + Xapian::PostingIterator i; + char *term; + + term = g_strdup_printf ("%s%s", find_prefix (prefix_name), value); + + *begin = db.postlist_begin (term); + + if (end) + *end = db.postlist_end (term); + + free (term); +} + +Xapian::Document +find_message_by_docid (Xapian::Database db, Xapian::docid docid) +{ + return db.get_document (docid); +} + +Xapian::Document +find_message_by_message_id (Xapian::Database db, const char *message_id) +{ + Xapian::PostingIterator i, end; + + find_messages_by_term (db, "msgid", message_id, &i, &end); + + if (i != end) + return find_message_by_docid (db, *i); + else + return Xapian::Document (); +} + +static void +insert_thread_id (GHashTable *thread_ids, Xapian::Document doc) +{ + string value_string; + const char *value; + + value_string = doc.get_value (NOTMUCH_VALUE_THREAD); + value = value_string.c_str(); + if (strlen (value)) + g_hash_table_insert (thread_ids, strdup (value), NULL); +} + +static char * +find_thread_id (Xapian::Database db, + GPtrArray *parents, + const char *message_id) +{ + Xapian::PostingIterator child, children_end; + Xapian::Document doc; + GHashTable *thread_ids; + GList *keys, *l; + GString *result = NULL; + unsigned int i; + const char *parent_message_id; + + thread_ids = g_hash_table_new (g_str_hash, g_str_equal); + + find_messages_by_term (db, "ref", message_id, &child, &children_end); + for ( ; child != children_end; child++) { + doc = find_message_by_docid (db, *child); + insert_thread_id (thread_ids, doc); + } + + for (i = 0; i < parents->len; i++) { + parent_message_id = (char *) g_ptr_array_index (parents, i); + doc = find_message_by_message_id (db, parent_message_id); + insert_thread_id (thread_ids, doc); + } + + keys = g_hash_table_get_keys (thread_ids); + for (l = keys; l; l = l->next) { + char *id = (char *) l->data; + if (result == NULL) { + result = g_string_new (id); + } else { + g_string_append_printf (result, ",%s", id); + } + free (id); + } + + if (result) + return g_string_free (result, FALSE); + else + return NULL; +} + /* Add a term for each message-id in the References header of the * message. */ static void @@ -334,7 +433,8 @@ index_file (Xapian::WritableDatabase db, FILE *file; - const char *value, *from; + const char *subject, *refs, *in_reply_to, *from; + const char *message_id, *thread_id; time_t time; struct tm gm_time_tm; @@ -369,24 +469,29 @@ index_file (Xapian::WritableDatabase db, addresses = g_mime_message_get_all_recipients (message); gen_terms_address_names (term_gen, addresses, "to_name"); - value = g_mime_message_get_subject (message); - value = skip_re_in_subject (value); - gen_terms (term_gen, "subject", value); - gen_terms (term_gen, "body", value); + subject = g_mime_message_get_subject (message); + subject = skip_re_in_subject (subject); + gen_terms (term_gen, "subject", subject); + gen_terms (term_gen, "body", subject); gen_terms_body (term_gen, filename, g_mime_parser_get_headers_end (parser)); parents = g_ptr_array_new (); - value = g_mime_object_get_header (GMIME_OBJECT (message), "references"); - parse_references (parents, value); + refs = g_mime_object_get_header (GMIME_OBJECT (message), "references"); + parse_references (parents, refs); - value = g_mime_object_get_header (GMIME_OBJECT (message), "in-reply-to"); - parse_references (parents, value); + in_reply_to = g_mime_object_get_header (GMIME_OBJECT (message), + "in-reply-to"); + parse_references (parents, in_reply_to); for (i = 0; i < parents->len; i++) - add_term (doc, "ref", (const char *) g_ptr_array_index (parents, i)); + add_term (doc, "ref", (char *) g_ptr_array_index (parents, i)); + + message_id = g_mime_message_get_message_id (message); + + thread_id = find_thread_id (db, parents, message_id); for (i = 0; i < parents->len; i++) g_free (g_ptr_array_index (parents, i)); @@ -418,12 +523,18 @@ index_file (Xapian::WritableDatabase db, add_term (doc, "type", "mail"); add_term (doc, "source_id", "1"); - value = g_mime_message_get_message_id (message); - add_term (doc, "msgid", value); - add_term (doc, "thread", value); - - doc.add_value (NOTMUCH_VALUE_MESSAGE_ID, value); - doc.add_value (NOTMUCH_VALUE_THREAD, value); + add_term (doc, "msgid", message_id); + doc.add_value (NOTMUCH_VALUE_MESSAGE_ID, message_id); + + if (thread_id) { + add_term (doc, "thread", thread_id); + doc.add_value (NOTMUCH_VALUE_THREAD, thread_id); + free ((void *) thread_id); + } else { + /* If not referenced thread, use the message ID */ + add_term (doc, "thread", message_id); + doc.add_value (NOTMUCH_VALUE_THREAD, message_id); + } doc.add_value (NOTMUCH_VALUE_DATE, Xapian::sortable_serialise (time));