]> Sergey Matveev's repositories - public-inbox.git/blobdiff - lib/PublicInbox/LeiToMail.pm
net_reader: use and accept URIimap objects in more places
[public-inbox.git] / lib / PublicInbox / LeiToMail.pm
index e89cca712e17ab7098d9404f17d313d6b4ef8dff..b5d560c7b735a80142536b6e003acdd227005e0c 100644 (file)
@@ -14,6 +14,7 @@ use PublicInbox::LeiDedupe;
 use PublicInbox::OnDestroy;
 use PublicInbox::Git;
 use PublicInbox::GitAsyncCat;
+use PublicInbox::PktOp qw(pkt_do);
 use Symbol qw(gensym);
 use IO::Handle; # ->autoflush
 use Fcntl qw(SEEK_SET SEEK_END O_CREAT O_EXCL O_WRONLY);
@@ -331,9 +332,31 @@ sub _maildir_write_cb ($$) {
        }
 }
 
+sub _imap_write_cb ($$) {
+       my ($self, $lei) = @_;
+       my $dedupe = $lei->{dedupe};
+       $dedupe->prepare_dedupe if $dedupe;
+       my $imap_append = $lei->{nwr}->can('imap_append');
+       my $mic = $lei->{nwr}->mic_get($self->{uri});
+       my $folder = $self->{uri}->mailbox;
+       sub { # for git_to_mail
+               my ($bref, $smsg, $eml) = @_;
+               $mic // return $lei->fail; # dst may be undef-ed in last run
+               if ($dedupe) {
+                       $eml //= PublicInbox::Eml->new($$bref); # copy bref
+                       return if $dedupe->is_dup($eml, $smsg->{blob});
+               }
+               eval { $imap_append->($mic, $folder, $bref, $smsg, $eml) };
+               if (my $err = $@) {
+                       undef $mic;
+                       die $err;
+               }
+       }
+}
+
 sub write_cb { # returns a callback for git_to_mail
        my ($self, $lei) = @_;
-       # _mbox_write_cb or _maildir_write_cb
+       # _mbox_write_cb, _maildir_write_cb or _imap_write_cb
        my $m = "_$self->{base_type}_write_cb";
        $self->$m($lei);
 }
@@ -360,6 +383,18 @@ sub new {
                        "$dst exists and is not a writable file\n";
                $self->can("eml2$fmt") or die "bad mbox format: $fmt\n";
                $self->{base_type} = 'mbox';
+       } elsif ($fmt =~ /\Aimaps?\z/) { # TODO .onion support
+               require PublicInbox::NetWriter;
+               my $nwr = PublicInbox::NetWriter->new;
+               $nwr->add_url($dst);
+               $nwr->{quiet} = $lei->{opt}->{quiet};
+               my $err = $nwr->errors($dst);
+               return $lei->fail($err) if $err;
+               require PublicInbox::URIimap; # TODO: URI cast early
+               $self->{uri} = PublicInbox::URIimap->new($dst);
+               $self->{uri}->mailbox or die "No mailbox: $dst";
+               $lei->{nwr} = $nwr;
+               $self->{base_type} = 'imap';
        } else {
                die "bad mail --format=$fmt\n";
        }
@@ -394,6 +429,25 @@ sub _do_augment_maildir {
        }
 }
 
+sub _augment_imap { # PublicInbox::NetReader::imap_each cb
+       my ($url, $uid, $kw, $eml, $lei) = @_;
+       _augment($eml, $lei);
+}
+
+sub _do_augment_imap {
+       my ($self, $lei) = @_;
+       my $nwr = $lei->{nwr};
+       if ($lei->{opt}->{augment}) {
+               my $dedupe = $lei->{dedupe};
+               if ($dedupe && $dedupe->prepare_dedupe) {
+                       $nwr->imap_each($self->{uri}, \&_augment_imap, $lei);
+                       $dedupe->pause_dedupe;
+               }
+       } else { # clobber existing IMAP folder
+               $nwr->imap_delete_all($self->{uri});
+       }
+}
+
 sub _pre_augment_mbox {
        my ($self, $lei) = @_;
        my $dst = $lei->{ovv}->{dst};
@@ -445,7 +499,7 @@ sub pre_augment { # fast (1 disk seek), runs in same process as post_augment
 
 sub do_augment { # slow, runs in wq worker
        my ($self, $lei) = @_;
-       # _do_augment_maildir, _do_augment_mbox
+       # _do_augment_maildir, _do_augment_mbox, or _do_augment_imap
        my $m = "_do_augment_$self->{base_type}";
        $self->$m($lei);
 }
@@ -462,6 +516,13 @@ sub ipc_atfork_child {
        my ($self) = @_;
        my $lei = delete $self->{lei};
        $lei->lei_atfork_child;
+       if ($self->{-wq_worker_nr} == 0) {
+               local $0 = 'do_augment';
+               eval { do_augment($self, $lei) };
+               $lei->fail($@) if $@;
+               pkt_do($lei->{pkt_op_p}, '.') == 1 or
+                                       die "do_post_augment trigger: $!";
+       }
        if (my $zpipe = delete $lei->{zpipe}) {
                $lei->{1} = $zpipe->[1];
                close $zpipe->[0];