unofficial mirror of notmuch@notmuchmail.org
 help / color / mirror / code / Atom feed
From: David Bremner <david@tethera.net>
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	[thread overview]
Message-ID: <20180830112915.11761-8-david@tethera.net> (raw)
In-Reply-To: <20180830112915.11761-1-david@tethera.net>

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 <<EOF > EXPECTED
 Subject: root message
-- 
2.18.0

  parent reply	other threads:[~2018-08-30 11:29 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-08-30 11:29 threading replies fixes v3 David Bremner
2018-08-30 11:29 ` [PATCH 01/15] util: add DEBUG_PRINTF, rename error_util.h -> debug_print.h David Bremner
2018-09-01 17:06   ` Tomi Ollila
2018-09-03 11:54     ` David Bremner
2018-08-30 11:29 ` [PATCH 02/15] test: start threading test corpus David Bremner
2018-08-30 11:29 ` [PATCH 03/15] test: add known broken tests for "ghost roots" David Bremner
2018-08-30 11:29 ` [PATCH 04/15] lib/thread: sort sibling messages by date David Bremner
2018-09-01 17:11   ` Tomi Ollila
2018-09-03 15:18     ` David Bremner
2018-08-30 11:29 ` [PATCH 05/15] lib: read reference terms into message struct David Bremner
2018-08-30 11:29 ` [PATCH 06/15] lib/thread: refactor in_reply_to test David Bremner
2018-09-01 20:02   ` Tomi Ollila
2018-08-30 11:29 ` David Bremner [this message]
2018-08-30 11:29 ` [PATCH 08/15] lib: calculate message depth in thread David Bremner
2018-08-30 11:29 ` [PATCH 09/15] lib/thread: rewrite _parent_or_toplevel to use depths David Bremner
2018-08-30 11:29 ` [PATCH 10/15] lib/thread: change _resolve_thread_relationships " David Bremner
2018-08-30 11:29 ` [PATCH 11/15] test: add known broken test for good In-Reply-To / bad References David Bremner
2018-08-30 11:29 ` [PATCH 12/15] test/thread-replies: mangle In-Reply-To's David Bremner
2018-08-30 11:29 ` [PATCH 13/15] util/string-util: export skip_space David Bremner
2018-08-30 11:29 ` [PATCH 14/15] lib: add _notmuch_message_id_parse_strict David Bremner
2018-09-01 20:27   ` Tomi Ollila
2018-08-30 11:29 ` [PATCH 15/15] lib: change parent strategy to use In-Reply-To if it looks sane David Bremner
2018-09-01 20:29   ` Tomi Ollila

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://notmuchmail.org/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20180830112915.11761-8-david@tethera.net \
    --to=david@tethera.net \
    --cc=notmuch@notmuchmail.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://yhetil.org/notmuch.git/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).