--- /dev/null
+Return-Path: <dkg@fifthhorseman.net>\r
+X-Original-To: notmuch@notmuchmail.org\r
+Delivered-To: notmuch@notmuchmail.org\r
+Received: from localhost (localhost [127.0.0.1])\r
+ by arlo.cworth.org (Postfix) with ESMTP id A76D66DE1BA2\r
+ for <notmuch@notmuchmail.org>; Sun, 31 Jan 2016 12:40:22 -0800 (PST)\r
+X-Virus-Scanned: Debian amavisd-new at cworth.org\r
+X-Spam-Flag: NO\r
+X-Spam-Score: 0\r
+X-Spam-Level: \r
+X-Spam-Status: No, score=0 tagged_above=-999 required=5 tests=[none]\r
+ autolearn=disabled\r
+Received: from arlo.cworth.org ([127.0.0.1])\r
+ by localhost (arlo.cworth.org [127.0.0.1]) (amavisd-new, port 10024)\r
+ with ESMTP id fyvCM6BOp48V for <notmuch@notmuchmail.org>;\r
+ Sun, 31 Jan 2016 12:40:20 -0800 (PST)\r
+Received: from che.mayfirst.org (che.mayfirst.org [209.234.253.108])\r
+ by arlo.cworth.org (Postfix) with ESMTP id B1CBC6DE1AD2\r
+ for <notmuch@notmuchmail.org>; Sun, 31 Jan 2016 12:40:09 -0800 (PST)\r
+Received: from fifthhorseman.net (ip-64-134-185-108.public.wayport.net\r
+ [64.134.185.108])\r
+ by che.mayfirst.org (Postfix) with ESMTPSA id F2200F9A5\r
+ for <notmuch@notmuchmail.org>; Sun, 31 Jan 2016 15:40:06 -0500 (EST)\r
+Received: by fifthhorseman.net (Postfix, from userid 1000)\r
+ id 647F52119A; Sun, 31 Jan 2016 15:40:06 -0500 (EST)\r
+From: Daniel Kahn Gillmor <dkg@fifthhorseman.net>\r
+To: Notmuch Mail <notmuch@notmuchmail.org>\r
+Subject: [PATCH v3 15/16] added notmuch_message_reindex\r
+Date: Sun, 31 Jan 2016 15:40:00 -0500\r
+Message-Id: <1454272801-23623-16-git-send-email-dkg@fifthhorseman.net>\r
+X-Mailer: git-send-email 2.7.0.rc3\r
+In-Reply-To: <1454272801-23623-1-git-send-email-dkg@fifthhorseman.net>\r
+References: <1454272801-23623-1-git-send-email-dkg@fifthhorseman.net>\r
+X-BeenThere: notmuch@notmuchmail.org\r
+X-Mailman-Version: 2.1.20\r
+Precedence: list\r
+List-Id: "Use and development of the notmuch mail system."\r
+ <notmuch.notmuchmail.org>\r
+List-Unsubscribe: <https://notmuchmail.org/mailman/options/notmuch>,\r
+ <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>\r
+List-Archive: <http://notmuchmail.org/pipermail/notmuch/>\r
+List-Post: <mailto:notmuch@notmuchmail.org>\r
+List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>\r
+List-Subscribe: <https://notmuchmail.org/mailman/listinfo/notmuch>,\r
+ <mailto:notmuch-request@notmuchmail.org?subject=subscribe>\r
+X-List-Received-Date: Sun, 31 Jan 2016 20:40:22 -0000\r
+\r
+This new function asks the database to reindex a given message, using\r
+the supplied indexopts.\r
+\r
+This can be used, for example, to index the cleartext of an encrypted\r
+message.\r
+---\r
+ lib/message.cc | 91 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-\r
+ lib/notmuch.h | 14 +++++++++\r
+ 2 files changed, 104 insertions(+), 1 deletion(-)\r
+\r
+diff --git a/lib/message.cc b/lib/message.cc\r
+index 8d72ea2..3b35418 100644\r
+--- a/lib/message.cc\r
++++ b/lib/message.cc\r
+@@ -529,7 +529,9 @@ static void\r
+ _notmuch_message_remove_terms (notmuch_message_t *message, const char *prefix)\r
+ {\r
+ Xapian::TermIterator i;\r
+- size_t prefix_len = strlen (prefix);\r
++ size_t prefix_len = 0;\r
++\r
++ prefix_len = strlen (prefix);\r
+ \r
+ while (1) {\r
+ i = message->doc.termlist_begin ();\r
+@@ -1667,3 +1669,90 @@ _notmuch_message_database (notmuch_message_t *message)\r
+ {\r
+ return message->notmuch;\r
+ }\r
++\r
++notmuch_status_t\r
++notmuch_message_reindex (notmuch_message_t *message,\r
++ notmuch_indexopts_t *indexopts)\r
++{\r
++ notmuch_database_t *notmuch = NULL;\r
++ notmuch_status_t ret = NOTMUCH_STATUS_SUCCESS, status;\r
++ notmuch_tags_t *tags = NULL;\r
++ notmuch_filenames_t *filenames, *orig_filenames = NULL;\r
++ const char *filename = NULL, *tag = NULL;\r
++ notmuch_message_t *newmsg = NULL;\r
++ notmuch_bool_t readded = FALSE, skip;\r
++ const char *autotags[] = {\r
++ "attachment",\r
++ "encrypted",\r
++ "signed",\r
++ "index-decrypted",\r
++ "index-decryption-failed" };\r
++\r
++ if (message == NULL)\r
++ return NOTMUCH_STATUS_NULL_POINTER;\r
++ \r
++ notmuch = _notmuch_message_database (message);\r
++\r
++ /* cache tags and filenames */\r
++ tags = notmuch_message_get_tags(message);\r
++ filenames = notmuch_message_get_filenames(message);\r
++ orig_filenames = notmuch_message_get_filenames(message);\r
++ \r
++ /* walk through filenames, removing them until the message is gone */\r
++ for ( ; notmuch_filenames_valid (filenames);\r
++ notmuch_filenames_move_to_next (filenames)) {\r
++ filename = notmuch_filenames_get (filenames);\r
++\r
++ ret = notmuch_database_remove_message (notmuch, filename);\r
++ if (ret != NOTMUCH_STATUS_SUCCESS &&\r
++ ret != NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID)\r
++ return ret;\r
++ }\r
++ if (ret != NOTMUCH_STATUS_SUCCESS)\r
++ return ret;\r
++ \r
++ /* re-add the filenames with the associated indexopts */\r
++ for (; notmuch_filenames_valid (orig_filenames);\r
++ notmuch_filenames_move_to_next (orig_filenames)) {\r
++ filename = notmuch_filenames_get (orig_filenames);\r
++\r
++ status = notmuch_database_add_message_with_indexopts(notmuch,\r
++ filename,\r
++ indexopts,\r
++ readded ? NULL : &newmsg);\r
++ if (status == NOTMUCH_STATUS_SUCCESS ||\r
++ status == NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID) {\r
++ if (!readded) {\r
++ /* re-add tags */\r
++ for (; notmuch_tags_valid (tags);\r
++ notmuch_tags_move_to_next (tags)) {\r
++ tag = notmuch_tags_get (tags);\r
++ skip = FALSE;\r
++ \r
++ for (size_t i = 0; i < ARRAY_SIZE(autotags); i++)\r
++ if (strcmp (tag, autotags[i]) == 0)\r
++ skip = TRUE;\r
++ \r
++ if (!skip) {\r
++ status = notmuch_message_add_tag (newmsg, tag);\r
++ if (status != NOTMUCH_STATUS_SUCCESS)\r
++ ret = status;\r
++ }\r
++ }\r
++ readded = TRUE;\r
++ }\r
++ } else {\r
++ /* if we failed to add this filename, go ahead and try the\r
++ * next one as though it were first, but report the\r
++ * error... */\r
++ ret = status;\r
++ }\r
++ }\r
++ if (newmsg)\r
++ notmuch_message_destroy (newmsg);\r
++ \r
++ /* should we also destroy the incoming message object? at the\r
++ * moment, we leave that to the caller */\r
++ return ret;\r
++}\r
++\r
+diff --git a/lib/notmuch.h b/lib/notmuch.h\r
+index 854a451..e6287cd 100644\r
+--- a/lib/notmuch.h\r
++++ b/lib/notmuch.h\r
+@@ -1377,6 +1377,20 @@ notmuch_filenames_t *\r
+ notmuch_message_get_filenames (notmuch_message_t *message);\r
+ \r
+ /**\r
++ * Re-index the e-mail corresponding to 'message' using the supplied index options\r
++ *\r
++ * Returns the status of the re-index operation. (see the return\r
++ * codes documented in notmuch_database_add_message)\r
++ *\r
++ * After reindexing, the user should discard the message object passed\r
++ * in here by calling notmuch_message_destroy, since it refers to the\r
++ * original message, not to the reindexed message.\r
++ */\r
++notmuch_status_t\r
++notmuch_message_reindex (notmuch_message_t *message,\r
++ notmuch_indexopts_t *indexopts);\r
++\r
++/**\r
+ * Message flags.\r
+ */\r
+ typedef enum _notmuch_message_flag {\r
+-- \r
+2.7.0.rc3\r
+\r