From 6c2caa791bd5fbf5c4edb1a4a2c1807e527348a7 Mon Sep 17 00:00:00 2001 From: "Eric Wong (Contractor, The Linux Foundation)" Date: Mon, 19 Mar 2018 08:14:54 +0000 Subject: watchmaildir: support v2 repositories Unfortunately this gives up some minor performance tweaks we made to avoid reforking import processes. --- MANIFEST | 1 + lib/PublicInbox/WatchMaildir.pm | 29 +++++----- t/watch_maildir_v2.t | 125 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 139 insertions(+), 16 deletions(-) create mode 100644 t/watch_maildir_v2.t diff --git a/MANIFEST b/MANIFEST index 3b0b013f..4346cd9d 100644 --- a/MANIFEST +++ b/MANIFEST @@ -182,3 +182,4 @@ t/utf8.mbox t/v2writable.t t/view.t t/watch_maildir.t +t/watch_maildir_v2.t diff --git a/lib/PublicInbox/WatchMaildir.pm b/lib/PublicInbox/WatchMaildir.pm index 3adebdde..2808b726 100644 --- a/lib/PublicInbox/WatchMaildir.pm +++ b/lib/PublicInbox/WatchMaildir.pm @@ -91,18 +91,6 @@ sub _done_for_now { my ($self) = @_; my $importers = $self->{importers}; foreach my $im (values %$importers) { - $im->barrier; - } - - my $opendirs = $self->{opendirs}; - - # spamdir scanning means every importer remains open - my $spamdir = $self->{spamdir}; - return if defined($spamdir) && $opendirs->{$spamdir}; - - foreach my $im (values %$importers) { - # not done if we're scanning - next if $opendirs->{$im->{git}->{git_dir}}; $im->done; } } @@ -267,10 +255,19 @@ sub _path_to_mime { sub _importer_for { my ($self, $inbox) = @_; my $im = $inbox->{-import} ||= eval { - my $git = $inbox->git; - my $name = $inbox->{name}; - my $addr = $inbox->{-primary_address}; - PublicInbox::Import->new($git, $name, $addr, $inbox); + my $v = $inbox->{version} || 1; + if ($v == 2) { + eval { require PublicInbox::V2Writable }; + die "v2 not supported: $@\n" if $@; + PublicInbox::V2Writable->new($inbox); + } elsif ($v == 1) { + my $git = $inbox->git; + my $name = $inbox->{name}; + my $addr = $inbox->{-primary_address}; + PublicInbox::Import->new($git, $name, $addr, $inbox); + } else { + die "unsupported inbox version: $v\n"; + } }; my $importers = $self->{importers}; diff --git a/t/watch_maildir_v2.t b/t/watch_maildir_v2.t new file mode 100644 index 00000000..85130e3c --- /dev/null +++ b/t/watch_maildir_v2.t @@ -0,0 +1,125 @@ +# Copyright (C) 2018 all contributors +# License: AGPL-3.0+ +use Test::More; +use File::Temp qw/tempdir/; +use PublicInbox::MIME; +use Cwd; +use PublicInbox::Config; +my @mods = qw(Filesys::Notify::Simple PublicInbox::V2Writable); +foreach my $mod (@mods) { + eval "require $mod"; + plan skip_all => "$mod missing for watch_maildir_v2.t" if $@; +} + +my $tmpdir = tempdir('watch_maildir-v2-XXXXXX', TMPDIR => 1, CLEANUP => 1); +my $mainrepo = "$tmpdir/v2"; +my $maildir = "$tmpdir/md"; +my $spamdir = "$tmpdir/spam"; +use_ok 'PublicInbox::WatchMaildir'; +use_ok 'PublicInbox::Emergency'; +my $cfgpfx = "publicinbox.test"; +my $addr = 'test-public@example.com'; +my @cmd = ('blib/script/public-inbox-init', '-V2', 'test', $mainrepo, + 'http://example.com/v2list', $addr); +local $ENV{PI_CONFIG} = "$tmpdir/pi_config"; +is(system(@cmd), 0, 'public-inbox init OK'); + +my $msg = < +Date: Sat, 18 Jun 2016 00:00:00 +0000 + +something +EOF +PublicInbox::Emergency->new($maildir)->prepare(\$msg); +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({ + "$cfgpfx.address" => $addr, + "$cfgpfx.mainrepo" => $mainrepo, + "$cfgpfx.watch" => "maildir:$maildir", + "$cfgpfx.filter" => 'PublicInbox::Filter::Vger', + "publicinboxlearn.watchspam" => "maildir:$spamdir", +}); +my $ibx = $config->lookup_name('test'); +ok($ibx, 'found inbox by name'); +my $srch = $ibx->search; + +PublicInbox::WatchMaildir->new($config)->scan('full'); +my $res = $srch->reopen->query(''); +is($res->{total}, 1, 'got one revision'); + +# my $git = PublicInbox::Git->new("$mainrepo/git/0.git"); +# my @list = $git->qx(qw(rev-list refs/heads/master)); +# is(scalar @list, 1, 'one revision in rev-list'); + +my $write_spam = sub { + is(scalar glob("$spamdir/new/*"), undef, 'no spam existing'); + $sem->prepare(\$msg); + $sem->commit; + my @new = glob("$spamdir/new/*"); + is(scalar @new, 1); + my @p = split(m!/+!, $new[0]); + ok(link($new[0], "$spamdir/cur/".$p[-1].":2,S")); + is(unlink($new[0]), 1); +}; +$write_spam->(); +is(unlink(glob("$maildir/new/*")), 1, 'unlinked old spam'); +PublicInbox::WatchMaildir->new($config)->scan('full'); +is($srch->reopen->query('')->{total}, 0, 'deleted file'); + +# check with scrubbing +{ + $msg .= qq(-- +To unsubscribe from this list: send the line "unsubscribe git" in +the body of a message to majordomo\@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html\n); + PublicInbox::Emergency->new($maildir)->prepare(\$msg); + PublicInbox::WatchMaildir->new($config)->scan('full'); + $res = $srch->reopen->query(''); + is($res->{total}, 1, 'got one file back'); + my $mref = $ibx->msg_by_smsg($res->{msgs}->[0]); + like($$mref, qr/something\n\z/s, 'message scrubbed on import'); + + is(unlink(glob("$maildir/new/*")), 1, 'unlinked spam'); + $write_spam->(); + PublicInbox::WatchMaildir->new($config)->scan('full'); + $res = $srch->reopen->query(''); + is($res->{total}, 0, 'inbox is empty again'); +} + +{ + my $fail_bin = getcwd()."/t/fail-bin"; + ok(-x "$fail_bin/spamc", "mock spamc exists"); + my $fail_path = "$fail_bin:$ENV{PATH}"; # for spamc ham mock + local $ENV{PATH} = $fail_path; + PublicInbox::Emergency->new($maildir)->prepare(\$msg); + $config->{'publicinboxwatch.spamcheck'} = 'spamc'; + { + local $SIG{__WARN__} = sub {}; # quiet spam check warning + PublicInbox::WatchMaildir->new($config)->scan('full'); + } + $res = $srch->reopen->query(''); + is($res->{total}, 0, 'inbox is still empty'); + is(unlink(glob("$maildir/new/*")), 1); +} + +{ + my $main_bin = getcwd()."/t/main-bin"; + ok(-x "$main_bin/spamc", "mock spamc exists"); + my $main_path = "$main_bin:$ENV{PATH}"; # for spamc ham mock + local $ENV{PATH} = $main_path; + PublicInbox::Emergency->new($maildir)->prepare(\$msg); + $config->{'publicinboxwatch.spamcheck'} = 'spamc'; + PublicInbox::WatchMaildir->new($config)->scan('full'); + $res = $srch->reopen->query(''); + is($res->{total}, 1, 'inbox has one mail after spamc OK-ed a message'); + my $mref = $ibx->msg_by_smsg($res->{msgs}->[0]); + like($$mref, qr/something\n\z/s, 'message scrubbed on import'); +} + +done_testing; -- cgit v1.2.3-24-ge0c7