diff --git a/lib/message.cc b/lib/message.cc index 153e4bed..23266c1a 100644 --- a/lib/message.cc +++ b/lib/message.cc @@ -588,6 +588,58 @@ _notmuch_message_add_reply (notmuch_message_t *message, _notmuch_message_list_add_message (message->replies, reply); } +static int +_cmpmsg (const void *pa, const void *pb) +{ + notmuch_message_t **a = (notmuch_message_t **) pa; + notmuch_message_t **b = (notmuch_message_t **) pb; + time_t time_a = notmuch_message_get_date (*a); + time_t time_b = notmuch_message_get_date (*b); + + if (time_a == time_b) + return 0; + else if (time_a < time_b) + return -1; + else + return 1; +} + +notmuch_message_list_t * +_notmuch_message_sort_subtrees (void *ctx, notmuch_message_list_t *list) +{ + + size_t count = 0; + size_t capacity = 16; + + if (! list) + return list; + + void *local = talloc_new (NULL); + notmuch_message_list_t *new_list = _notmuch_message_list_create (ctx); + notmuch_message_t **message_array = talloc_zero_array (local, notmuch_message_t *, capacity); + + for (notmuch_messages_t *messages = _notmuch_messages_create (list); + notmuch_messages_valid (messages); + notmuch_messages_move_to_next (messages)) { + notmuch_message_t *root = notmuch_messages_get (messages); + if (count >= capacity) { + capacity *= 2; + message_array = talloc_realloc (local, message_array, notmuch_message_t *, capacity); + } + message_array[count++] = root; + root->replies = _notmuch_message_sort_subtrees (root, root->replies); + } + + qsort (message_array, count, sizeof (notmuch_message_t *), _cmpmsg); + for (size_t i = 0; i < count; i++) { + _notmuch_message_list_add_message (new_list, message_array[i]); + } + + talloc_free (local); + talloc_free (list); + return new_list; +} + notmuch_messages_t * notmuch_message_get_replies (notmuch_message_t *message) { diff --git a/lib/notmuch-private.h b/lib/notmuch-private.h index 3764a6a9..39fc4757 100644 --- a/lib/notmuch-private.h +++ b/lib/notmuch-private.h @@ -539,6 +539,9 @@ _notmuch_message_remove_unprefixed_terms (notmuch_message_t *message); const char * _notmuch_message_get_thread_id_only(notmuch_message_t *message); +notmuch_message_list_t * +_notmuch_message_sort_subtrees (void *ctx, notmuch_message_list_t *list); + /* sha1.c */ char * diff --git a/lib/thread.cc b/lib/thread.cc index e961c76b..b599a97d 100644 --- a/lib/thread.cc +++ b/lib/thread.cc @@ -429,6 +429,12 @@ _resolve_thread_relationships (notmuch_thread_t *thread) _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 diff --git a/test/T510-thread-replies.sh b/test/T510-thread-replies.sh index 753c7ae1..72af50df 100755 --- a/test/T510-thread-replies.sh +++ b/test/T510-thread-replies.sh @@ -192,7 +192,6 @@ EOF test_expect_equal_file EXPECTED OUTPUT test_begin_subtest "reply to ghost (RT)" -test_subtest_known_broken notmuch show --entire-thread=true id:87bmc6lp3h.fsf@len.workgroup | grep ^Subject: | head -1 > OUTPUT cat < EXPECTED Subject: FYI: xxxx xxxxxxx xxxxxxxxxxxx xxx @@ -200,7 +199,6 @@ EOF test_expect_equal_file EXPECTED OUTPUT test_begin_subtest "reply to ghost (RT/tree view)" -test_subtest_known_broken test_emacs '(notmuch-tree "id:87bmc6lp3h.fsf@len.workgroup") (notmuch-test-wait) (test-output)