user/dev discussion of public-inbox itself
 help / color / mirror / code / Atom feed
0aa1322997fb8381ae34c132b6f1ade02b0f598f blob 3354 bytes (raw)

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
 
# Copyright (C) 2021 all contributors <meta@public-inbox.org>
# License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt>

# front-end for the "lei convert" sub-command
package PublicInbox::LeiConvert;
use strict;
use v5.10.1;
use parent qw(PublicInbox::IPC PublicInbox::LeiInput);
use PublicInbox::Eml;
use PublicInbox::LeiStore;
use PublicInbox::LeiOverview;

sub mbox_cb {
	my ($eml, $self) = @_;
	my $kw = PublicInbox::MboxReader::mbox_keywords($eml);
	$eml->header_set($_) for qw(Status X-Status);
	$self->{wcb}->(undef, { kw => $kw }, $eml);
}

sub net_cb { # callback for ->imap_each, ->nntp_each
	my (undef, undef, $kw, $eml, $self) = @_; # @_[0,1]: url + uid ignored
	$self->{wcb}->(undef, { kw => $kw }, $eml);
}

sub mdir_cb {
	my ($f, $kw, $eml, $self) = @_;
	$self->{wcb}->(undef, { kw => $kw }, $eml);
}

sub convert_fh ($$$$) {
	my ($self, $ifmt, $fh, $name) = @_;
	if ($ifmt eq 'eml') {
		my $buf = do { local $/; <$fh> } //
			return $self->{lei}->child_error(1 << 8, <<"");
error reading $name: $!

		my $eml = PublicInbox::Eml->new(\$buf);
		$self->{wcb}->(undef, { kw => [] }, $eml);
	} else {
		PublicInbox::MboxReader->$ifmt($fh, \&mbox_cb, $self);
	}
}

sub do_convert { # via wq_do
	my ($self) = @_;
	my $lei = $self->{lei};
	my $in_fmt = $lei->{opt}->{'in-format'};
	my $mics;
	if (my $stdin = delete $self->{0}) {
		convert_fh($self, $in_fmt, $stdin, '<stdin>');
	}
	for my $input (@{$self->{inputs}}) {
		my $ifmt = lc($in_fmt // '');
		if ($input =~ m!\Aimaps?://!) {
			$lei->{net}->imap_each($input, \&net_cb, $self);
			next;
		} elsif ($input =~ m!\A(?:nntps?|s?news)://!) {
			$lei->{net}->nntp_each($input, \&net_cb, $self);
			next;
		} elsif ($input =~ s!\A([a-z0-9]+):!!i) {
			$ifmt = lc $1;
		}
		if (-f $input) {
			my $m = $lei->{opt}->{'lock'} //
					($ifmt eq 'eml' ? ['none'] :
					PublicInbox::MboxLock->defaults);
			my $mbl = PublicInbox::MboxLock->acq($input, 0, $m);
			convert_fh($self, $ifmt, $mbl->{fh}, $input);
		} elsif (-d _) {
			PublicInbox::MdirReader::maildir_each_eml($input,
							\&mdir_cb, $self);
		} else {
			die "BUG: $input unhandled"; # should've failed earlier
		}
	}
	delete $lei->{1};
	delete $self->{wcb}; # commit
}

sub lei_convert { # the main "lei convert" method
	my ($lei, @inputs) = @_;
	$lei->{opt}->{kw} //= 1;
	$lei->{opt}->{dedupe} //= 'none';
	my $self = $lei->{cnv} = bless {}, __PACKAGE__;
	my $ovv = PublicInbox::LeiOverview->new($lei, 'out-format');
	$lei->{l2m} or return
		$lei->fail("output not specified or is not a mail destination");
	$lei->{opt}->{augment} = 1 unless $ovv->{dst} eq '/dev/stdout';
	$self->prepare_inputs($lei, \@inputs) or return;
	my $op = $lei->workers_start($self, 'lei_convert', 1, {
		'' => [ $lei->can('dclose'), $lei ]
	});
	$self->wq_io_do('do_convert', []);
	$self->wq_close(1);
	while ($op && $op->{sock}) { $op->event_step }
}

sub ipc_atfork_child {
	my ($self) = @_;
	my $lei = $self->{lei};
	$lei->lei_atfork_child;
	my $l2m = delete $lei->{l2m};
	if (my $net = $lei->{net}) { # may prompt user once
		$net->{mics_cached} = $net->imap_common_init($lei);
		$net->{nn_cached} = $net->nntp_common_init($lei);
	}
	$SIG{__WARN__} = PublicInbox::Eml::warn_ignore_cb();
	$l2m->pre_augment($lei);
	$l2m->do_augment($lei);
	$l2m->post_augment($lei);
	$self->{wcb} = $l2m->write_cb($lei);
	$self->SUPER::ipc_atfork_child;
}

1;
debug log:

solving 0aa13229 ...
found 0aa13229 in https://80x24.org/public-inbox.git

Code repositories for project(s) associated with this inbox:

	https://80x24.org/public-inbox.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).