From 5b93fa6e70c905e3c5f2a8109683db29ccfd5bcf Mon Sep 17 00:00:00 2001 From: Daniel Kahn Gillmor Date: Sun, 4 Jun 2017 09:32:34 -0300 Subject: [PATCH] lib: add notmuch_message_reindex This new function asks the database to reindex a given message. The parameter `indexopts` is currently ignored, but is intended to provide an extensible API to support e.g. changing the encryption or filtering status (e.g. whether and how certain non-plaintext parts are indexed). --- lib/add-message.cc | 2 +- lib/message.cc | 108 +++++++++++++++++++++++++++++++++++++++++- lib/notmuch-private.h | 6 +++ lib/notmuch.h | 15 ++++++ 4 files changed, 129 insertions(+), 2 deletions(-) diff --git a/lib/add-message.cc b/lib/add-message.cc index f0a80c4f..711ed9fa 100644 --- a/lib/add-message.cc +++ b/lib/add-message.cc @@ -220,7 +220,7 @@ _my_talloc_free_for_g_hash (void *ptr) talloc_free (ptr); } -static notmuch_status_t +notmuch_status_t _notmuch_database_link_message_to_parents (notmuch_database_t *notmuch, notmuch_message_t *message, notmuch_message_file_t *message_file, diff --git a/lib/message.cc b/lib/message.cc index a1c3cd78..539d3320 100644 --- a/lib/message.cc +++ b/lib/message.cc @@ -579,7 +579,9 @@ void _notmuch_message_remove_terms (notmuch_message_t *message, const char *prefix) { Xapian::TermIterator i; - size_t prefix_len = strlen (prefix); + size_t prefix_len = 0; + + prefix_len = strlen (prefix); while (1) { i = message->doc.termlist_begin (); @@ -1934,3 +1936,107 @@ _notmuch_message_frozen (notmuch_message_t *message) { return message->frozen; } + +notmuch_status_t +notmuch_message_reindex (notmuch_message_t *message, + notmuch_param_t unused (*indexopts)) +{ + notmuch_database_t *notmuch = NULL; + notmuch_status_t ret = NOTMUCH_STATUS_SUCCESS; + notmuch_private_status_t private_status; + notmuch_filenames_t *orig_filenames = NULL; + const char *orig_thread_id = NULL; + notmuch_message_file_t *message_file = NULL; + + int found = 0; + + if (message == NULL) + return NOTMUCH_STATUS_NULL_POINTER; + + /* Save in case we need to delete message */ + orig_thread_id = notmuch_message_get_thread_id (message); + if (!orig_thread_id) { + /* XXX TODO: make up new error return? */ + INTERNAL_ERROR ("message without thread-id"); + } + + /* strdup it because the metadata may be invalidated */ + orig_thread_id = talloc_strdup (message, orig_thread_id); + + notmuch = _notmuch_message_database (message); + + ret = _notmuch_database_ensure_writable (notmuch); + if (ret) + return ret; + + orig_filenames = notmuch_message_get_filenames (message); + + private_status = _notmuch_message_remove_indexed_terms (message); + if (private_status) { + ret = COERCE_STATUS(private_status, "error removing terms"); + goto DONE; + } + + /* re-add the filenames with the associated indexopts */ + for (; notmuch_filenames_valid (orig_filenames); + notmuch_filenames_move_to_next (orig_filenames)) { + + const char *date; + const char *from, *to, *subject; + char *message_id = NULL; + const char *thread_id = NULL; + + const char *filename = notmuch_filenames_get (orig_filenames); + + message_file = _notmuch_message_file_open (notmuch, filename); + if (message_file == NULL) + continue; + + ret = _notmuch_message_file_get_headers (message_file, + &from, &subject, &to, &date, + &message_id); + if (ret) + goto DONE; + + /* XXX TODO: deal with changing message id? */ + + _notmuch_message_add_filename (message, filename); + + ret = _notmuch_database_link_message_to_parents (notmuch, message, + message_file, + &thread_id); + if (ret) + goto DONE; + + if (thread_id == NULL) + thread_id = orig_thread_id; + + _notmuch_message_add_term (message, "thread", thread_id); + _notmuch_message_set_header_values (message, date, from, subject); + + ret = _notmuch_message_index_file (message, message_file); + + if (ret == NOTMUCH_STATUS_FILE_ERROR) + continue; + if (ret) + goto DONE; + + found++; + _notmuch_message_file_close (message_file); + message_file = NULL; + } + if (found == 0) { + /* put back thread id to help cleanup */ + _notmuch_message_add_term (message, "thread", orig_thread_id); + ret = _notmuch_message_delete (message); + } else { + _notmuch_message_sync (message); + } + + DONE: + if (message_file) + _notmuch_message_file_close (message_file); + + /* XXX TODO destroy orig_filenames? */ + return ret; +} diff --git a/lib/notmuch-private.h b/lib/notmuch-private.h index c8934b8b..b187a80f 100644 --- a/lib/notmuch-private.h +++ b/lib/notmuch-private.h @@ -436,6 +436,12 @@ _notmuch_message_file_get_headers (notmuch_message_file_t *message_file, const char * _notmuch_message_file_get_filename (notmuch_message_file_t *message); +/* add-message.cc */ +notmuch_status_t +_notmuch_database_link_message_to_parents (notmuch_database_t *notmuch, + notmuch_message_t *message, + notmuch_message_file_t *message_file, + const char **thread_id); /* index.cc */ notmuch_status_t diff --git a/lib/notmuch.h b/lib/notmuch.h index 4c03a893..f78b3473 100644 --- a/lib/notmuch.h +++ b/lib/notmuch.h @@ -219,6 +219,7 @@ typedef struct _notmuch_tags notmuch_tags_t; typedef struct _notmuch_directory notmuch_directory_t; typedef struct _notmuch_filenames notmuch_filenames_t; typedef struct _notmuch_config_list notmuch_config_list_t; +typedef struct _notmuch_param notmuch_param_t; #endif /* __DOXYGEN__ */ /** @@ -1393,6 +1394,20 @@ notmuch_message_get_filename (notmuch_message_t *message); notmuch_filenames_t * notmuch_message_get_filenames (notmuch_message_t *message); +/** + * Re-index the e-mail corresponding to 'message' using the supplied index options + * + * Returns the status of the re-index operation. (see the return + * codes documented in notmuch_database_add_message) + * + * After reindexing, the user should discard the message object passed + * in here by calling notmuch_message_destroy, since it refers to the + * original message, not to the reindexed message. + */ +notmuch_status_t +notmuch_message_reindex (notmuch_message_t *message, + notmuch_param_t *indexopts); + /** * Message flags. */ -- 2.26.2