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 6C8E36DE0233 for ; Thu, 30 Aug 2018 04:29:38 -0700 (PDT) X-Virus-Scanned: Debian amavisd-new at cworth.org X-Spam-Flag: NO X-Spam-Score: 0.001 X-Spam-Level: X-Spam-Status: No, score=0.001 tagged_above=-999 required=5 tests=[AWL=0.012, 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 ZXJC7jpKzg31 for ; Thu, 30 Aug 2018 04:29:37 -0700 (PDT) Received: from fethera.tethera.net (fethera.tethera.net [198.245.60.197]) by arlo.cworth.org (Postfix) with ESMTPS id 706CF6DE023B for ; Thu, 30 Aug 2018 04:29:37 -0700 (PDT) Received: from remotemail by fethera.tethera.net with local (Exim 4.89) (envelope-from ) id 1fvL8q-0007Ea-G9; Thu, 30 Aug 2018 07:29:36 -0400 Received: (nullmailer pid 12127 invoked by uid 1000); Thu, 30 Aug 2018 11:29:32 -0000 From: David Bremner To: notmuch@notmuchmail.org Subject: [PATCH 07/15] lib/thread: initial use of references as for fallback parenting Date: Thu, 30 Aug 2018 08:29:07 -0300 Message-Id: <20180830112915.11761-8-david@tethera.net> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20180830112915.11761-1-david@tethera.net> References: <20180830112915.11761-1-david@tethera.net> X-BeenThere: notmuch@notmuchmail.org X-Mailman-Version: 2.1.26 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: Thu, 30 Aug 2018 11:29:38 -0000 This is mainly to lay out the structure of the final code. The problem isn't really solved yet, although some very simple cases are better (hence the fixed test). We need two passes through the messages because we need to be careful not to re-parent too many messages and end up without any toplevel messages. --- lib/thread.cc | 43 +++++++++++++++++++++++++++++++++++-- test/T510-thread-replies.sh | 1 - 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/lib/thread.cc b/lib/thread.cc index 8074b625..72c447ef 100644 --- a/lib/thread.cc +++ b/lib/thread.cc @@ -407,22 +407,52 @@ _parent_via_in_reply_to (notmuch_thread_t *thread, notmuch_message_t *message) { } } +static void +_parent_or_toplevel (notmuch_thread_t *thread, notmuch_message_t *message) +{ + bool found = false; + notmuch_message_t *parent = NULL; + const notmuch_string_list_t *references = + _notmuch_message_get_references (message); + for (notmuch_string_node_t *ref_node = references->head; + ! found && ref_node; ref_node = ref_node->next) { + if ((found = g_hash_table_lookup_extended (thread->message_hash, + ref_node->string, NULL, + (void **) &parent))) { + _notmuch_message_add_reply (parent, message); + } + } + if (! found) + _notmuch_message_list_add_message (thread->toplevel_list, message); +} + static void _resolve_thread_relationships (notmuch_thread_t *thread) { notmuch_message_node_t *node, *first_node; notmuch_message_t *message; + void *local; + notmuch_message_list_t *maybe_toplevel_list; first_node = thread->message_list->head; if (! first_node) return; + local = talloc_new (thread); + maybe_toplevel_list = _notmuch_message_list_create (local); + for (node = first_node->next; node; node = node->next) { message = node->message; if (! _parent_via_in_reply_to (thread, message)) - _notmuch_message_list_add_message (thread->toplevel_list, message); + _notmuch_message_list_add_message (maybe_toplevel_list, message); } + for (notmuch_messages_t *roots = _notmuch_messages_create (maybe_toplevel_list); + notmuch_messages_valid (roots); + notmuch_messages_move_to_next (roots)) { + notmuch_message_t *message = notmuch_messages_get (roots); + _parent_or_toplevel (thread, message); + } /* * if we reach the end of the list without finding a top-level * message, that means the thread is a cycle (or set of cycles) @@ -433,7 +463,15 @@ _resolve_thread_relationships (notmuch_thread_t *thread) message = first_node->message; if (! thread->toplevel_list->head || ! _parent_via_in_reply_to (thread, message)) { - _notmuch_message_list_add_message (thread->toplevel_list, message); + /* + * If the oldest message happens to be in-reply-to a + * missing message, we only check for references if there + * is some other candidate for root message. + */ + if (thread->toplevel_list->head) + _parent_or_toplevel (thread, message); + else + _notmuch_message_list_add_message (thread->toplevel_list, message); } } @@ -453,6 +491,7 @@ _resolve_thread_relationships (notmuch_thread_t *thread) * correctly in the thread even when an intermediate message is * missing from the thread. */ + talloc_free (local); } /* Create a new notmuch_thread_t object by finding the thread diff --git a/test/T510-thread-replies.sh b/test/T510-thread-replies.sh index 72af50df..c244054a 100755 --- a/test/T510-thread-replies.sh +++ b/test/T510-thread-replies.sh @@ -167,7 +167,6 @@ test_expect_equal_json "$output" "$expected" add_email_corpus threading test_begin_subtest "reply to ghost" -test_subtest_known_broken notmuch show --entire-thread=true id:000-real-root@example.org | grep ^Subject: | head -1 > OUTPUT cat < EXPECTED Subject: root message -- 2.18.0