mu: sort children of a thread based on their own date only

This is a revival of commit c4ccaf0fdb:
"mu: sort childs of thread based on the sortfield only",
whose effect was apparently lost during the rewrite to C++.

Today when we query a find cmd with the `--threads` option, all the
children of each thread are sorted according to the most recent
message in the thread.

This patch changes how the children of a thread are sorted. Threads
are still sorted according to the thread date, but the children of each
thread are now sorted by their own date only.

Here is an example of what happened with the previous sorting:

Example with random kernel thread sorted by date:

[PATCH 0/4] drm/panel: jh057n0090: Add regulators and drop magic value in init
  ┣━▶[PATCH 1/4] MAINTAINERS: Add Purism mail alias as reviewer for their devkit's panel
  ┣━▶[PATCH 2/4] drm/panel: jh057n0090: Don't use magic constant
  ┣━▶[PATCH 3/4] dt-bindings: display/panel: jh057n0090: Document power supply properties
  ┗━▶[PATCH 4/4] drm/panel: jh057n0090: Add regulator support

If someone replies to one of these emails in the middle, its date will
bubble-up and the sorting becomes:

[PATCH 0/4] drm/panel: jh057n0090: Add regulators and drop magic value in init
  ┣━▶[PATCH 2/4] drm/panel: jh057n0090: Don't use magic constant
  ┃  ┗━▶ Re: [PATCH 2/4] drm/panel: jh057n0090: Don't use magic constant
  ┣━▶[PATCH 1/4] MAINTAINERS: Add Purism mail alias as reviewer for their devkit's panel
  ┣━▶[PATCH 3/4] dt-bindings: display/panel: jh057n0090: Document power supply properties
  ┗━▶[PATCH 4/4] drm/panel: jh057n0090: Add regulator support

With this patch, we will have the following output:

[PATCH 0/4] drm/panel: jh057n0090: Add regulators and drop magic value in init
  ┣━▶[PATCH 1/4] MAINTAINERS: Add Purism mail alias as reviewer for their devkit's panel
  ┣━▶[PATCH 2/4] drm/panel: jh057n0090: Don't use magic constant
  ┃  ┗━▶ Re: [PATCH 2/4] drm/panel: jh057n0090: Don't use magic constant
  ┣━▶[PATCH 3/4] dt-bindings: display/panel: jh057n0090: Document power supply properties
  ┗━▶[PATCH 4/4] drm/panel: jh057n0090: Add regulator support

Cc: Julien Masson <massonju.eseo@gmail.com>
Signed-off-by: Jerome Brunet <jbrun3t@gmail.com>
This commit is contained in:
Jerome Brunet
2026-08-14 14:11:18 +02:00
committed by Seth Ladygo
parent c61d5b980a
commit f31b5eedde

View File

@ -80,6 +80,13 @@ struct Container {
std::string thread_date_key; std::string thread_date_key;
// The container's own date-key, set once from its query-match and never
// overwritten by the bubble-up above. Siblings must sort by this, not by
// thread_date_key -- otherwise a subthread gaining a new, later message
// (e.g. a reply to one message in a patch series) reorders it among its
// siblings, even though its own date didn't change.
std::string own_date_key;
Option<QueryMatch&> query_match; Option<QueryMatch&> query_match;
bool is_nuked{}; bool is_nuked{};
Container* parent{}; Container* parent{};
@ -191,9 +198,9 @@ determine_id_table(QueryResultsType& qres)
// know what query_matchs will be at the root level yet, so remember // know what query_matchs will be at the root level yet, so remember
// both. Moreover, even when sorting the top-level in descending // both. Moreover, even when sorting the top-level in descending
// order, still sort the thread levels below that in ascending // order, still sort the thread levels below that in ascending
// order. // order, keeping sibling order stable.
container.thread_date_key = container.query_match->date_key = container.own_date_key = container.thread_date_key =
mi.date_str().value_or(""); container.query_match->date_key = mi.date_str().value_or("");
// initial guess for the thread-date; might be updated // initial guess for the thread-date; might be updated
// later. // later.
@ -487,9 +494,13 @@ sort_container(Container& container)
for (auto& child : container.children) for (auto& child : container.children)
sort_container(*child); sort_container(*child);
// now sort this level; use a stable sort so messages with equal // now sort this level, by each child's own date, falling back to
// dates keep their original (mset) order. // thread_date_key if the container has no message of its own; use a
std::ranges::stable_sort(container.children, {}, &Container::thread_date_key); // stable sort so messages with equal dates keep their original (mset)
// order.
std::ranges::stable_sort(container.children, {}, [](const Container* c) {
return c->own_date_key.empty() ? c->thread_date_key : c->own_date_key;
});
// and 'bubble up' the date of the *newest* message with a date. We // and 'bubble up' the date of the *newest* message with a date. We
// reasonably assume that it's later than its parent. // reasonably assume that it's later than its parent.
@ -701,6 +712,29 @@ test_sort_descending()
{{"m1", "1:f:f:z"}, {"m2", "1:f:z"}, {"m3", "1:z"}, {"m4", "0:z"}}); {{"m1", "1:f:f:z"}, {"m2", "1:f:z"}, {"m3", "1:z"}, {"m4", "0:z"}});
} }
static void
test_sibling_order_stable()
{
auto results = MockQueryResults{
MockQueryResult{"cover", "1", {}},
MockQueryResult{"m1", "2", {"cover"}},
MockQueryResult{"m2", "3", {"cover"}},
MockQueryResult{"m3", "4", {"cover"}},
MockQueryResult{"reply-m2", "5", {"cover", "m2"}},
};
calculate_threads(results, false);
assert_thread_paths(results,
{
{"cover", "0"},
{"m1", "0:0"},
{"m2", "0:1"},
{"reply-m2", "0:1:0"},
{"m3", "0:2"},
});
}
static void static void
test_id_table_inconsistent() test_id_table_inconsistent()
{ {
@ -931,6 +965,7 @@ try {
g_test_add_func("/threader/sort/ascending", test_sort_ascending); g_test_add_func("/threader/sort/ascending", test_sort_ascending);
g_test_add_func("/threader/sort/decending", test_sort_descending); g_test_add_func("/threader/sort/decending", test_sort_descending);
g_test_add_func("/threader/sort/sibling-order-stable", test_sibling_order_stable);
g_test_add_func("/threader/id-table-inconsistent", test_id_table_inconsistent); g_test_add_func("/threader/id-table-inconsistent", test_id_table_inconsistent);
g_test_add_func("/threader/dups/dup-last", test_dups_dup_last); g_test_add_func("/threader/dups/dup-last", test_dups_dup_last);