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 50D061F803 for ; Sat, 5 Jan 2019 08:36:50 +0000 (UTC) From: Eric Wong To: meta@public-inbox.org Subject: [PATCH 1/3] watchmaildir: support multiple inboxes in the same Maildir Date: Sat, 5 Jan 2019 08:36:47 +0000 Message-Id: <20190105083649.27331-2-e@80x24.org> In-Reply-To: <20190105083649.27331-1-e@80x24.org> References: <20190105083649.27331-1-e@80x24.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit List-Id: Not sure what I was smoking when I originally wrote this code. cf. https://public-inbox.org/meta/874li887mp.fsf@vuxu.org/ --- lib/PublicInbox/WatchMaildir.pm | 54 +++++++++++++++++++++------------ t/watch_maildir_v2.t | 38 +++++++++++++++++++++-- 2 files changed, 69 insertions(+), 23 deletions(-) diff --git a/lib/PublicInbox/WatchMaildir.pm b/lib/PublicInbox/WatchMaildir.pm index b558cda..064cedf 100644 --- a/lib/PublicInbox/WatchMaildir.pm +++ b/lib/PublicInbox/WatchMaildir.pm @@ -20,6 +20,7 @@ package PublicInbox::WatchMaildir; sub new { my ($class, $config) = @_; my (%mdmap, @mdir, $spamc, $spamdir); + my %uniq; # "publicinboxwatch" is the documented namespace # "publicinboxlearn" is legacy but may be supported @@ -32,7 +33,17 @@ sub new { # skip "new", no MUA has seen it, yet. my $cur = "$dir/cur"; $spamdir = $cur; + my $old = $mdmap{$cur}; + if (ref($old)) { + foreach my $ibx (@$old) { + warn <<""; +"$cur already watched for `$ibx->{name}' + + } + die; + } push @mdir, $cur; + $uniq{$cur}++; $mdmap{$cur} = 'watchspam'; } else { warn "unsupported $k=$dir\n"; @@ -58,10 +69,11 @@ sub new { } my $new = "$watch/new"; my $cur = "$watch/cur"; - push @mdir, $new, $cur; - die "$new already in use\n" if $mdmap{$new}; - die "$cur already in use\n" if $mdmap{$cur}; - $mdmap{$new} = $mdmap{$cur} = $ibx; + push @mdir, $new unless $uniq{$new}++; + push @mdir, $cur unless $uniq{$cur}++; + + push @{$mdmap{$new} ||= []}, $ibx; + push @{$mdmap{$cur} ||= []}, $ibx; } else { warn "watch unsupported: $k=$watch\n"; } @@ -134,28 +146,30 @@ sub _try_path { warn "unrecognized path: $path\n"; return; } - my $inbox = $self->{mdmap}->{$1}; - unless ($inbox) { + my $inboxes = $self->{mdmap}->{$1}; + unless ($inboxes) { warn "unmappable dir: $1\n"; return; } - if (!ref($inbox) && $inbox eq 'watchspam') { + if (!ref($inboxes) && $inboxes eq 'watchspam') { return _remove_spam($self, $path); } - my $im = _importer_for($self, $inbox); - my $mime = _path_to_mime($path) or return; - my $wm = $inbox->{-watchheader}; - if ($wm) { - my $v = $mime->header_obj->header_raw($wm->[0]); - return unless ($v && $v =~ $wm->[1]); - } - if (my $scrub = $inbox->filter) { - my $ret = $scrub->scrub($mime) or return; - $ret == REJECT() and return; - $mime = $ret; - } + foreach my $ibx (@$inboxes) { + my $mime = _path_to_mime($path) or next; + my $im = _importer_for($self, $ibx); - $im->add($mime, $self->{spamcheck}); + my $wm = $ibx->{-watchheader}; + if ($wm) { + my $v = $mime->header_obj->header_raw($wm->[0]); + next unless ($v && $v =~ $wm->[1]); + } + if (my $scrub = $ibx->filter) { + my $ret = $scrub->scrub($mime) or next; + $ret == REJECT() and next; + $mime = $ret; + } + $im->add($mime, $self->{spamcheck}); + } } sub quit { trigger_scan($_[0], 'quit') } diff --git a/t/watch_maildir_v2.t b/t/watch_maildir_v2.t index fc002dc..3b5d2b8 100644 --- a/t/watch_maildir_v2.t +++ b/t/watch_maildir_v2.t @@ -38,13 +38,14 @@ ok(POSIX::mkfifo("$maildir/cur/fifo", 0777), 'create FIFO to ensure we do not get stuck on it :P'); my $sem = PublicInbox::Emergency->new($spamdir); # create dirs -my $config = PublicInbox::Config->new({ +my %orig = ( "$cfgpfx.address" => $addr, "$cfgpfx.mainrepo" => $mainrepo, "$cfgpfx.watch" => "maildir:$maildir", "$cfgpfx.filter" => 'PublicInbox::Filter::Vger', - "publicinboxlearn.watchspam" => "maildir:$spamdir", -}); + "publicinboxlearn.watchspam" => "maildir:$spamdir" +); +my $config = PublicInbox::Config->new({%orig}); my $ibx = $config->lookup_name('test'); ok($ibx, 'found inbox by name'); my $srch = $ibx->search; @@ -137,4 +138,35 @@ More majordomo info at http://vger.kernel.org/majordomo-info.html\n); is($post->{blob}, $msgs->[0]->{blob}, 'same message'); } +# multiple inboxes in the same maildir +{ + my $v1repo = "$tmpdir/v1"; + my $v1pfx = "publicinbox.v1"; + my $v1addr = 'v1-public@example.com'; + is(system(qw(git init -q --bare), $v1repo), 0, 'v1 init OK'); + my $config = PublicInbox::Config->new({ + %orig, + "$v1pfx.address" => $v1addr, + "$v1pfx.mainrepo" => $v1repo, + "$v1pfx.watch" => "maildir:$maildir", + }); + my $both = < +Date: Sat, 18 Jun 2016 00:00:00 +0000 + +both +EOF + PublicInbox::Emergency->new($maildir)->prepare(\$both); + PublicInbox::WatchMaildir->new($config)->scan('full'); + my ($total, $msgs) = $srch->reopen->query('m:both@b.com'); + my $v1 = $config->lookup_name('v1'); + my $msg = $v1->git->cat_file($msgs->[0]->{blob}); + is($both, $$msg, 'got original message back from v1'); + $msg = $ibx->git->cat_file($msgs->[0]->{blob}); + is($both, $$msg, 'got original message back from v2'); +} + done_testing; -- EW