From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on dcvr.yhbt.net X-Spam-Level: X-Spam-ASN: X-Spam-Status: No, score=-4.0 required=3.0 tests=ALL_TRUSTED,BAYES_00 shortcircuit=no autolearn=ham autolearn_force=no version=3.4.2 Received: from localhost (dcvr.yhbt.net [127.0.0.1]) by dcvr.yhbt.net (Postfix) with ESMTP id 2F33D1F9F4 for ; Thu, 16 Sep 2021 02:19:44 +0000 (UTC) From: Eric Wong To: meta@public-inbox.org Subject: [PATCH 3/3] imapd: sort LIST response Date: Wed, 15 Sep 2021 21:19:43 -0500 Message-Id: <20210916021943.22529-4-e@80x24.org> In-Reply-To: <20210916021943.22529-1-e@80x24.org> References: <20210916021943.22529-1-e@80x24.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit List-Id: While RFC 3501 doesn't require LIST responses be sorted, it makes reading protocol dumps easier and we memoize it once per-refresh, so it shouldn't be too expensive even with thousands of folders. --- lib/PublicInbox/IMAP.pm | 4 ++-- lib/PublicInbox/IMAPD.pm | 15 ++++++++++++--- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/lib/PublicInbox/IMAP.pm b/lib/PublicInbox/IMAP.pm index 37e07dae..27013ea5 100644 --- a/lib/PublicInbox/IMAP.pm +++ b/lib/PublicInbox/IMAP.pm @@ -384,7 +384,7 @@ sub ensure_slices_exist ($$$) { push @created, $sub_mailbox; } return unless @created; - my $l = $imapd->{inboxlist} or return; + my $l = $imapd->{mailboxlist} or return; push @$l, map { qq[* LIST (\\HasNoChildren) "." $_\r\n] } @created; } @@ -850,7 +850,7 @@ sub cmd_status ($$$;@) { my %patmap = ('*' => '.*', '%' => '[^\.]*'); sub cmd_list ($$$$) { my ($self, $tag, $refname, $wildcard) = @_; - my $l = $self->{imapd}->{inboxlist}; + my $l = $self->{imapd}->{mailboxlist}; if ($refname eq '' && $wildcard eq '') { # request for hierarchy delimiter $l = [ qq[* LIST (\\Noselect) "." ""\r\n] ]; diff --git a/lib/PublicInbox/IMAPD.pm b/lib/PublicInbox/IMAPD.pm index 7425409d..6aa3d12f 100644 --- a/lib/PublicInbox/IMAPD.pm +++ b/lib/PublicInbox/IMAPD.pm @@ -70,12 +70,21 @@ sub imapd_refresh_finalize { } %$mailboxes = (%$mailboxes, %{$imapd->{mailboxes}}); $imapd->{mailboxes} = $mailboxes; - $imapd->{inboxlist} = [ + $imapd->{mailboxlist} = [ + map { $_->[2] } + sort { $a->[0] cmp $b->[0] || $a->[1] <=> $b->[1] } map { - my $no = $mailboxes->{$_} == $dummy ? '' : 'No'; my $u = $_; # capitalize "INBOX" for user-familiarity $u =~ s/\Ainbox(\.|\z)/INBOX$1/i; - qq[* LIST (\\Has${no}Children) "." $u\r\n] + if ($mailboxes->{$_} == $dummy) { + [ $u, -1, + qq[* LIST (\\HasChildren) "." $u\r\n]] + } else { + $u =~ /\A(.+)\.([0-9]+)\z/ or + die "BUG: `$u' has no slice digit(s)"; + [ $1, $2 + 0, + qq[* LIST (\\HasNoChildren) "." $u\r\n] ] + } } keys %$mailboxes ]; $imapd->{pi_cfg} = $pi_cfg;