From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from localhost (localhost [127.0.0.1]) by arlo.cworth.org (Postfix) with ESMTP id 1EC566DE0A73 for ; Sun, 2 Apr 2017 06:17:09 -0700 (PDT) X-Virus-Scanned: Debian amavisd-new at cworth.org X-Spam-Flag: NO X-Spam-Score: -0.005 X-Spam-Level: X-Spam-Status: No, score=-0.005 tagged_above=-999 required=5 tests=[AWL=0.006, SPF_PASS=-0.001, T_RP_MATCHES_RCVD=-0.01] autolearn=disabled Received: from arlo.cworth.org ([127.0.0.1]) by localhost (arlo.cworth.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id tU1FNvylXWBR for ; Sun, 2 Apr 2017 06:17:07 -0700 (PDT) Received: from fethera.tethera.net (fethera.tethera.net [198.245.60.197]) by arlo.cworth.org (Postfix) with ESMTPS id 34F076DE0A5B for ; Sun, 2 Apr 2017 06:17:04 -0700 (PDT) Received: from remotemail by fethera.tethera.net with local (Exim 4.84_2) (envelope-from ) id 1cufMg-0003CM-IJ; Sun, 02 Apr 2017 09:16:18 -0400 Received: (nullmailer pid 30009 invoked by uid 1000); Sun, 02 Apr 2017 13:16:56 -0000 From: David Bremner To: notmuch@notmuchmail.org Cc: Daniel Kahn Gillmor Subject: [rfc patch v2 2/5] added notmuch_message_reindex Date: Sun, 2 Apr 2017 10:16:43 -0300 Message-Id: <20170402131646.29884-3-david@tethera.net> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170402131646.29884-1-david@tethera.net> References: <20170402131646.29884-1-david@tethera.net> X-BeenThere: notmuch@notmuchmail.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: "Use and development of the notmuch mail system." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 02 Apr 2017 13:17:09 -0000 From: Daniel Kahn Gillmor 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). Since we have no way of distinguising terms added (without prefix) from the headers and terms added from the body, we just save the tags and properties, remove the message from the database entirely, and add it back into the database in full, re-adding tags and properties as needed. --- lib/message.cc | 102 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- lib/notmuch.h | 14 ++++++++ 2 files changed, 115 insertions(+), 1 deletion(-) diff --git a/lib/message.cc b/lib/message.cc index f8215a49..d68e4c66 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 (); @@ -1872,3 +1874,101 @@ _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, status; + notmuch_tags_t *tags = NULL; + notmuch_message_properties_t *properties = NULL; + notmuch_filenames_t *filenames, *orig_filenames = NULL; + const char *filename = NULL, *tag = NULL, *propkey = NULL; + notmuch_message_t *newmsg = NULL; + notmuch_bool_t readded = FALSE, skip; + const char *autotags[] = { + "attachment", + "encrypted", + "signed" }; + + if (message == NULL) + return NOTMUCH_STATUS_NULL_POINTER; + + notmuch = _notmuch_message_database (message); + + /* cache tags, properties, and filenames */ + tags = notmuch_message_get_tags (message); + properties = notmuch_message_get_properties (message, "", FALSE); + filenames = notmuch_message_get_filenames (message); + orig_filenames = notmuch_message_get_filenames (message); + + /* walk through filenames, removing them until the message is gone */ + for ( ; notmuch_filenames_valid (filenames); + notmuch_filenames_move_to_next (filenames)) { + filename = notmuch_filenames_get (filenames); + + ret = notmuch_database_remove_message (notmuch, filename); + if (ret != NOTMUCH_STATUS_SUCCESS && + ret != NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID) + return ret; + } + if (ret != NOTMUCH_STATUS_SUCCESS) + return ret; + + /* re-add the filenames with the associated indexopts */ + for (; notmuch_filenames_valid (orig_filenames); + notmuch_filenames_move_to_next (orig_filenames)) { + filename = notmuch_filenames_get (orig_filenames); + + status = notmuch_database_add_message(notmuch, + filename, + readded ? NULL : &newmsg); + if (status == NOTMUCH_STATUS_SUCCESS || + status == NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID) { + if (!readded) { + /* re-add tags */ + for (; notmuch_tags_valid (tags); + notmuch_tags_move_to_next (tags)) { + tag = notmuch_tags_get (tags); + skip = FALSE; + + for (size_t i = 0; i < ARRAY_SIZE (autotags); i++) + if (strcmp (tag, autotags[i]) == 0) + skip = TRUE; + + if (!skip) { + status = notmuch_message_add_tag (newmsg, tag); + if (status != NOTMUCH_STATUS_SUCCESS) + ret = status; + } + } + /* re-add properties */ + for (; notmuch_message_properties_valid (properties); + notmuch_message_properties_move_to_next (properties)) { + propkey = notmuch_message_properties_key (properties); + skip = FALSE; + + if (!skip) { + status = notmuch_message_add_property (newmsg, propkey, + notmuch_message_properties_value (properties)); + if (status != NOTMUCH_STATUS_SUCCESS) + ret = status; + } + } + readded = TRUE; + } + } else { + /* if we failed to add this filename, go ahead and try the + * next one as though it were first, but report the + * error... */ + ret = status; + } + } + if (newmsg) + notmuch_message_destroy (newmsg); + + /* should we also destroy the incoming message object? at the + * moment, we leave that to the caller */ + return ret; +} diff --git a/lib/notmuch.h b/lib/notmuch.h index fc00f96d..1f31efed 100644 --- a/lib/notmuch.h +++ b/lib/notmuch.h @@ -1389,6 +1389,20 @@ 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. */ typedef enum _notmuch_message_flag { -- 2.11.0