From 46dce33abc82ea6ebd3be2e0887506af4185c739 Mon Sep 17 00:00:00 2001 From: David Bremner Date: Thu, 30 Aug 2018 08:29:10 -0300 Subject: [PATCH] lib/thread: change _resolve_thread_relationships to use depths We (finally) implement the XXX comment. It requires a bit of care not to reparent all of the possible toplevel messages. _notmuch_messages_has_next is not ready to be a public function yet, since it punts on the mset case. We know in the one case it is called, the notmuch_messages_t is just a regular list / iterator. --- lib/messages.c | 12 +++++++++ lib/notmuch-private.h | 3 +++ lib/thread.cc | 53 ++++++++++++++++++------------------- test/T510-thread-replies.sh | 1 - 4 files changed, 41 insertions(+), 28 deletions(-) diff --git a/lib/messages.c b/lib/messages.c index ba8a9777..04fa19f8 100644 --- a/lib/messages.c +++ b/lib/messages.c @@ -110,6 +110,18 @@ notmuch_messages_valid (notmuch_messages_t *messages) return (messages->iterator != NULL); } +bool +_notmuch_messages_has_next (notmuch_messages_t *messages) +{ + if (! notmuch_messages_valid (messages)) + return false; + + if (! messages->is_of_list_type) + INTERNAL_ERROR("_notmuch_messages_has_next not implimented for msets"); + + return (messages->iterator->next != NULL); +} + notmuch_message_t * notmuch_messages_get (notmuch_messages_t *messages) { diff --git a/lib/notmuch-private.h b/lib/notmuch-private.h index 94fc54d7..9eca0789 100644 --- a/lib/notmuch-private.h +++ b/lib/notmuch-private.h @@ -487,6 +487,9 @@ _notmuch_message_list_add_message (notmuch_message_list_t *list, notmuch_messages_t * _notmuch_messages_create (notmuch_message_list_t *list); +bool +_notmuch_messages_has_next (notmuch_messages_t *messages); + /* query.cc */ bool diff --git a/lib/thread.cc b/lib/thread.cc index 4f85a829..47c90664 100644 --- a/lib/thread.cc +++ b/lib/thread.cc @@ -473,12 +473,6 @@ _resolve_thread_relationships (notmuch_thread_t *thread) _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) @@ -487,36 +481,41 @@ _resolve_thread_relationships (notmuch_thread_t *thread) */ if (first_node) { message = first_node->message; - if (_notmuch_message_list_empty(thread->toplevel_list) || + THREAD_DEBUG("checking first message %s\n", + notmuch_message_get_message_id (message)); + + if (_notmuch_message_list_empty (maybe_toplevel_list) || ! _parent_via_in_reply_to (thread, 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 (! _notmuch_message_list_empty (thread->toplevel_list)) - _parent_or_toplevel (thread, message); - else - _notmuch_message_list_add_message (thread->toplevel_list, message); + + THREAD_DEBUG("adding first message as toplevel = %s\n", + notmuch_message_get_message_id (message)); + _notmuch_message_list_add_message (maybe_toplevel_list, message); } } + for (notmuch_messages_t *messages = _notmuch_messages_create (maybe_toplevel_list); + notmuch_messages_valid (messages); + notmuch_messages_move_to_next (messages)) + { + notmuch_message_t *message = notmuch_messages_get (messages); + _notmuch_message_label_depths (message, 0); + } + + 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); + if (_notmuch_messages_has_next (roots) || ! _notmuch_message_list_empty (thread->toplevel_list)) + _parent_or_toplevel (thread, message); + else + _notmuch_message_list_add_message (thread->toplevel_list, message); + } + /* XXX this could be made conditional on messages being inserted * (out of order) in later passes */ thread->toplevel_list = _notmuch_message_sort_subtrees (thread, thread->toplevel_list); - - /* XXX: After scanning through the entire list looking for parents - * via "In-Reply-To", we should do a second pass that looks at the - * list of messages IDs in the "References" header instead. (And - * for this the parent would be the "deepest" message of all the - * messages found in the "References" list.) - * - * Doing this will allow messages and sub-threads to be positioned - * correctly in the thread even when an intermediate message is - * missing from the thread. - */ talloc_free (local); } diff --git a/test/T510-thread-replies.sh b/test/T510-thread-replies.sh index c244054a..915e68ef 100755 --- a/test/T510-thread-replies.sh +++ b/test/T510-thread-replies.sh @@ -174,7 +174,6 @@ EOF test_expect_equal_file EXPECTED OUTPUT test_begin_subtest "reply to ghost (tree view)" -test_subtest_known_broken test_emacs '(notmuch-tree "id:000-real-root@example.org") (notmuch-test-wait) (test-output)