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 451631F934 for ; Sun, 23 May 2021 21:36:51 +0000 (UTC) From: Eric Wong To: meta@public-inbox.org Subject: [PATCH 1/2] lei inspect: use LeiMailSync->match_imap_url Date: Sun, 23 May 2021 21:36:50 +0000 Message-Id: <20210523213651.24941-2-e@80x24.org> In-Reply-To: <20210523213651.24941-1-e@80x24.org> References: <20210523213651.24941-1-e@80x24.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit List-Id: Move match_imap_url into LeiMailSync so it can be used in more places, such as "lei inspect". Upcoming commands such as "lei forget-mail-sync" and {add,forget,pause,resume}-watch will also support relaxed IMAP matching rules since there's no reasonable way to expect users use ";UIDVALIDITY=" on the command-line. --- lib/PublicInbox/LeiExportKw.pm | 43 ++++++---------------------------- lib/PublicInbox/LeiInspect.pm | 13 +--------- lib/PublicInbox/LeiMailSync.pm | 32 +++++++++++++++++++++++++ t/lei-import-imap.t | 10 ++++++-- 4 files changed, 48 insertions(+), 50 deletions(-) diff --git a/lib/PublicInbox/LeiExportKw.pm b/lib/PublicInbox/LeiExportKw.pm index 82a4db04..404570c5 100644 --- a/lib/PublicInbox/LeiExportKw.pm +++ b/lib/PublicInbox/LeiExportKw.pm @@ -75,7 +75,7 @@ sub input_path_url { my $mdir = $1; require PublicInbox::LeiToMail; # kw2suffix $lms->each_src($input, \&export_kw_md, $self, $mdir); - } elsif ($input =~ m!\Aimaps?://!) { + } elsif ($input =~ m!\Aimaps?://i!) { my $uri = PublicInbox::URIimap->new($input); my $mic = $self->{nwr}->mic_for_folder($uri); $lms->each_src($$uri, \&export_kw_imap, $self, $mic); @@ -84,37 +84,6 @@ sub input_path_url { $lms->lms_commit; } -sub match_imap_url ($$) { - my ($all, $url) = @_; # $all = [ $lms->folders ]; - require PublicInbox::URIimap; - my $cli = PublicInbox::URIimap->new($url)->canonical; - my ($s, $h, $mb) = ($cli->scheme, $cli->host, $cli->mailbox); - my @uri = map { PublicInbox::URIimap->new($_)->canonical } - grep(m!\A\Q$s\E://.*?\Q$h\E\b.*?/\Q$mb\E\b!, @$all); - my @match; - for my $x (@uri) { - next if $x->mailbox ne $cli->mailbox; - next if $x->host ne $cli->host; - next if $x->port != $cli->port; - my $x_uidval = $x->uidvalidity; - next if ($cli->uidvalidity // $x_uidval) != $x_uidval; - - # allow nothing in CLI to possibly match ";AUTH=ANONYMOUS" - if (defined($x->auth) && !defined($cli->auth) && - !defined($cli->user)) { - push @match, $x; - # or maybe user was forgotten on CLI: - } elsif (defined($x->user) && !defined($cli->user)) { - push @match, $x; - } elsif (($x->user//"\0") eq ($cli->user//"\0")) { - push @match, $x; - } - } - return $match[0] if scalar(@match) <= 1; - warn "E: `$url' is ambiguous:\n\t", join("\n\t", @match), "\n"; - undef; -} - sub lei_export_kw { my ($lei, @folders) = @_; my $sto = $lei->_lei_store or return $lei->fail(<match_imap_url($orig, $all); + if (ref $res) { + $_ = $$res; $lei->qerr(<err($res) if defined $res; push @no, $orig; } } else { @@ -188,7 +159,7 @@ EOF $lei->{opt}->{'mail-sync'} = 1; # for prepare_inputs $self->prepare_inputs($lei, \@folders) or return; my $j = $opt->{jobs} // scalar(@{$self->{inputs}}) || 1; - if (my @ro = grep(!/\A(?:maildir|imaps?):/, @folders)) { + if (my @ro = grep(!/\A(?:maildir|imaps?):/i, @folders)) { return $lei->fail("cannot export to read-only folders: @ro"); } my $m = $opt->{mode} // 'merge'; diff --git a/lib/PublicInbox/LeiInspect.pm b/lib/PublicInbox/LeiInspect.pm index f79ebc9a..7fd33289 100644 --- a/lib/PublicInbox/LeiInspect.pm +++ b/lib/PublicInbox/LeiInspect.pm @@ -31,18 +31,7 @@ sub inspect_sync_folder ($$) { my $lms = $lse->lms or return $ent; my @folders; if ($folder =~ m!\Aimaps?://!i) { - require PublicInbox::URIimap; - my $uri = PublicInbox::URIimap->new($folder)->canonical; - if (defined($uri->uidvalidity)) { - $folders[0] = $$uri; - } else { - my @maybe = $lms->folders($$uri); - @folders = grep { - my $u = PublicInbox::URIimap->new($_); - $uri->uidvalidity($u->uidvalidity); - $$uri eq $$u; - } @maybe; - } + @folders = map { $_->as_string } $lms->match_imap_url($folder); } elsif ($folder =~ m!\A(maildir|mh):(.+)!i) { my $type = lc $1; $folders[0] = "$type:".$lei->abs_path($2); diff --git a/lib/PublicInbox/LeiMailSync.pm b/lib/PublicInbox/LeiMailSync.pm index 32e17c65..b2986686 100644 --- a/lib/PublicInbox/LeiMailSync.pm +++ b/lib/PublicInbox/LeiMailSync.pm @@ -265,4 +265,36 @@ WHERE b.oidbin = ? undef; } +sub match_imap_url { + my ($self, $url, $all) = @_; # $all = [ $lms->folders ]; + $all //= [ $self->folders ]; + require PublicInbox::URIimap; + my $want = PublicInbox::URIimap->new($url)->canonical; + my ($s, $h, $mb) = ($want->scheme, $want->host, $want->mailbox); + my @uri = map { PublicInbox::URIimap->new($_)->canonical } + grep(m!\A\Q$s\E://.*?\Q$h\E\b.*?/\Q$mb\E\b!, @$all); + my @match; + for my $x (@uri) { + next if $x->mailbox ne $want->mailbox; + next if $x->host ne $want->host; + next if $x->port != $want->port; + my $x_uidval = $x->uidvalidity; + next if ($want->uidvalidity // $x_uidval) != $x_uidval; + + # allow nothing in want to possibly match ";AUTH=ANONYMOUS" + if (defined($x->auth) && !defined($want->auth) && + !defined($want->user)) { + push @match, $x; + # or maybe user was forgotten on CLI: + } elsif (defined($x->user) && !defined($want->user)) { + push @match, $x; + } elsif (($x->user//"\0") eq ($want->user//"\0")) { + push @match, $x; + } + } + return @match if wantarray; + scalar(@match) <= 1 ? $match[0] : + "E: `$url' is ambiguous:\n\t".join("\n\t", @match)."\n"; +} + 1; diff --git a/t/lei-import-imap.t b/t/lei-import-imap.t index d424ebb1..d3935c82 100644 --- a/t/lei-import-imap.t +++ b/t/lei-import-imap.t @@ -22,9 +22,15 @@ test_lei({ tmpdir => $tmpdir }, sub { is_deeply(json_utf8->decode($lei_out), {}, 'no inspect stats, yet'); lei_ok('import', $url); + lei_ok('inspect', $url); + my $res = json_utf8->decode($lei_out); + is(scalar keys %$res, 1, 'got one key in inspect URL'); + my $re = qr!\Aimap://;AUTH=ANONYMOUS\@\Q$host_port\E + /t\.v2\.0;UIDVALIDITY=\d+!x; + like((keys %$res)[0], qr/$re\z/, 'got expanded key'); + lei_ok 'ls-mail-sync'; - like($lei_out, qr!\Aimap://;AUTH=ANONYMOUS\@\Q$host_port\E - /t\.v2\.0;UIDVALIDITY=\d+\n\z!x, 'ls-mail-sync'); + like($lei_out, qr!$re\n\z!, 'ls-mail-sync'); chomp(my $u = $lei_out); lei_ok('import', $u, \'UIDVALIDITY match in URL'); $url = $u;