aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Bremner <david@tethera.net>2018-08-30 08:29:07 -0300
committerDavid Bremner <david@tethera.net>2018-09-06 08:07:13 -0300
commita33085828408ec421bcfcf23449b51e0a0e3cece (patch)
treec5ec41a779e160c80c9b45e90749f4b7d439052a
parentac2146118b83ca08aa6dd1275f65eefaed9fe2c0 (diff)
lib/thread: initial use of references as for fallback parenting
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.
-rw-r--r--lib/thread.cc43
-rwxr-xr-xtest/T510-thread-replies.sh1
2 files changed, 41 insertions, 3 deletions
diff --git a/lib/thread.cc b/lib/thread.cc
index 4711319d..bca1fb8f 100644
--- a/lib/thread.cc
+++ b/lib/thread.cc
@@ -414,21 +414,51 @@ _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)
@@ -439,7 +469,15 @@ _resolve_thread_relationships (notmuch_thread_t *thread)
message = first_node->message;
if (_notmuch_message_list_empty(thread->toplevel_list) ||
! _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 (! _notmuch_message_list_empty (thread->toplevel_list))
+ _parent_or_toplevel (thread, message);
+ else
+ _notmuch_message_list_add_message (thread->toplevel_list, message);
}
}
@@ -459,6 +497,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