* [PATCH 00/11] Maildir code consolidation, test updates
@ 2021-02-09 8:09 Eric Wong
2021-02-09 8:09 ` [PATCH 01/11] t/thread-index-gap.t: avoid unnecessary map Eric Wong
` (10 more replies)
0 siblings, 11 replies; 12+ messages in thread
From: Eric Wong @ 2021-02-09 8:09 UTC (permalink / raw)
To: meta
MdirReader is the home of Maildir-related code, and
-watch is updated to use some of it, as is the
InboxWritable->import_maildir (which I'm not sure
should live).
"lei q --alert=" is slightly changed for CLI-friendliness
tr/-/:/
And damn, I just misread "Cwd" as "Covid"; /me goes back
to hiding under the bed :<
Eric Wong (11):
t/thread-index-gap.t: avoid unnecessary map
test_common: disable fsync on the command-line where possible
t/cgi.t: modernizations and style updates
git: ->qx: respect caller's $/ in array context
lei: split out MdirReader package, lazy-require earlier
t/run.perl: fix for >128 tests
use MdirReader in -watch and InboxWritable
lei q: prefix --alert ops with ':' instead of '-'
t/run.perl: drop Cwd dependency
lei: replace "I:"-prefixed info messages with "#"
tests: (lei) fixes for TEST_RUN_MODE=0 and oneshot mode
MANIFEST | 2 +
lib/PublicInbox/Git.pm | 1 -
lib/PublicInbox/IPC.pm | 2 +
lib/PublicInbox/Import.pm | 6 +--
lib/PublicInbox/InboxWritable.pm | 55 +++++++++------------
lib/PublicInbox/LEI.pm | 21 ++++----
lib/PublicInbox/LeiImport.pm | 25 ++++++----
lib/PublicInbox/LeiOverview.pm | 2 +-
lib/PublicInbox/LeiToMail.pm | 26 ++++------
lib/PublicInbox/MdirReader.pm | 39 +++++++++++++++
lib/PublicInbox/TestCommon.pm | 10 +++-
lib/PublicInbox/Watch.pm | 6 ++-
t/cgi.t | 84 +++++++++++++-------------------
t/lei-import.t | 5 +-
t/lei-mirror.t | 2 +-
t/lei.t | 2 +-
t/lei_to_mail.t | 19 ++++++--
t/mdir_reader.t | 22 +++++++++
t/run.perl | 22 ++++-----
t/thread-index-gap.t | 10 ++--
20 files changed, 211 insertions(+), 150 deletions(-)
create mode 100644 lib/PublicInbox/MdirReader.pm
create mode 100644 t/mdir_reader.t
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 01/11] t/thread-index-gap.t: avoid unnecessary map
2021-02-09 8:09 [PATCH 00/11] Maildir code consolidation, test updates Eric Wong
@ 2021-02-09 8:09 ` Eric Wong
2021-02-09 8:09 ` [PATCH 02/11] test_common: disable fsync on the CLI where possible Eric Wong
` (9 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Eric Wong @ 2021-02-09 8:09 UTC (permalink / raw)
To: meta
We only care abount the number of results.
---
t/thread-index-gap.t | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/t/thread-index-gap.t b/t/thread-index-gap.t
index 83c3707d..125c5cbd 100644
--- a/t/thread-index-gap.t
+++ b/t/thread-index-gap.t
@@ -47,14 +47,12 @@ for my $msgs (['orig', reverse @msgs], ['shuffle', shuffle(@msgs)]) {
my $over = $ibx->over;
my $dbh = $over->dbh;
my $tid = $dbh->selectall_arrayref('SELECT DISTINCT(tid) FROM over');
- my @tid = map { $_->[0] } @$tid;
- is(scalar(@tid), 1, "only one thread initially ($desc)");
+ is(scalar(@$tid), 1, "only one thread initially ($desc)");
$over->dbh_close;
- run_script([qw(-index --reindex --rethread), $ibx->{inboxdir}]) or
- BAIL_OUT 'rethread';
+ run_script([qw(-index --no-fsync --reindex --rethread),
+ $ibx->{inboxdir}]) or BAIL_OUT 'rethread';
$tid = $dbh->selectall_arrayref('SELECT DISTINCT(tid) FROM over');
- @tid = map { $_->[0] } @$tid;
- is(scalar(@tid), 1, "only one thread after rethread ($desc)");
+ is(scalar(@$tid), 1, "only one thread after rethread ($desc)");
}
done_testing;
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 02/11] test_common: disable fsync on the CLI where possible
2021-02-09 8:09 [PATCH 00/11] Maildir code consolidation, test updates Eric Wong
2021-02-09 8:09 ` [PATCH 01/11] t/thread-index-gap.t: avoid unnecessary map Eric Wong
@ 2021-02-09 8:09 ` Eric Wong
2021-02-09 8:09 ` [PATCH 03/11] t/cgi.t: modernizations and style updates Eric Wong
` (8 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Eric Wong @ 2021-02-09 8:09 UTC (permalink / raw)
To: meta
This makes tests faster for users on slow TMPDIR (or not using
eatmydata) and forces coverage on a non-default switch.
Unfortunately, this doesn't yet cover InboxWritable usage.
---
lib/PublicInbox/TestCommon.pm | 3 +++
1 file changed, 3 insertions(+)
diff --git a/lib/PublicInbox/TestCommon.pm b/lib/PublicInbox/TestCommon.pm
index 2f4ca622..ec9191b6 100644
--- a/lib/PublicInbox/TestCommon.pm
+++ b/lib/PublicInbox/TestCommon.pm
@@ -269,6 +269,9 @@ sub run_script ($;$$) {
die "unable to deal with $ref $redir";
}
}
+ if ($key =~ /-(index|convert|extindex|convert|xcpdb)\z/) {
+ unshift @argv, '--no-fsync';
+ }
if ($run_mode == 0) {
# spawn an independent new process, like real-world use cases:
require PublicInbox::Spawn;
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 03/11] t/cgi.t: modernizations and style updates
2021-02-09 8:09 [PATCH 00/11] Maildir code consolidation, test updates Eric Wong
2021-02-09 8:09 ` [PATCH 01/11] t/thread-index-gap.t: avoid unnecessary map Eric Wong
2021-02-09 8:09 ` [PATCH 02/11] test_common: disable fsync on the CLI where possible Eric Wong
@ 2021-02-09 8:09 ` Eric Wong
2021-02-09 8:09 ` [PATCH 04/11] git: ->qx: respect caller's $/ in array context Eric Wong
` (7 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Eric Wong @ 2021-02-09 8:09 UTC (permalink / raw)
To: meta
We prefer BAIL_OUT or fail to die in tests (I didn't know
BAIL_OUT existed when I started the project). We can also
depend on IO::Uncompress::Gunzip being available,
We'll keep the cgi_run wrapper since the .cgi could
use some coverage and remove the FIXME note. run_script
makes tests fast enough.
---
t/cgi.t | 84 ++++++++++++++++++++++++---------------------------------
1 file changed, 35 insertions(+), 49 deletions(-)
diff --git a/t/cgi.t b/t/cgi.t
index 3818b991..567c2ee0 100644
--- a/t/cgi.t
+++ b/t/cgi.t
@@ -1,42 +1,36 @@
+#!perl -w
# Copyright (C) 2014-2021 all contributors <meta@public-inbox.org>
# License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt>
-# FIXME: this test is too slow and most non-CGI-requirements
-# should be moved over to things which use test_psgi
use strict;
-use warnings;
-use Test::More;
-use PublicInbox::Eml;
+use v5.10.1;
use PublicInbox::TestCommon;
-use PublicInbox::Import;
+use IO::Uncompress::Gunzip qw(gunzip);
require_mods(qw(Plack::Handler::CGI Plack::Util));
+require PublicInbox::Eml;
+require PublicInbox::Import;
+require PublicInbox::Inbox;
+require PublicInbox::InboxWritable;
+require PublicInbox::Config;
my ($tmpdir, $for_destroy) = tmpdir();
my $home = "$tmpdir/pi-home";
my $pi_home = "$home/.public-inbox";
my $pi_config = "$pi_home/config";
my $maindir = "$tmpdir/main.git";
my $addr = 'test-public@example.com';
-
+PublicInbox::Import::init_bare($maindir);
{
- is(1, mkdir($home, 0755), "setup ~/ for testing");
- is(1, mkdir($pi_home, 0755), "setup ~/.public-inbox");
- PublicInbox::Import::init_bare($maindir);
-
- open my $fh, '>', "$maindir/description" or die "open: $!\n";
- print $fh "test for public-inbox\n";
- close $fh or die "close: $!\n";
- open $fh, '>>', $pi_config or die;
- print $fh <<EOF or die;
+ mkdir($home, 0755) or BAIL_OUT $!;
+ mkdir($pi_home, 0755) or BAIL_OUT $!;
+ open my $fh, '>>', $pi_config or BAIL_OUT $!;
+ print $fh <<EOF or BAIL_OUT $!;
[publicinbox "test"]
address = $addr
inboxdir = $maindir
indexlevel = basic
EOF
- close $fh or die "close: $!\n";
+ close $fh or BAIL_OUT $!;
}
-use_ok 'PublicInbox::Inbox';
-use_ok 'PublicInbox::InboxWritable';
-use_ok 'PublicInbox::Config';
my $cfg = PublicInbox::Config->new($pi_config);
my $ibx = $cfg->lookup_name('test');
my $im = PublicInbox::InboxWritable->new($ibx)->importer(0);
@@ -58,7 +52,7 @@ EOF
ok($im->add($mime), 'added initial message');
$mime->header_set('Message-ID', '<toobig@example.com>');
- $mime->body_str_set("z\n" x 1024);
+ $mime->body_set("z\n" x 1024);
ok($im->add($mime), 'added big message');
# deliver a reply, too
@@ -98,7 +92,7 @@ EOF
}
# retrieve thread as an mbox
-{
+SKIP: {
local $ENV{HOME} = $home;
my $path = "/test/blahblah\@example.com/t.mbox.gz";
my $res = cgi_run($path);
@@ -109,13 +103,10 @@ EOF
if ($indexed) {
$res = cgi_run($path);
like($res->{head}, qr/^Status: 200 /, "search returned mbox");
- eval {
- require IO::Uncompress::Gunzip;
- my $in = $res->{body};
- my $out;
- IO::Uncompress::Gunzip::gunzip(\$in => \$out);
- like($out, qr/^From /m, "From lines in mbox");
- };
+ my $in = $res->{body};
+ my $out;
+ gunzip(\$in => \$out);
+ like($out, qr/^From /m, "From lines in mbox");
$res = cgi_run('/test/toobig@example.com/');
like($res->{head}, qr/^Status: 300 /,
'did not index or return >max-size message');
@@ -123,29 +114,24 @@ EOF
'warned about skipping large OID');
} else {
like($res->{head}, qr/^Status: 501 /, "search not available");
- SKIP: { skip 'DBD::SQLite not available', 4 };
- }
-
- my $have_xml_treepp = eval { require XML::TreePP; 1 } if $indexed;
- if ($have_xml_treepp) {
- $path = "/test/blahblah\@example.com/t.atom";
- $res = cgi_run($path);
- like($res->{head}, qr/^Status: 200 /, "atom returned 200");
- like($res->{head}, qr!^Content-Type: application/atom\+xml!m,
- "search returned atom");
- my $t = XML::TreePP->new->parse($res->{body});
- is(scalar @{$t->{feed}->{entry}}, 3, "parsed three entries");
- like($t->{feed}->{-xmlns}, qr/\bAtom\b/,
- 'looks like an an Atom feed');
- } else {
- SKIP: { skip 'DBD::SQLite or XML::TreePP missing', 2 };
+ skip('DBD::SQLite not available', 7); # (4 - 1) above, 4 below
}
+ require_mods('XML::TreePP', 4);
+ $path = "/test/blahblah\@example.com/t.atom";
+ $res = cgi_run($path);
+ like($res->{head}, qr/^Status: 200 /, "atom returned 200");
+ like($res->{head}, qr!^Content-Type: application/atom\+xml!m,
+ "search returned atom");
+ my $t = XML::TreePP->new->parse($res->{body});
+ is(scalar @{$t->{feed}->{entry}}, 3, "parsed three entries");
+ like($t->{feed}->{-xmlns}, qr/\bAtom\b/,
+ 'looks like an an Atom feed');
}
done_testing();
sub cgi_run {
- my %env = (
+ my $env = {
PATH_INFO => $_[0],
QUERY_STRING => $_[1] || "",
SCRIPT_NAME => '',
@@ -154,11 +140,11 @@ sub cgi_run {
GATEWAY_INTERFACE => 'CGI/1.1',
HTTP_ACCEPT => '*/*',
HTTP_HOST => 'test.example.com',
- );
+ };
my ($in, $out, $err) = ("", "", "");
my $rdr = { 0 => \$in, 1 => \$out, 2 => \$err };
- run_script(['.cgi'], \%env, $rdr);
- die "unexpected error: \$?=$? ($err)" if $?;
+ run_script(['.cgi'], $env, $rdr);
+ fail "unexpected error: \$?=$? ($err)" if $?;
my ($head, $body) = split(/\r\n\r\n/, $out, 2);
{ head => $head, body => $body, err => $err }
}
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 04/11] git: ->qx: respect caller's $/ in array context
2021-02-09 8:09 [PATCH 00/11] Maildir code consolidation, test updates Eric Wong
` (2 preceding siblings ...)
2021-02-09 8:09 ` [PATCH 03/11] t/cgi.t: modernizations and style updates Eric Wong
@ 2021-02-09 8:09 ` Eric Wong
2021-02-09 8:09 ` [PATCH 05/11] lei: split out MdirReader package, lazy-require earlier Eric Wong
` (6 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Eric Wong @ 2021-02-09 8:09 UTC (permalink / raw)
To: meta
This could lead to bad results when doing ls-tree -z
for v2 import in case there's multiple files. In any case,
the `local $/ = "\0"' in Import.pm is also eliminated to
reduce potential confusion and surprises.
---
lib/PublicInbox/Git.pm | 1 -
lib/PublicInbox/Import.pm | 6 ++----
2 files changed, 2 insertions(+), 5 deletions(-)
diff --git a/lib/PublicInbox/Git.pm b/lib/PublicInbox/Git.pm
index ac7ff267..e176921c 100644
--- a/lib/PublicInbox/Git.pm
+++ b/lib/PublicInbox/Git.pm
@@ -364,7 +364,6 @@ sub popen {
sub qx {
my $fh = popen(@_);
if (wantarray) {
- local $/ = "\n";
my @ret = <$fh>;
close $fh; # caller should check $?
@ret;
diff --git a/lib/PublicInbox/Import.pm b/lib/PublicInbox/Import.pm
index a070aa1e..e803ee74 100644
--- a/lib/PublicInbox/Import.pm
+++ b/lib/PublicInbox/Import.pm
@@ -68,11 +68,9 @@ sub gfi_start {
chomp($self->{tip} = $git->qx(qw(rev-parse --revs-only), $ref));
die "fatal: rev-parse --revs-only $ref: \$?=$?" if $?;
if ($self->{path_type} ne '2/38' && $self->{tip}) {
- local $/ = "\0";
- my @t = $git->qx(qw(ls-tree -r -z --name-only), $ref);
+ my $t = $git->qx(qw(ls-tree -r -z --name-only), $ref);
die "fatal: ls-tree -r -z --name-only $ref: \$?=$?" if $?;
- chomp @t;
- $self->{-tree} = { map { $_ => 1 } @t };
+ $self->{-tree} = { map { $_ => 1 } split(/\0/, $t) };
}
$in_r = $self->{in} = $git->popen(qw(fast-import
--quiet --done --date-format=raw),
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 05/11] lei: split out MdirReader package, lazy-require earlier
2021-02-09 8:09 [PATCH 00/11] Maildir code consolidation, test updates Eric Wong
` (3 preceding siblings ...)
2021-02-09 8:09 ` [PATCH 04/11] git: ->qx: respect caller's $/ in array context Eric Wong
@ 2021-02-09 8:09 ` Eric Wong
2021-02-09 8:09 ` [PATCH 06/11] t/run.perl: fix for >128 tests Eric Wong
` (5 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Eric Wong @ 2021-02-09 8:09 UTC (permalink / raw)
To: meta
We'll do more requires in the top-level lei-daemon process to
save work in workers. We can also work towards aborting on
user errors in lei-daemon rather than worker processes.
"lei import -f mbox*" is finally tested inside t/lei_to_mail.t
---
MANIFEST | 1 +
lib/PublicInbox/LeiImport.pm | 25 +++++++++++++++----------
lib/PublicInbox/LeiToMail.pm | 26 ++++++++++----------------
lib/PublicInbox/MdirReader.pm | 21 +++++++++++++++++++++
lib/PublicInbox/TestCommon.pm | 4 +++-
t/lei-import.t | 5 ++++-
t/lei_to_mail.t | 19 ++++++++++++++++---
7 files changed, 70 insertions(+), 31 deletions(-)
create mode 100644 lib/PublicInbox/MdirReader.pm
diff --git a/MANIFEST b/MANIFEST
index 7f417743..6b3fc812 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -199,6 +199,7 @@ lib/PublicInbox/ManifestJsGz.pm
lib/PublicInbox/Mbox.pm
lib/PublicInbox/MboxGz.pm
lib/PublicInbox/MboxReader.pm
+lib/PublicInbox/MdirReader.pm
lib/PublicInbox/MiscIdx.pm
lib/PublicInbox/MiscSearch.pm
lib/PublicInbox/MsgIter.pm
diff --git a/lib/PublicInbox/LeiImport.pm b/lib/PublicInbox/LeiImport.pm
index a63bfdfd..8358d9d4 100644
--- a/lib/PublicInbox/LeiImport.pm
+++ b/lib/PublicInbox/LeiImport.pm
@@ -6,7 +6,6 @@ package PublicInbox::LeiImport;
use strict;
use v5.10.1;
use parent qw(PublicInbox::IPC);
-use PublicInbox::MboxReader;
use PublicInbox::Eml;
use PublicInbox::InboxWritable qw(eml_from_path);
use PublicInbox::PktOp;
@@ -37,8 +36,17 @@ sub call { # the main "lei import" method
$lei->{opt}->{kw} //= 1;
my $fmt = $lei->{opt}->{'format'};
my $self = $lei->{imp} = bless {}, $cls;
- if (my @f = grep { -f } @argv && !$fmt) {
- return $lei->fail("--format unset for regular files:\n@f");
+ my @f;
+ for my $x (@argv) {
+ if (-f $x) { push @f, $x }
+ elsif (-d _) { require PublicInbox::MdirReader }
+ }
+ (@f && !$fmt) and
+ return $lei->fail("--format unset for regular file(s):\n@f");
+ if (@f && $fmt ne 'eml') {
+ require PublicInbox::MboxReader;
+ PublicInbox::MboxReader->can($fmt) or
+ return $lei->fail( "--format=$fmt unrecognized\n");
}
$self->{0} = $lei->{0} if $lei->{opt}->{stdin};
my $ops = {
@@ -83,11 +91,9 @@ error reading $x: $!
my $eml = PublicInbox::Eml->new(\$buf);
_import_eml($eml, $lei->{sto}, $set_kw);
- } else { # some mbox
- my $cb = PublicInbox::MboxReader->can($fmt);
- $cb or return $lei->child_error(1 >> 8, <<"");
---format $fmt unsupported for $x
-
+ } else { # some mbox (->can already checked in call);
+ my $cb = PublicInbox::MboxReader->can($fmt) //
+ die "BUG: bad fmt=$fmt";
$cb->(undef, $fh, \&_import_eml, $lei->{sto}, $set_kw);
}
};
@@ -109,8 +115,7 @@ unable to open $x: $!
_import_fh($lei, $fh, $x);
} elsif (-d _ && (-d "$x/cur" || -d "$x/new")) {
- require PublicInbox::LeiToMail;
- PublicInbox::LeiToMail::maildir_each_file($x,
+ PublicInbox::MdirReader::maildir_each_file($x,
\&_import_maildir,
$lei->{sto}, $lei->{opt}->{kw});
} else {
diff --git a/lib/PublicInbox/LeiToMail.pm b/lib/PublicInbox/LeiToMail.pm
index a5a196db..e3e512be 100644
--- a/lib/PublicInbox/LeiToMail.pm
+++ b/lib/PublicInbox/LeiToMail.pm
@@ -18,6 +18,7 @@ use Symbol qw(gensym);
use IO::Handle; # ->autoflush
use Fcntl qw(SEEK_SET SEEK_END O_CREAT O_EXCL O_WRONLY);
use Errno qw(EEXIST ESPIPE ENOENT EPIPE);
+my ($maildir_each_file);
# struggles with short-lived repos, Gcf2Client makes little sense with lei;
# but we may use in-process libgit2 in the future.
@@ -266,18 +267,6 @@ sub _mbox_write_cb ($$) {
}
}
-sub maildir_each_file ($$;@) {
- my ($dir, $cb, @arg) = @_;
- $dir .= '/' unless substr($dir, -1) eq '/';
- for my $d (qw(new/ cur/)) {
- my $pfx = $dir.$d;
- opendir my $dh, $pfx or next;
- while (defined(my $fn = readdir($dh))) {
- $cb->($pfx.$fn, @arg) if $fn =~ /:2,[A-Za-z]*\z/;
- }
- }
-}
-
sub _augment_file { # maildir_each_file cb
my ($f, $lei) = @_;
my $eml = PublicInbox::InboxWritable::eml_from_path($f) or return;
@@ -354,11 +343,18 @@ sub new {
my $dst = $lei->{ovv}->{dst};
my $self = bless {}, $cls;
if ($fmt eq 'maildir') {
+ $maildir_each_file //= do {
+ require PublicInbox::MdirReader;
+ PublicInbox::MdirReader->can('maildir_each_file');
+ };
+ $lei->{opt}->{augment} and
+ require PublicInbox::InboxWritable; # eml_from_path
$self->{base_type} = 'maildir';
-e $dst && !-d _ and die
"$dst exists and is not a directory\n";
$lei->{ovv}->{dst} = $dst .= '/' if substr($dst, -1) ne '/';
} elsif (substr($fmt, 0, 4) eq 'mbox') {
+ require PublicInbox::MboxReader if $lei->{opt}->{augment};
(-d $dst || (-e _ && !-w _)) and die
"$dst exists and is not a writable file\n";
$self->can("eml2$fmt") or die "bad mbox --format=$fmt\n";
@@ -389,12 +385,11 @@ sub _do_augment_maildir {
if ($lei->{opt}->{augment}) {
my $dedupe = $lei->{dedupe};
if ($dedupe && $dedupe->prepare_dedupe) {
- require PublicInbox::InboxWritable; # eml_from_path
- maildir_each_file($dst, \&_augment_file, $lei);
+ $maildir_each_file->($dst, \&_augment_file, $lei);
$dedupe->pause_dedupe;
}
} else { # clobber existing Maildir
- maildir_each_file($dst, \&_unlink);
+ $maildir_each_file->($dst, \&_unlink);
}
}
@@ -435,7 +430,6 @@ sub _do_augment_mbox {
my $rd = $zsfx ? decompress_src($out, $zsfx, $lei) :
dup_src($out);
my $fmt = $lei->{ovv}->{fmt};
- require PublicInbox::MboxReader;
PublicInbox::MboxReader->$fmt($rd, \&_augment, $lei);
}
# maybe some systems don't honor O_APPEND, Perl does this:
diff --git a/lib/PublicInbox/MdirReader.pm b/lib/PublicInbox/MdirReader.pm
new file mode 100644
index 00000000..c6a0e7a8
--- /dev/null
+++ b/lib/PublicInbox/MdirReader.pm
@@ -0,0 +1,21 @@
+# Copyright (C) 2020-2021 all contributors <meta@public-inbox.org>
+# License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt>
+
+# Maildirs for now, MH eventually
+package PublicInbox::MdirReader;
+use strict;
+use v5.10.1;
+
+sub maildir_each_file ($$;@) {
+ my ($dir, $cb, @arg) = @_;
+ $dir .= '/' unless substr($dir, -1) eq '/';
+ for my $d (qw(new/ cur/)) {
+ my $pfx = $dir.$d;
+ opendir my $dh, $pfx or next;
+ while (defined(my $fn = readdir($dh))) {
+ $cb->($pfx.$fn, @arg) if $fn =~ /:2,[A-Za-z]*\z/;
+ }
+ }
+}
+
+1;
diff --git a/lib/PublicInbox/TestCommon.pm b/lib/PublicInbox/TestCommon.pm
index ec9191b6..53f13437 100644
--- a/lib/PublicInbox/TestCommon.pm
+++ b/lib/PublicInbox/TestCommon.pm
@@ -14,7 +14,7 @@ BEGIN {
@EXPORT = qw(tmpdir tcp_server tcp_connect require_git require_mods
run_script start_script key2sub xsys xsys_e xqx eml_load tick
have_xapian_compact json_utf8 setup_public_inboxes
- tcp_host_port test_lei $lei $lei_out $lei_err $lei_opt);
+ tcp_host_port test_lei lei $lei $lei_out $lei_err $lei_opt);
require Test::More;
my @methods = grep(!/\W/, @Test::More::EXPORT);
eval(join('', map { "*$_=\\&Test::More::$_;" } @methods));
@@ -457,6 +457,8 @@ our $lei = sub {
$res;
};
+sub lei (@) { $lei->(@_) }
+
sub json_utf8 () {
state $x = ref(PublicInbox::Config->json)->new->utf8->canonical;
}
diff --git a/t/lei-import.t b/t/lei-import.t
index 709d89fa..b691798a 100644
--- a/t/lei-import.t
+++ b/t/lei-import.t
@@ -3,12 +3,14 @@
# License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt>
use strict; use v5.10.1; use PublicInbox::TestCommon;
test_lei(sub {
+ok(!$lei->(qw(import -f bogus), 't/plack-qp.eml'), 'fails with bogus format');
+like($lei_err, qr/\bbogus unrecognized/, 'gave error message');
ok($lei->(qw(q s:boolean)), 'search miss before import');
unlike($lei_out, qr/boolean/i, 'no results, yet');
open my $fh, '<', 't/data/0001.patch' or BAIL_OUT $!;
ok($lei->([qw(import -f eml -)], undef, { %$lei_opt, 0 => $fh }),
- 'import single file from stdin');
+ 'import single file from stdin') or diag $lei_err;
close $fh;
ok($lei->(qw(q s:boolean)), 'search hit after import');
ok($lei->(qw(import -f eml), 't/data/message_embed.eml'),
@@ -35,5 +37,6 @@ $res = json_utf8->decode($lei_out);
is($res->[1], undef, 'only one result');
is_deeply($res->[0]->{kw}, [], 'no keywords set');
+# see t/lei_to_mail.t for "import -f mbox*"
});
done_testing;
diff --git a/t/lei_to_mail.t b/t/lei_to_mail.t
index a25795ca..77e9902e 100644
--- a/t/lei_to_mail.t
+++ b/t/lei_to_mail.t
@@ -10,6 +10,7 @@ use Fcntl qw(SEEK_SET);
use PublicInbox::Spawn qw(popen_rd which);
use List::Util qw(shuffle);
require_mods(qw(DBD::SQLite));
+require PublicInbox::MdirReader;
require PublicInbox::MboxReader;
require PublicInbox::LeiOverview;
require PublicInbox::LEI;
@@ -127,6 +128,17 @@ my $orig = do {
is(do { local $/; <$fh> }, $raw, 'jobs > 1');
$raw;
};
+
+test_lei(sub {
+ ok(lei(qw(import -f), $mbox, $fn), 'imported mbox');
+ ok(lei(qw(q s:x)), 'lei q works') or diag $lei_err;
+ my $res = json_utf8->decode($lei_out);
+ my $x = $res->[0];
+ is($x->{'s'}, 'x', 'subject imported') or diag $lei_out;
+ is_deeply($x->{'kw'}, ['seen'], 'kw imported') or diag $lei_out;
+ is($res->[1], undef, 'only one result');
+});
+
for my $zsfx (qw(gz bz2 xz)) { # XXX should we support zst, zz, lzo, lzma?
my $zsfx2cmd = PublicInbox::LeiToMail->can('zsfx2cmd');
SKIP: {
@@ -230,6 +242,7 @@ SKIP: { # FIFO support
}
{ # Maildir support
+ my $each_file = PublicInbox::MdirReader->can('maildir_each_file');
my $md = "$tmpdir/maildir/";
my $wcb = $wcb_get->('maildir', $md);
is(ref($wcb), 'CODE', 'got Maildir callback');
@@ -237,7 +250,7 @@ SKIP: { # FIFO support
$wcb->(\(my $x = $buf), $b4dc0ffee);
my @f;
- PublicInbox::LeiToMail::maildir_each_file($md, sub { push @f, shift });
+ $each_file->($md, sub { push @f, shift });
open my $fh, $f[0] or BAIL_OUT $!;
is(do { local $/; <$fh> }, $buf, 'wrote to Maildir');
@@ -246,7 +259,7 @@ SKIP: { # FIFO support
$wcb->(\($x = $buf."\nx\n"), $deadcafe);
my @x = ();
- PublicInbox::LeiToMail::maildir_each_file($md, sub { push @x, shift });
+ $each_file->($md, sub { push @x, shift });
is(scalar(@x), 1, 'wrote one new file');
ok(!-f $f[0], 'old file clobbered');
open $fh, $x[0] or BAIL_OUT $!;
@@ -257,7 +270,7 @@ SKIP: { # FIFO support
$wcb->(\($x = $buf."\ny\n"), $deadcafe);
$wcb->(\($x = $buf."\ny\n"), $b4dc0ffee); # skipped by dedupe
@f = ();
- PublicInbox::LeiToMail::maildir_each_file($md, sub { push @f, shift });
+ $each_file->($md, sub { push @f, shift });
is(scalar grep(/\A\Q$x[0]\E\z/, @f), 1, 'old file still there');
my @new = grep(!/\A\Q$x[0]\E\z/, @f);
is(scalar @new, 1, '1 new file written (b4dc0ffee skipped)');
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 06/11] t/run.perl: fix for >128 tests
2021-02-09 8:09 [PATCH 00/11] Maildir code consolidation, test updates Eric Wong
` (4 preceding siblings ...)
2021-02-09 8:09 ` [PATCH 05/11] lei: split out MdirReader package, lazy-require earlier Eric Wong
@ 2021-02-09 8:09 ` Eric Wong
2021-02-09 8:09 ` [PATCH 07/11] use MdirReader in -watch and InboxWritable Eric Wong
` (4 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Eric Wong @ 2021-02-09 8:09 UTC (permalink / raw)
To: meta
We need to explicitly close the write-end of the pipe in workers
to ensure they don't prevent each other from seeing EOF.
Also, make a note to keep using the pipe for now since
Linux <3.14 had broken read(2) semantics when file descriptions
are shared across threads/processes.
---
t/run.perl | 17 +++++++++--------
1 file changed, 9 insertions(+), 8 deletions(-)
diff --git a/t/run.perl b/t/run.perl
index 96db3045..d0b29e68 100755
--- a/t/run.perl
+++ b/t/run.perl
@@ -127,9 +127,10 @@ my $producer = $$;
my $eof; # we stop respawning if true
my $start_worker = sub {
- my ($i, $j, $rd, $todo) = @_;
+ my ($j, $rd, $wr, $todo) = @_;
my $pid = fork // DIE "fork: $!";
if ($pid == 0) {
+ close $wr if $wr;
$worker = $$;
while (1) {
my $r = sysread($rd, my $buf, UINT_SIZE);
@@ -155,15 +156,16 @@ my $start_worker = sub {
for (my $i = $repeat; $i != 0; $i--) {
my @todo = $shuffle ? List::Util::shuffle(@tests) : @tests;
- # single-producer, multi-consumer queue relying on POSIX semantics
+ # single-producer, multi-consumer queue relying on POSIX pipe semantics
+ # POSIX.1-2008 stipulates a regular file should work, but Linux <3.14
+ # had broken read(2) semantics according to the read(2) manpage
pipe(my ($rd, $wr)) or DIE "pipe: $!";
# fill the queue before forking so children can start earlier
my $n = (_POSIX_PIPE_BUF / UINT_SIZE);
if ($n >= $#todo) {
print $wr join('', map { pack('I', $_) } (0..$#todo)) or DIE;
- close $wr or die;
- $wr = undef;
+ undef $wr;
} else { # write what we can...
$wr->autoflush(1);
print $wr join('', map { pack('I', $_) } (0..$n)) or DIE;
@@ -186,22 +188,21 @@ for (my $i = $repeat; $i != 0; $i--) {
# skip_all can exit(0), respawn if needed:
if (!$eof) {
print $OLDERR "# respawning job[$j]\n";
- $start_worker->($i, $j, $rd, \@todo);
+ $start_worker->($j, $rd, $wr, \@todo);
}
}
};
# start the workers to consume the queue
for (my $j = 0; $j < $jobs; $j++) {
- $start_worker->($i, $j, $rd, \@todo);
+ $start_worker->($j, $rd, $wr, \@todo);
}
-
if ($wr) {
local $SIG{CHLD} = $sigchld;
# too many tests to fit in the pipe before starting workers,
# send the rest now the workers are running
print $wr join('', map { pack('I', $_) } ($n..$#todo)) or DIE;
- close $wr or die;
+ undef $wr;
}
$sigchld->(0) while scalar(keys(%pids));
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 07/11] use MdirReader in -watch and InboxWritable
2021-02-09 8:09 [PATCH 00/11] Maildir code consolidation, test updates Eric Wong
` (5 preceding siblings ...)
2021-02-09 8:09 ` [PATCH 06/11] t/run.perl: fix for >128 tests Eric Wong
@ 2021-02-09 8:09 ` Eric Wong
2021-02-09 8:09 ` [PATCH 08/11] lei q: prefix --alert ops with ':' instead of '-' Eric Wong
` (3 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Eric Wong @ 2021-02-09 8:09 UTC (permalink / raw)
To: meta
MdirReader now handles files in "$MAILDIR/new" properly and
is stricter about what it accepts. eml_from_path is also
made robust against FIFOs while eliminating TOCTOU races with
between stat(2) and open(2) calls.
---
MANIFEST | 1 +
lib/PublicInbox/InboxWritable.pm | 55 +++++++++++++-------------------
lib/PublicInbox/MdirReader.pm | 22 +++++++++++--
lib/PublicInbox/Watch.pm | 6 ++--
t/mdir_reader.t | 22 +++++++++++++
5 files changed, 69 insertions(+), 37 deletions(-)
create mode 100644 t/mdir_reader.t
diff --git a/MANIFEST b/MANIFEST
index 6b3fc812..f8ee6998 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -376,6 +376,7 @@ t/mbox_reader.t
t/mda-mime.eml
t/mda.t
t/mda_filter_rubylang.t
+t/mdir_reader.t
t/mid.t
t/mime.t
t/miscsearch.t
diff --git a/lib/PublicInbox/InboxWritable.pm b/lib/PublicInbox/InboxWritable.pm
index 3a4012cd..c3acc4f9 100644
--- a/lib/PublicInbox/InboxWritable.pm
+++ b/lib/PublicInbox/InboxWritable.pm
@@ -10,6 +10,7 @@ use PublicInbox::Import;
use PublicInbox::Filter::Base qw(REJECT);
use Errno qw(ENOENT);
our @EXPORT_OK = qw(eml_from_path);
+use Fcntl qw(O_RDONLY O_NONBLOCK);
use constant {
PERM_UMASK => 0,
@@ -118,25 +119,10 @@ sub filter {
undef;
}
-sub is_maildir_basename ($) {
- my ($bn) = @_;
- return 0 if $bn !~ /\A[a-zA-Z0-9][\-\w:,=\.]+\z/;
- if ($bn =~ /:2,([A-Z]+)\z/i) {
- my $flags = $1;
- return 0 if $flags =~ /[DT]/; # no [D]rafts or [T]rashed mail
- }
- 1;
-}
-
-sub is_maildir_path ($) {
- my ($path) = @_;
- my @p = split(m!/+!, $path);
- (is_maildir_basename($p[-1]) && -f $path) ? 1 : 0;
-}
-
sub eml_from_path ($) {
my ($path) = @_;
- if (open my $fh, '<', $path) {
+ if (sysopen(my $fh, $path, O_RDONLY|O_NONBLOCK)) {
+ return unless -f $fh; # no FIFOs or directories
my $str = do { local $/; <$fh> } or return;
PublicInbox::Eml->new(\$str);
} else { # ENOENT is common with Maildir
@@ -145,27 +131,30 @@ sub eml_from_path ($) {
}
}
+sub _each_maildir_fn {
+ my ($fn, $im, $self) = @_;
+ if ($fn =~ /:2,([A-Za-z]*)\z/) {
+ my $fl = $1;
+ return if $fl =~ /[DT]/; # no Drafts or Trash for public
+ }
+ my $eml = eml_from_path($fn) or return;
+ if ($self && (my $filter = $self->filter($im))) {
+ my $ret = $filter->scrub($eml) or return;
+ return if $ret == REJECT();
+ $eml = $ret;
+ }
+ $im->add($eml);
+}
+
sub import_maildir {
my ($self, $dir) = @_;
- my $im = $self->importer(1);
-
foreach my $sub (qw(cur new tmp)) {
-d "$dir/$sub" or die "$dir is not a Maildir (missing $sub)\n";
}
- foreach my $sub (qw(cur new)) {
- opendir my $dh, "$dir/$sub" or die "opendir $dir/$sub: $!\n";
- while (defined(my $fn = readdir($dh))) {
- next unless is_maildir_basename($fn);
- my $mime = eml_from_path("$dir/$fn") or next;
-
- if (my $filter = $self->filter($im)) {
- my $ret = $filter->scrub($mime) or return;
- return if $ret == REJECT();
- $mime = $ret;
- }
- $im->add($mime);
- }
- }
+ my $im = $self->importer(1);
+ my @self = $self->filter($im) ? ($self) : ();
+ PublicInbox::MdirReader::maildir_each_file(\&_each_maildir_fn,
+ $im, @self);
$im->done;
}
diff --git a/lib/PublicInbox/MdirReader.pm b/lib/PublicInbox/MdirReader.pm
index c6a0e7a8..e0ff676d 100644
--- a/lib/PublicInbox/MdirReader.pm
+++ b/lib/PublicInbox/MdirReader.pm
@@ -2,18 +2,36 @@
# License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt>
# Maildirs for now, MH eventually
+# ref: https://cr.yp.to/proto/maildir.html
+# https://wiki2.dovecot.org/MailboxFormat/Maildir
package PublicInbox::MdirReader;
use strict;
use v5.10.1;
+# returns Maildir flags from a basename ('' for no flags, undef for invalid)
+sub maildir_basename_flags {
+ my (@f) = split(/:/, $_[0], -1);
+ return if (scalar(@f) > 2 || substr($f[0], 0, 1) eq '.');
+ $f[1] // return ''; # "new"
+ $f[1] =~ /\A2,([A-Za-z]*)\z/ ? $1 : undef; # "cur"
+}
+
+# same as above, but for full path name
+sub maildir_path_flags {
+ my ($f) = @_;
+ my $i = rindex($f, '/');
+ $i >= 0 ? maildir_basename_flags(substr($f, $i + 1)) : undef;
+}
+
sub maildir_each_file ($$;@) {
my ($dir, $cb, @arg) = @_;
$dir .= '/' unless substr($dir, -1) eq '/';
for my $d (qw(new/ cur/)) {
my $pfx = $dir.$d;
opendir my $dh, $pfx or next;
- while (defined(my $fn = readdir($dh))) {
- $cb->($pfx.$fn, @arg) if $fn =~ /:2,[A-Za-z]*\z/;
+ while (defined(my $bn = readdir($dh))) {
+ maildir_basename_flags($bn) // next;
+ $cb->($pfx.$bn, @arg);
}
}
}
diff --git a/lib/PublicInbox/Watch.pm b/lib/PublicInbox/Watch.pm
index 1835fa0e..a4302162 100644
--- a/lib/PublicInbox/Watch.pm
+++ b/lib/PublicInbox/Watch.pm
@@ -2,12 +2,13 @@
# License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt>
#
# ref: https://cr.yp.to/proto/maildir.html
-# http://wiki2.dovecot.org/MailboxFormat/Maildir
+# httsp://wiki2.dovecot.org/MailboxFormat/Maildir
package PublicInbox::Watch;
use strict;
use v5.10.1;
use PublicInbox::Eml;
use PublicInbox::InboxWritable qw(eml_from_path);
+use PublicInbox::MdirReader;
use PublicInbox::Filter::Base qw(REJECT);
use PublicInbox::Spamcheck;
use PublicInbox::Sigfd;
@@ -207,7 +208,8 @@ sub import_eml ($$$) {
sub _try_path {
my ($self, $path) = @_;
- return unless PublicInbox::InboxWritable::is_maildir_path($path);
+ my $fl = PublicInbox::MdirReader::maildir_path_flags($path) // return;
+ return if $fl =~ /[DT]/; # no Drafts or Trash
if ($path !~ $self->{mdre}) {
warn "unrecognized path: $path\n";
return;
diff --git a/t/mdir_reader.t b/t/mdir_reader.t
new file mode 100644
index 00000000..51b38af4
--- /dev/null
+++ b/t/mdir_reader.t
@@ -0,0 +1,22 @@
+#!perl -w
+# Copyright (C) 2021 all contributors <meta@public-inbox.org>
+# License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt>
+use PublicInbox::TestCommon;
+require_ok 'PublicInbox::MdirReader';
+*maildir_basename_flags = \&PublicInbox::MdirReader::maildir_basename_flags;
+*maildir_path_flags = \&PublicInbox::MdirReader::maildir_path_flags;
+
+is(maildir_basename_flags('foo'), '', 'new valid name accepted');
+is(maildir_basename_flags('foo:2,'), '', 'cur valid name accepted');
+is(maildir_basename_flags('foo:2,bar'), 'bar', 'flags name accepted');
+is(maildir_basename_flags('.foo:2,bar'), undef, 'no hidden files');
+is(maildir_basename_flags('fo:o:2,bar'), undef, 'no extra colon');
+is(maildir_path_flags('/path/to/foo:2,S'), 'S', 'flag returned for path');
+is(maildir_path_flags('/path/to/.foo:2,S'), undef, 'no hidden paths');
+is(maildir_path_flags('/path/to/foo:2,'), '', 'no flags in path');
+
+# not sure if there's a better place for eml_from_path
+use_ok 'PublicInbox::InboxWritable', qw(eml_from_path);
+is(eml_from_path('.'), undef, 'eml_from_path fails on directory');
+
+done_testing;
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 08/11] lei q: prefix --alert ops with ':' instead of '-'
2021-02-09 8:09 [PATCH 00/11] Maildir code consolidation, test updates Eric Wong
` (6 preceding siblings ...)
2021-02-09 8:09 ` [PATCH 07/11] use MdirReader in -watch and InboxWritable Eric Wong
@ 2021-02-09 8:09 ` Eric Wong
2021-02-09 8:09 ` [PATCH 09/11] t/run.perl: drop Cwd dependency Eric Wong
` (2 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Eric Wong @ 2021-02-09 8:09 UTC (permalink / raw)
To: meta
Using dashed keywords confuses the option parser without
"=" signs (and bash completion doesn't yet work with "=").
So use ":" instead of "-" as the prefix for internal ops,
since ":" is just as unlikely to be the first character of
an executable file in a user's $PATH.
---
lib/PublicInbox/LEI.pm | 8 ++++----
lib/PublicInbox/LeiOverview.pm | 2 +-
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/lib/PublicInbox/LEI.pm b/lib/PublicInbox/LEI.pm
index e2a945a4..e29b13c3 100644
--- a/lib/PublicInbox/LEI.pm
+++ b/lib/PublicInbox/LEI.pm
@@ -227,9 +227,9 @@ my %OPTDESC = (
'show threads|t' => 'display entire thread a message belongs to',
'q threads|t' =>
'return all messages in the same threads as the actual match(es)',
-'alert=s@' => ['CMD,-WINCH,-bell,<any command>',
+'alert=s@' => ['CMD,:WINCH,:bell,<any command>',
'run command(s) or perform ops when done writing to output ' .
- '(default: "-WINCH,-bell" with --mua and Maildir/IMAP output, ' .
+ '(default: ":WINCH,:bell" with --mua and Maildir/IMAP output, ' .
'nothing otherwise)' ],
'augment|a' => 'augment --output destination instead of clobbering',
@@ -758,14 +758,14 @@ sub poke_mua { # forces terminal MUAs to wake up and hopefully notice new mail
my ($self) = @_;
my $alerts = $self->{opt}->{alert} // return;
while (my $op = shift(@$alerts)) {
- if ($op eq '-WINCH') {
+ if ($op eq ':WINCH') {
# hit the process group that started the MUA
if ($self->{sock}) {
send($self->{sock}, '-WINCH', MSG_EOR);
} elsif ($self->{oneshot}) {
kill('-WINCH', $$);
}
- } elsif ($op eq '-bell') {
+ } elsif ($op eq ':bell') {
out($self, "\a");
} elsif ($op =~ /(?<!\\),/) { # bare ',' (not ',,')
push @$alerts, split(/(?<!\\),/, $op);
diff --git a/lib/PublicInbox/LeiOverview.pm b/lib/PublicInbox/LeiOverview.pm
index 98c89d12..c820f0d7 100644
--- a/lib/PublicInbox/LeiOverview.pm
+++ b/lib/PublicInbox/LeiOverview.pm
@@ -100,7 +100,7 @@ sub new {
return $lei->fail($@) if $@;
if ($opt->{mua} && $lei->{l2m}->lock_free) {
$lei->{early_mua} = 1;
- $opt->{alert} //= [ '-WINCH,-bell' ] if -t $lei->{1};
+ $opt->{alert} //= [ ':WINCH,:bell' ] if -t $lei->{1};
}
}
$self;
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 09/11] t/run.perl: drop Cwd dependency
2021-02-09 8:09 [PATCH 00/11] Maildir code consolidation, test updates Eric Wong
` (7 preceding siblings ...)
2021-02-09 8:09 ` [PATCH 08/11] lei q: prefix --alert ops with ':' instead of '-' Eric Wong
@ 2021-02-09 8:09 ` Eric Wong
2021-02-09 8:09 ` [PATCH 10/11] lei: replace "I:"-prefixed info messages with "#" Eric Wong
2021-02-09 8:09 ` [PATCH 11/11] tests|lei: fixes for TEST_RUN_MODE=0 and lei oneshot Eric Wong
10 siblings, 0 replies; 12+ messages in thread
From: Eric Wong @ 2021-02-09 8:09 UTC (permalink / raw)
To: meta
Perl 5.8.8/5.10.0+ can use fchdir(), and we depend on 5.10.1+
---
t/run.perl | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/t/run.perl b/t/run.perl
index d0b29e68..e8512e18 100755
--- a/t/run.perl
+++ b/t/run.perl
@@ -14,7 +14,6 @@ use strict;
use v5.10.1;
use IO::Handle; # ->autoflush
use PublicInbox::TestCommon;
-use Cwd qw(getcwd);
use Getopt::Long qw(:config gnu_getopt no_ignore_case auto_abbrev);
use Errno qw(EINTR);
use Fcntl qw(:seek);
@@ -33,7 +32,7 @@ if (($ENV{TEST_RUN_MODE} // 2) == 0) {
die "$0 is not compatible with TEST_RUN_MODE=0\n";
}
my @tests = scalar(@ARGV) ? @ARGV : glob('t/*.t');
-my $cwd = getcwd();
+open my $cwd_fh, '<', '.' or die "open .: $!";
open my $OLDOUT, '>&STDOUT' or die "dup STDOUT: $!";
open my $OLDERR, '>&STDERR' or die "dup STDERR: $!";
$OLDOUT->autoflush(1);
@@ -64,7 +63,7 @@ our ($worker, $worker_test);
sub test_status () {
$? = 255 if $? == 0 && !$tb->is_passing;
my $status = $? ? 'not ok' : 'ok';
- chdir($cwd) or DIE "chdir($cwd): $!";
+ chdir($cwd_fh) or DIE "fchdir: $!";
if ($log_suffix ne '') {
my $log = $worker_test;
$log =~ s/\.t\z/$log_suffix/;
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 10/11] lei: replace "I:"-prefixed info messages with "#"
2021-02-09 8:09 [PATCH 00/11] Maildir code consolidation, test updates Eric Wong
` (8 preceding siblings ...)
2021-02-09 8:09 ` [PATCH 09/11] t/run.perl: drop Cwd dependency Eric Wong
@ 2021-02-09 8:09 ` Eric Wong
2021-02-09 8:09 ` [PATCH 11/11] tests|lei: fixes for TEST_RUN_MODE=0 and lei oneshot Eric Wong
10 siblings, 0 replies; 12+ messages in thread
From: Eric Wong @ 2021-02-09 8:09 UTC (permalink / raw)
To: meta
The "#" is what TAP <https://testanything.org/> uses,
which is also consistent with what our (and many other)
test suites emit.
---
lib/PublicInbox/LEI.pm | 6 +++---
t/lei.t | 2 +-
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/lib/PublicInbox/LEI.pm b/lib/PublicInbox/LEI.pm
index e29b13c3..5f265087 100644
--- a/lib/PublicInbox/LEI.pm
+++ b/lib/PublicInbox/LEI.pm
@@ -559,7 +559,7 @@ sub _lei_cfg ($;$) {
open my $fh, '>>', $f or die "open($f): $!\n";
@st = stat($fh) or die "fstat($f): $!\n";
$cur_st = pack('dd', $st[10], $st[7]);
- qerr($self, "I: $f created") if $self->{cmd} ne 'config';
+ qerr($self, "# $f created") if $self->{cmd} ne 'config';
}
my $cfg = PublicInbox::Config::git_config_dump($f);
$cfg->{-st} = $cur_st;
@@ -619,7 +619,7 @@ sub lei_init {
my @cur = stat($cur) if defined($cur);
$cur = File::Spec->canonpath($cur // $dir);
my @dir = stat($dir);
- my $exists = "I: leistore.dir=$cur already initialized" if @dir;
+ my $exists = "# leistore.dir=$cur already initialized" if @dir;
if (@cur) {
if ($cur eq $dir) {
_lei_store($self, 1)->done;
@@ -638,7 +638,7 @@ E: leistore.dir=$cur already initialized and it is not $dir
}
lei_config($self, 'leistore.dir', $dir);
_lei_store($self, 1)->done;
- $exists //= "I: leistore.dir=$dir newly initialized";
+ $exists //= "# leistore.dir=$dir newly initialized";
return qerr($self, $exists);
}
diff --git a/t/lei.t b/t/lei.t
index 8e771eb5..4785acca 100644
--- a/t/lei.t
+++ b/t/lei.t
@@ -49,7 +49,7 @@ my $test_help = sub {
my $ok_err_info = sub {
my ($msg) = @_;
- is(grep(!/^I:/, split(/^/, $lei_err)), 0, $msg) or
+ is(grep(!/^#/, split(/^/, $lei_err)), 0, $msg) or
diag "$msg: err=$lei_err";
};
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 11/11] tests|lei: fixes for TEST_RUN_MODE=0 and lei oneshot
2021-02-09 8:09 [PATCH 00/11] Maildir code consolidation, test updates Eric Wong
` (9 preceding siblings ...)
2021-02-09 8:09 ` [PATCH 10/11] lei: replace "I:"-prefixed info messages with "#" Eric Wong
@ 2021-02-09 8:09 ` Eric Wong
10 siblings, 0 replies; 12+ messages in thread
From: Eric Wong @ 2021-02-09 8:09 UTC (permalink / raw)
To: meta
DESTROY callbacks can clobber $?, so we must take care to
preserve it when exiting. We'll also try to make an effort to
ensure better DESTROY ordering and delete as much as possible
before x_it finishes.
We also need to load PublicInbox::Config when setting up
public inboxes.
---
lib/PublicInbox/IPC.pm | 2 ++
lib/PublicInbox/LEI.pm | 7 +++++--
lib/PublicInbox/TestCommon.pm | 3 ++-
t/lei-mirror.t | 2 +-
4 files changed, 10 insertions(+), 4 deletions(-)
diff --git a/lib/PublicInbox/IPC.pm b/lib/PublicInbox/IPC.pm
index 9331233a..efac4c4d 100644
--- a/lib/PublicInbox/IPC.pm
+++ b/lib/PublicInbox/IPC.pm
@@ -412,9 +412,11 @@ sub DESTROY {
my ($self) = @_;
my $ppid = $self->{-wq_ppid};
wq_kill($self) if $ppid && $ppid == $$;
+ my $err = $?;
wq_close($self);
wq_wait_old($self);
ipc_worker_stop($self);
+ $? = $err if $err;
}
sub detect_nproc () {
diff --git a/lib/PublicInbox/LEI.pm b/lib/PublicInbox/LEI.pm
index 5f265087..dd831c54 100644
--- a/lib/PublicInbox/LEI.pm
+++ b/lib/PublicInbox/LEI.pm
@@ -336,8 +336,9 @@ sub x_it ($$) {
my $wq = delete $self->{$f} or next;
$wq->DESTROY;
}
- # cleanup anything that has tempfiles
- delete @$self{qw(ovv dedupe)};
+ # cleanup anything that has tempfiles or open file handles
+ %PATH2CFG = ();
+ delete @$self{qw(ovv dedupe sto cfg)};
if (my $signum = ($code & 127)) { # usually SIGPIPE (13)
$SIG{PIPE} = 'DEFAULT'; # $SIG{$signum} doesn't work
kill $signum, $$;
@@ -1072,8 +1073,10 @@ sub DESTROY {
my ($self) = @_;
$self->{1}->autoflush(1) if $self->{1};
stop_pager($self);
+ my $err = $?;
my $oneshot_pids = delete $self->{"pid.$self.$$"} or return;
waitpid($_, 0) for keys %$oneshot_pids;
+ $? = $err if $err; # preserve ->fail or ->x_it code
}
1;
diff --git a/lib/PublicInbox/TestCommon.pm b/lib/PublicInbox/TestCommon.pm
index 53f13437..63d45ac3 100644
--- a/lib/PublicInbox/TestCommon.pm
+++ b/lib/PublicInbox/TestCommon.pm
@@ -541,7 +541,6 @@ sub setup_public_inboxes () {
my $end = $lk->lock_for_scope;
return @ret if -f $stamp;
- require PublicInbox::InboxWritable;
local $ENV{PI_CONFIG} = $pi_config;
for my $V (1, 2) {
run_script([qw(-init), "-V$V", "t$V",
@@ -549,6 +548,8 @@ sub setup_public_inboxes () {
"$test_home/t$V", "http://example.com/t$V",
"t$V\@example.com" ]) or BAIL_OUT "init v$V";
}
+ require PublicInbox::Config;
+ require PublicInbox::InboxWritable;
my $cfg = PublicInbox::Config->new;
my $seen = 0;
$cfg->each_inbox(sub {
diff --git a/t/lei-mirror.t b/t/lei-mirror.t
index e3707979..cbe300da 100644
--- a/t/lei-mirror.t
+++ b/t/lei-mirror.t
@@ -27,7 +27,7 @@ test_lei({ tmpdir => $tmpdir }, sub {
like($lei_out, qr!\Q$t2\E!, 't2 added to ls-externals');
ok(!$lei->('add-external', $t2, '--mirror', "$http/t2/"),
- '--mirror fails if reused');
+ '--mirror fails if reused') or diag "$lei_err.$lei_out = $?";
ok($lei->('ls-external'), 'ls-external');
like($lei_out, qr!\Q$t2\E!, 'still in ls-externals');
^ permalink raw reply related [flat|nested] 12+ messages in thread
end of thread, other threads:[~2021-02-09 8:09 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2021-02-09 8:09 [PATCH 00/11] Maildir code consolidation, test updates Eric Wong
2021-02-09 8:09 ` [PATCH 01/11] t/thread-index-gap.t: avoid unnecessary map Eric Wong
2021-02-09 8:09 ` [PATCH 02/11] test_common: disable fsync on the CLI where possible Eric Wong
2021-02-09 8:09 ` [PATCH 03/11] t/cgi.t: modernizations and style updates Eric Wong
2021-02-09 8:09 ` [PATCH 04/11] git: ->qx: respect caller's $/ in array context Eric Wong
2021-02-09 8:09 ` [PATCH 05/11] lei: split out MdirReader package, lazy-require earlier Eric Wong
2021-02-09 8:09 ` [PATCH 06/11] t/run.perl: fix for >128 tests Eric Wong
2021-02-09 8:09 ` [PATCH 07/11] use MdirReader in -watch and InboxWritable Eric Wong
2021-02-09 8:09 ` [PATCH 08/11] lei q: prefix --alert ops with ':' instead of '-' Eric Wong
2021-02-09 8:09 ` [PATCH 09/11] t/run.perl: drop Cwd dependency Eric Wong
2021-02-09 8:09 ` [PATCH 10/11] lei: replace "I:"-prefixed info messages with "#" Eric Wong
2021-02-09 8:09 ` [PATCH 11/11] tests|lei: fixes for TEST_RUN_MODE=0 and lei oneshot Eric Wong
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).