From c4ccaf0fdbd0d901df5de286af5d795217902e2d Mon Sep 17 00:00:00 2001 From: Julien Masson Date: Mon, 10 Feb 2020 15:34:00 +0100 Subject: [PATCH] mu: sort childs of thread based on the sortfield only MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Today when we query a find cmd with the `--threads` option, all the childs of each thread are sorted according to their leader based on the sortfield. This patch change the way of how the childs of a thread are sorted. The threads are still sorted according to their leader but all the childs of each thread are now sorted based on the sortfield 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 reply to one of these emails in the middle, this email become the leader and the thread is displayed like this: [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 The tests cases concerning threads have also been updated. Signed-off-by: Julien Masson --- lib/mu-container.c | 93 ++++++++++++++++++++++++-------------------- mu/test-mu-threads.c | 54 ++++++++++++------------- 2 files changed, 78 insertions(+), 69 deletions(-) diff --git a/lib/mu-container.c b/lib/mu-container.c index d88ae85f..1f143441 100644 --- a/lib/mu-container.c +++ b/lib/mu-container.c @@ -353,36 +353,8 @@ container_cmp (MuContainer *a, MuContainer *b, MuMsgFieldId mfid) return mu_msg_cmp (a->msg, b->msg, mfid); } -static gboolean -container_is_leaf (const MuContainer *c) -{ - return c->child == NULL; -} - -static MuContainer* -container_max (MuContainer *a, MuContainer *b, MuMsgFieldId mfid) -{ - return container_cmp (a, b, mfid) > 0 ? a : b; -} - -static MuContainer* -find_sorted_tree_leader (MuContainer *root, SortFuncData *order) -{ - MuContainer *last_child; - - if (container_is_leaf (root)) - return root; - - if (!order->descending) - last_child = root->child->last; - else /* reversed order, first is last */ - last_child = root->child; - - return container_max (root, last_child->leader, order->mfid); -} - static int -sort_func_wrapper (MuContainer *a, MuContainer *b, SortFuncData *data) +sort_func_root (MuContainer *a, MuContainer *b, SortFuncData *data) { if (data->descending) return container_cmp (b->leader, a->leader, data->mfid); @@ -390,10 +362,56 @@ sort_func_wrapper (MuContainer *a, MuContainer *b, SortFuncData *data) return container_cmp (a->leader, b->leader, data->mfid); } +static int +sort_func_child (MuContainer *a, MuContainer *b, SortFuncData *data) +{ + if (data->descending) + return container_cmp (a, b, data->mfid); + else + return container_cmp (b, a, data->mfid); +} + static MuContainer* -container_sort_real (MuContainer *c, SortFuncData *sfdata) +container_sort(MuContainer *c, GCompareDataFunc func, SortFuncData *sfdata) { GSList *lst; + + lst = mu_container_to_list (c); + lst = g_slist_sort_with_data (lst, func, sfdata); + c = mu_container_from_list (lst); + g_slist_free (lst); + + return c; +} + +static MuContainer* +container_sort_child (MuContainer *c, SortFuncData *sfdata) +{ + MuContainer *cur, *leader; + + if (!c) + return NULL; + + /* find leader */ + leader = c->leader; + for (cur = c; cur; cur = cur->next) { + if (cur->child) + cur->child = container_sort_child (cur->child, sfdata); + if (container_cmp (cur->leader, leader, sfdata->mfid) > 0) + leader = cur->leader; + } + + c = container_sort(c, (GCompareDataFunc)sort_func_child, sfdata); + + /* set parent's leader to the one found */ + c->parent->leader = leader; + + return c; +} + +static MuContainer* +container_sort_root (MuContainer *c, SortFuncData *sfdata) +{ MuContainer *cur; if (!c) @@ -401,19 +419,10 @@ container_sort_real (MuContainer *c, SortFuncData *sfdata) for (cur = c; cur; cur = cur->next) { if (cur->child) - cur->child = container_sort_real (cur->child, sfdata); - cur->leader = find_sorted_tree_leader (cur, sfdata); + cur->child = container_sort_child (cur->child, sfdata); } - /* sort siblings */ - lst = mu_container_to_list (c); - lst = g_slist_sort_with_data(lst, - (GCompareDataFunc)sort_func_wrapper, - sfdata); - c = mu_container_from_list (lst); - g_slist_free (lst); - - return c; + return container_sort (c, (GCompareDataFunc)sort_func_root, sfdata); } MuContainer* @@ -429,7 +438,7 @@ mu_container_sort (MuContainer *c, MuMsgFieldId mfid, gboolean descending, g_return_val_if_fail (c, NULL); g_return_val_if_fail (mu_msg_field_id_is_valid(mfid), NULL); - return container_sort_real (c, &sfdata); + return container_sort_root (c, &sfdata); } diff --git a/mu/test-mu-threads.c b/mu/test-mu-threads.c index 12252df6..d3be37a1 100644 --- a/mu/test-mu-threads.c +++ b/mu/test-mu-threads.c @@ -158,9 +158,9 @@ test_mu_threads_01 (void) const tinfo items [] = { {"0", "root0@msg.id", "root0"}, - {"0:0", "child0.0@msg.id", "Re: child 0.0"}, - {"0:1", "child0.1@msg.id", "Re: child 0.1"}, - {"0:1:0", "child0.1.0@msg.id", "Re: child 0.1.0"}, + {"0:0", "child0.1@msg.id", "Re: child 0.1"}, + {"0:0:0", "child0.1.0@msg.id", "Re: child 0.1.0"}, + {"0:1", "child0.0@msg.id", "Re: child 0.0"}, {"1", "root1@msg.id", "root1"}, {"2", "root2@msg.id", "root2"}, /* next one's been promoted 2.0.0 => 2.0 */ @@ -169,8 +169,8 @@ test_mu_threads_01 (void) {"3", "child3.0.0.0.0@msg.id", "Re: child 3.0.0.0"}, /* two children of absent root 4.0 */ - {"4:0", "child4.0@msg.id", "Re: child 4.0"}, - {"4:1", "child4.1@msg.id", "Re: child 4.1"} + {"4:0", "child4.1@msg.id", "Re: child 4.1"}, + {"4:1", "child4.0@msg.id", "Re: child 4.0"} }; xpath = fill_database (MU_TESTMAILDIR3); @@ -308,13 +308,13 @@ test_mu_threads_sort_2nd_child_promotes_thread (void) { "0", "A@msg.id", "A"}, { "1", "D@msg.id", "D"}, { "2", "B@msg.id", "B"}, - { "2:0", "C@msg.id", "C"}, - { "2:1", "E@msg.id", "E"}, + { "2:0", "E@msg.id", "E"}, + { "2:1", "C@msg.id", "C"}, }; const tinfo expected_desc [] = { { "0", "B@msg.id", "B"}, - { "0:0", "E@msg.id", "E"}, - { "0:1", "C@msg.id", "C"}, + { "0:0", "C@msg.id", "C"}, + { "0:1", "E@msg.id", "E"}, { "1", "D@msg.id", "D"}, { "2", "A@msg.id", "A"}, }; @@ -334,12 +334,12 @@ test_mu_threads_sort_orphan_promotes_thread (void) const tinfo expected_asc [] = { { "0", "A@msg.id", "A"}, { "1", "D@msg.id", "D"}, - { "2:0", "C@msg.id", "C"}, - { "2:1", "E@msg.id", "E"}, + { "2:0", "E@msg.id", "E"}, + { "2:1", "C@msg.id", "C"}, }; const tinfo expected_desc [] = { - { "0:0", "E@msg.id", "E"}, - { "0:1", "C@msg.id", "C"}, + { "0:0", "C@msg.id", "C"}, + { "0:1", "E@msg.id", "E"}, { "1", "D@msg.id", "D"}, { "2", "A@msg.id", "A"}, }; @@ -357,16 +357,16 @@ test_mu_threads_sort_child_does_not_promote_thread (void) const char *query = "maildir:/sort/child-does-not-promote-thread"; const tinfo expected_asc [] = { - { "0", "X@msg.id", "X"}, - { "1", "Y@msg.id", "Y"}, - { "1:0", "A@msg.id", "A"}, + { "0", "Y@msg.id", "Y"}, + { "0:0", "A@msg.id", "A"}, + { "1", "X@msg.id", "X"}, { "2", "Z@msg.id", "Z"}, }; const tinfo expected_desc [] = { { "0", "Z@msg.id", "Z"}, - { "1", "Y@msg.id", "Y"}, - { "1:0", "A@msg.id", "A"}, - { "2", "X@msg.id", "X"}, + { "1", "X@msg.id", "X"}, + { "2", "Y@msg.id", "Y"}, + { "2:0", "A@msg.id", "A"}, }; check_sort_by_subject_asc (query, expected_asc, @@ -409,19 +409,19 @@ test_mu_threads_sort_granchild_promotes_only_subthread (void) const tinfo expected_asc [] = { { "0", "A@msg.id", "A"}, { "1", "B@msg.id", "B"}, - { "1:0", "C@msg.id", "C"}, - { "1:1", "E@msg.id", "E"}, - { "1:2", "D@msg.id", "D"}, - { "1:2:0", "F@msg.id", "F"}, + { "1:0", "E@msg.id", "E"}, + { "1:1", "D@msg.id", "D"}, + { "1:1:0", "F@msg.id", "F"}, + { "1:2", "C@msg.id", "C"}, { "2", "G@msg.id", "G"}, }; const tinfo expected_desc [] = { { "0", "G@msg.id", "G"}, { "1", "B@msg.id", "B"}, - { "1:0", "D@msg.id", "D"}, - { "1:0:0", "F@msg.id", "F"}, - { "1:1", "E@msg.id", "E"}, - { "1:2", "C@msg.id", "C"}, + { "1:0", "C@msg.id", "C"}, + { "1:1", "D@msg.id", "D"}, + { "1:1:0", "F@msg.id", "F"}, + { "1:2", "E@msg.id", "E"}, { "2", "A@msg.id", "A"}, };