* [PATCH 00/14] Alpine Linux support
@ 2023-12-13 0:50 Eric Wong
2023-12-13 0:50 ` [PATCH 01/14] t/io: strace is optional on Linux Eric Wong
` (13 more replies)
0 siblings, 14 replies; 15+ messages in thread
From: Eric Wong @ 2023-12-13 0:50 UTC (permalink / raw)
To: meta
I haven't tested every single possible package combination, but
I think this is enough to get started.
Patch 3 was a WTF moment for me.
Some of these are relevant for other platforms, as well, and
patch 7 decoupling from Inline::C is a good step towards making
our codebase more modular.
Patch 12 is a good fix regardless.
Eric Wong (14):
t/io: strace is optional on Linux
tests: account for missing git-http-backend
t/cindex*: skip --join when join(1) is missing
tests: attempt compatibility w/ busybox lsof
lei inspect: drop unneeded strftime import
treewide: avoid strftime %k for portability
xap_helper_cxx: decouple from Inline::C
xap_helper_cxx: support clang w/o `c++' executable
install: updates for Alpine Linux and apk
test_common: extract oct_is from search.t
t/convert-compact: allow S_ISGID bit
www_coderepo: fix read buffering
gzip_filter: use OO ->zflush dispatch
t/lei-import: relax EIO regexp
install/deps.perl | 38 +++++++++++++++++++++----
install/os.perl | 12 ++++++--
lib/PublicInbox/Admin.pm | 10 ++++++-
lib/PublicInbox/ExtSearchIdx.pm | 4 +--
lib/PublicInbox/GzipFilter.pm | 2 +-
lib/PublicInbox/Hval.pm | 6 +++-
lib/PublicInbox/LeiInspect.pm | 1 -
lib/PublicInbox/LeiMirror.pm | 4 +--
lib/PublicInbox/LeiXSearch.pm | 3 +-
lib/PublicInbox/RepoAtom.pm | 4 +--
lib/PublicInbox/TestCommon.pm | 50 +++++++++++++++++++++++++++++++--
lib/PublicInbox/WwwCoderepo.pm | 6 ++--
lib/PublicInbox/WwwStatic.pm | 5 ++--
lib/PublicInbox/XapHelperCxx.pm | 26 +++++++++++------
t/cindex-join.t | 1 +
t/cindex.t | 11 ++++----
t/clone-coderepo.t | 1 +
t/convert-compact.t | 20 ++++++-------
t/ds-leak.t | 5 +---
t/httpd-corner.t | 31 ++++++++------------
t/httpd.t | 1 +
t/lei-import.t | 5 ++--
t/lei-mirror.t | 1 +
t/nntpd.t | 16 +++++------
t/search.t | 5 ----
t/solver_git.t | 8 ++++--
t/v2reindex.t | 5 ++--
t/www_listing.t | 1 +
t/xap_helper.t | 6 ++--
xt/msgtime_cmp.t | 2 +-
30 files changed, 190 insertions(+), 100 deletions(-)
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 01/14] t/io: strace is optional on Linux
2023-12-13 0:50 [PATCH 00/14] Alpine Linux support Eric Wong
@ 2023-12-13 0:50 ` Eric Wong
2023-12-13 0:50 ` [PATCH 02/14] tests: account for missing git-http-backend Eric Wong
` (12 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Eric Wong @ 2023-12-13 0:50 UTC (permalink / raw)
To: meta
There are many Linux (GNU or otherwise) which do not have
strace(1) installed.
---
lib/PublicInbox/TestCommon.pm | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/PublicInbox/TestCommon.pm b/lib/PublicInbox/TestCommon.pm
index 5f123eb4..d587bf10 100644
--- a/lib/PublicInbox/TestCommon.pm
+++ b/lib/PublicInbox/TestCommon.pm
@@ -978,7 +978,7 @@ sub strace (@) {
chomp $ps;
skip "strace unusable on daemons\n$f is `$ps' (!= 0)" if $ps;
}
- require_cmd('strace', 1);
+ require_cmd('strace', 1) or skip 'strace not available', 1;
}
sub strace_inject (;$) {
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 02/14] tests: account for missing git-http-backend
2023-12-13 0:50 [PATCH 00/14] Alpine Linux support Eric Wong
2023-12-13 0:50 ` [PATCH 01/14] t/io: strace is optional on Linux Eric Wong
@ 2023-12-13 0:50 ` Eric Wong
2023-12-13 0:50 ` [PATCH 03/14] t/cindex*: skip --join when join(1) is missing Eric Wong
` (11 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Eric Wong @ 2023-12-13 0:50 UTC (permalink / raw)
To: meta
Alpine Linux ships git-http-backend in the `git-daemon'
package separately from `git', so we must test for its
existence before attempting to test functionality which
depends on it.
---
lib/PublicInbox/TestCommon.pm | 19 ++++++++++++++++++-
t/clone-coderepo.t | 1 +
t/httpd.t | 1 +
t/lei-mirror.t | 1 +
t/www_listing.t | 1 +
5 files changed, 22 insertions(+), 1 deletion(-)
diff --git a/lib/PublicInbox/TestCommon.pm b/lib/PublicInbox/TestCommon.pm
index d587bf10..27a758e4 100644
--- a/lib/PublicInbox/TestCommon.pm
+++ b/lib/PublicInbox/TestCommon.pm
@@ -25,7 +25,7 @@ BEGIN {
run_script start_script key2sub xsys xsys_e xqx eml_load tick
have_xapian_compact json_utf8 setup_public_inboxes create_inbox
create_coderepo require_bsd kernel_version check_broken_tmpfs
- quit_waiter_pipe wait_for_eof
+ quit_waiter_pipe wait_for_eof require_git_http_backend
tcp_host_port test_lei lei lei_ok $lei_out $lei_err $lei_opt
test_httpd xbail require_cmd is_xdeeply tail_f
ignore_inline_c_missing no_pollerfd no_coredump cfg_new
@@ -163,6 +163,23 @@ sub require_git ($;$) {
skip("git $req+ required (have $cur_ver), skipping $nr tests")
}
+sub require_git_http_backend (;$) {
+ my ($nr) = @_;
+ state $ok = do {
+ require PublicInbox::Git;
+ my $git = PublicInbox::Git::check_git_exe() or plan
+ skip_all => 'nothing in public-inbox works w/o git';
+ my $rdr = { 1 => \my $out, 2 => \my $err };
+ xsys([$git, qw(http-backend)], undef, $rdr);
+ $out =~ /^Status:/ism;
+ };
+ if (!$ok) {
+ my $msg = "`git http-backend' not available";
+ defined($nr) ? skip $msg, $nr : plan skip_all => $msg;
+ }
+ $ok;
+}
+
my %IPv6_VERSION = (
'Net::NNTP' => 3.00,
'Mail::IMAPClient' => 3.40,
diff --git a/t/clone-coderepo.t b/t/clone-coderepo.t
index 0e6b4ac7..c0951941 100644
--- a/t/clone-coderepo.t
+++ b/t/clone-coderepo.t
@@ -8,6 +8,7 @@ use File::Temp;
use File::Path qw(remove_tree);
use PublicInbox::SHA qw(sha1_hex);
require_mods(qw(json Plack::Builder HTTP::Date HTTP::Status));
+require_git_http_backend;
require_git '1.8.5';
require_cmd 'curl';
require_ok 'PublicInbox::LeiMirror';
diff --git a/t/httpd.t b/t/httpd.t
index 0421c7ea..c0fbaa22 100644
--- a/t/httpd.t
+++ b/t/httpd.t
@@ -7,6 +7,7 @@ use PublicInbox::TestCommon;
use PublicInbox::Eml;
use Socket qw(IPPROTO_TCP SOL_SOCKET);
require_mods(qw(Plack::Util Plack::Builder HTTP::Date HTTP::Status));
+require_git_http_backend;
# FIXME: too much setup
my ($tmpdir, $for_destroy) = tmpdir();
diff --git a/t/lei-mirror.t b/t/lei-mirror.t
index 37c9751b..76041b73 100644
--- a/t/lei-mirror.t
+++ b/t/lei-mirror.t
@@ -5,6 +5,7 @@ use v5.12; use PublicInbox::TestCommon;
use PublicInbox::Inbox;
require_mods(qw(-httpd lei DBD::SQLite));
require_cmd('curl');
+require_git_http_backend;
use PublicInbox::Spawn qw(which);
require PublicInbox::Msgmap;
my $sock = tcp_server();
diff --git a/t/www_listing.t b/t/www_listing.t
index 709dbd05..0a4c79e8 100644
--- a/t/www_listing.t
+++ b/t/www_listing.t
@@ -77,6 +77,7 @@ sub tiny_test {
my $td;
SKIP: {
+ require_git_http_backend 1;
my $err = "$tmpdir/stderr.log";
my $out = "$tmpdir/stdout.log";
my $alt = "$tmpdir/alt.git";
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 03/14] t/cindex*: skip --join when join(1) is missing
2023-12-13 0:50 [PATCH 00/14] Alpine Linux support Eric Wong
2023-12-13 0:50 ` [PATCH 01/14] t/io: strace is optional on Linux Eric Wong
2023-12-13 0:50 ` [PATCH 02/14] tests: account for missing git-http-backend Eric Wong
@ 2023-12-13 0:50 ` Eric Wong
2023-12-13 0:50 ` [PATCH 04/14] tests: attempt compatibility w/ busybox lsof Eric Wong
` (10 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Eric Wong @ 2023-12-13 0:50 UTC (permalink / raw)
To: meta
While join(1) is POSIX, busybox on Alpine 3.19.0 does not
provide its functionality. So just skip tests for now since
it's too much trouble to provide a workaround for an otherwise
common POSIX command.
---
t/cindex-join.t | 1 +
t/cindex.t | 11 ++++++-----
2 files changed, 7 insertions(+), 5 deletions(-)
diff --git a/t/cindex-join.t b/t/cindex-join.t
index c2e85332..22c67107 100644
--- a/t/cindex-join.t
+++ b/t/cindex-join.t
@@ -11,6 +11,7 @@ use PublicInbox::Config;
use autodie;
use File::Spec;
$ENV{TEST_REMOTE_JOIN} or plan skip_all => 'TEST_REMOTE_JOIN unset';
+require_cmd 'join';
local $ENV{TAIL_ALL} = $ENV{TAIL_ALL} // 1; # while features are unstable
require_mods(qw(json Xapian DBD::SQLite +SCM_RIGHTS));
my @code = qw(https://80x24.org/mwrap-perl.git
diff --git a/t/cindex.t b/t/cindex.t
index 15c860e1..ab4cde7c 100644
--- a/t/cindex.t
+++ b/t/cindex.t
@@ -247,11 +247,12 @@ SKIP: {
ok(run_script([qw(-xcpdb --compact), "$tmp/ext"]), 'xcpdb compact');
};
-my $basic = create_inbox 'basic', indexlevel => 'basic', sub {
- my ($im, $ibx) = @_;
- $im->add(eml_load('t/plack-qp.eml'));
-};
-{
+SKIP: {
+ require_cmd('join', 1);
+ my $basic = create_inbox 'basic', indexlevel => 'basic', sub {
+ my ($im, $ibx) = @_;
+ $im->add(eml_load('t/plack-qp.eml'));
+ };
my $env = { PI_CONFIG => "$tmp/pi_config" };
PublicInbox::IO::write_file '>', $env->{PI_CONFIG}, <<EOM;
[publicinbox "basictest"]
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 04/14] tests: attempt compatibility w/ busybox lsof
2023-12-13 0:50 [PATCH 00/14] Alpine Linux support Eric Wong
` (2 preceding siblings ...)
2023-12-13 0:50 ` [PATCH 03/14] t/cindex*: skip --join when join(1) is missing Eric Wong
@ 2023-12-13 0:50 ` Eric Wong
2023-12-13 0:50 ` [PATCH 05/14] lei inspect: drop unneeded strftime import Eric Wong
` (9 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Eric Wong @ 2023-12-13 0:50 UTC (permalink / raw)
To: meta
BusyBox lsof(1) ignores the `-p PID' argument and shows
the open files for every process it knows about. BusyBox
lsof also lacks the `NODE' column of the non-BusyBox
implementation, so we'll rely on /proc/PID/fd/ in those
cases since the deleted file checks are Linux-only and
it's common to have procfs is mounted on /proc on Linux.
---
lib/PublicInbox/TestCommon.pm | 23 ++++++++++++++++++++++-
t/ds-leak.t | 5 +----
t/httpd-corner.t | 31 +++++++++++--------------------
t/nntpd.t | 16 +++++++---------
t/v2reindex.t | 5 ++---
5 files changed, 43 insertions(+), 37 deletions(-)
diff --git a/lib/PublicInbox/TestCommon.pm b/lib/PublicInbox/TestCommon.pm
index 27a758e4..9c413f43 100644
--- a/lib/PublicInbox/TestCommon.pm
+++ b/lib/PublicInbox/TestCommon.pm
@@ -29,7 +29,7 @@ BEGIN {
tcp_host_port test_lei lei lei_ok $lei_out $lei_err $lei_opt
test_httpd xbail require_cmd is_xdeeply tail_f
ignore_inline_c_missing no_pollerfd no_coredump cfg_new
- strace strace_inject);
+ strace strace_inject lsof_pid);
require Test::More;
my @methods = grep(!/\W/, @Test::More::EXPORT);
eval(join('', map { "*$_=\\&Test::More::$_;" } @methods));
@@ -951,6 +951,26 @@ sub test_httpd ($$;$$) {
}
};
+# TODO: support fstat(1) on OpenBSD, lsof already works on FreeBSD + Linux
+# don't use this for deleted file checks, we only check that on Linux atm
+# and we can readlink /proc/PID/fd/* directly
+sub lsof_pid ($;$) {
+ my ($pid, $rdr) = @_;
+ state $lsof = require_cmd('lsof', 1);
+ $lsof or skip 'lsof missing/broken', 1;
+ my @out = xqx([$lsof, '-p', $pid], undef, $rdr);
+ if ($?) {
+ undef $lsof;
+ skip "lsof -p PID broken \$?=$?", 1;
+ }
+ my @cols = split ' ', $out[0];
+ if (($cols[7] // '') eq 'NODE') { # normal lsof
+ @out;
+ } else { # busybox lsof ignores -p, so we DIY it
+ grep /\b$pid\b/, @out;
+ }
+}
+
sub no_pollerfd ($) {
my ($pid) = @_;
my ($re, @cmd);
@@ -966,6 +986,7 @@ sub no_pollerfd ($) {
my @of = xqx(\@cmd, {}, {2 => \(my $e)});
my $err = $?;
skip "$bin broken? (\$?=$err) ($e)", 1 if $err;
+ @of = grep /\b$pid\b/, @of; # busybox lsof ignores -p
is(grep(/$re/, @of), 0, "no $re FDs") or diag explain(\@of);
}
}
diff --git a/t/ds-leak.t b/t/ds-leak.t
index 179997eb..f39985e0 100644
--- a/t/ds-leak.t
+++ b/t/ds-leak.t
@@ -29,11 +29,8 @@ if ('close-on-exec for epoll and kqueue') {
is($l, undef, 'cloexec works and sleep(1) is running');
SKIP: {
- my $lsof = require_cmd('lsof', 1) or skip 'lsof missing', 1;
my $rdr = { 2 => \(my $null) };
- my @of = grep(/$evfd_re/, xqx([$lsof, '-p', $pid], {}, $rdr));
- my $err = $?;
- skip "lsof broken ? (\$?=$err)", 1 if $err;
+ my @of = grep /$evfd_re/, lsof_pid $pid, $rdr;
is_deeply(\@of, [], 'no FDs leaked to subprocess');
};
if (defined $pid) {
diff --git a/t/httpd-corner.t b/t/httpd-corner.t
index da1c24b9..35c88600 100644
--- a/t/httpd-corner.t
+++ b/t/httpd-corner.t
@@ -639,30 +639,21 @@ SKIP: {
};
SKIP: {
- skip 'only testing lsof(8) output on Linux', 1 if $^O ne 'linux';
- my $lsof = require_cmd('lsof', 1) or skip 'no lsof in PATH', 1;
- my $null_in = '';
- my $rdr = { 2 => \(my $null_err), 0 => \$null_in };
- my @lsof = xqx([$lsof, '-p', $td->{pid}], undef, $rdr);
- my $d = [ grep(/\(deleted\)/, @lsof) ];
- is_deeply($d, [], 'no lingering deleted inputs') or diag explain($d);
+ skip 'only testing /proc/PID/fd on Linux', 1 if $^O ne 'linux';
+ my $fd_dir = "/proc/$td->{pid}/fd";
+ -d $fd_dir or skip '/proc/$PID/fd missing', 1;
+ my @child = grep defined, map readlink, glob "$fd_dir/*";
+ my @d = grep /\(deleted\)/, @child;
+ is_deeply(\@d, [], 'no lingering deleted inputs') or diag explain(\@d);
# filter out pipes inherited from the parent
- my @this = xqx([$lsof, '-p', $$], undef, $rdr);
- my $bad;
- my $extract_inodes = sub {
- map {;
- my @f = split(' ', $_);
- my $inode = $f[-2];
- $bad = $_ if $inode !~ /\A[0-9]+\z/;
- $inode => 1;
- } grep (/\bpipe\b/, @_);
- };
- my %child = $extract_inodes->(@lsof);
+ my @this = grep defined, map readlink, glob "/proc/$$/fd/*";
+ my $extract_inodes = sub { map { $_ => 1 } grep /\bpipe\b/, @_ };
+ my %child = $extract_inodes->(@child);
my %parent = $extract_inodes->(@this);
- skip("inode not in expected format: $bad", 1) if defined($bad);
delete @child{(keys %parent)};
- is_deeply([], [keys %child], 'no extra pipes with -W0');
+ is_deeply([], [keys %child], 'no extra pipes with -W0') or
+ diag explain([child => \%child, parent => \%parent]);
};
# ensure compatibility with other PSGI servers
diff --git a/t/nntpd.t b/t/nntpd.t
index ffe0fd8c..0f3ef596 100644
--- a/t/nntpd.t
+++ b/t/nntpd.t
@@ -14,7 +14,6 @@ use PublicInbox::DS;
my $version = $ENV{PI_TEST_VERSION} || 1;
require_git('2.6') if $version == 2;
use_ok 'PublicInbox::Msgmap';
-my $lsof = require_cmd('lsof', 1);
my $fast_idle = eval { require Linux::Inotify2; 1 } //
eval { require IO::KQueue; 1 };
@@ -332,9 +331,7 @@ Date: Fri, 02 Oct 1993 00:00:00 +0000
($ENV{TEST_RUN_MODE} // 2)) {
skip 'Xapian.pm pre-loaded (by xt/check-run.t?)', 1;
}
- $lsof or skip 'lsof missing', 1;
- my @of = xqx([$lsof, '-p', $td->{pid}], undef, $noerr);
- skip('lsof broken', 1) if (!scalar(@of) || $?);
+ my @of = lsof_pid $td->{pid}, $noerr;
my @xap = grep m!\bXapian\b!, @of;
is_deeply(\@xap, [], 'Xapian not loaded in nntpd') or
diag explain(\@of);
@@ -364,12 +361,13 @@ Date: Fri, 02 Oct 1993 00:00:00 +0000
tick($fast_idle ? 0.1 : 2.1);
$art = $n->article($ex->header('Message-ID'));
ok($art, 'new article retrieved after compact');
- $lsof or skip 'lsof missing', 1;
- ($^O =~ /\A(?:linux)\z/) or
+ $^O eq 'linux' or
skip "lsof /(deleted)/ check untested on $^O", 1;
- my @lsof = xqx([$lsof, '-p', $td->{pid}], undef, $noerr);
- my $d = [ grep(/\(deleted\)/, grep(!/batch-command\.err/, @lsof)) ];
- is_deeply($d, [], 'no deleted files') or diag explain($d);
+ my $fd = "/proc/$td->{pid}/fd";
+ -d $fd or skip '/proc/PID/fd missing', 1;
+ my @of = map readlink, glob "$fd/*";
+ my @d = grep /\(deleted\)/, grep !/batch-command\.err/, @of;
+ is_deeply(\@d, [], 'no deleted files') or diag explain(\@d);
};
SKIP: { test_watch($tmpdir, $host_port, $group) };
{
diff --git a/t/v2reindex.t b/t/v2reindex.t
index 406c0517..8c49e154 100644
--- a/t/v2reindex.t
+++ b/t/v2reindex.t
@@ -1,4 +1,4 @@
-# Copyright (C) 2018-2021 all contributors <meta@public-inbox.org>
+# Copyright (C) all contributors <meta@public-inbox.org>
# License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt>
use strict; use v5.10.1; use PublicInbox::TestCommon;
use PublicInbox::Eml;
@@ -549,9 +549,8 @@ is($err, '', 'no errors from --xapian-only');
undef $for_destroy;
SKIP: {
skip 'only testing lsof(8) output on Linux', 1 if $^O ne 'linux';
- my $lsof = require_cmd('lsof', 1) or skip 'no lsof in PATH', 1;
my $rdr = { 2 => \(my $null_err) };
- my @d = grep(m!/xap[0-9]+/!, xqx([$lsof, '-p', $$], undef, $rdr));
+ my @d = grep m!/xap[0-9]+/!, lsof_pid $$, $rdr;
is_deeply(\@d, [], 'no deleted index files') or diag explain(\@d);
}
done_testing();
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 05/14] lei inspect: drop unneeded strftime import
2023-12-13 0:50 [PATCH 00/14] Alpine Linux support Eric Wong
` (3 preceding siblings ...)
2023-12-13 0:50 ` [PATCH 04/14] tests: attempt compatibility w/ busybox lsof Eric Wong
@ 2023-12-13 0:50 ` Eric Wong
2023-12-13 0:50 ` [PATCH 06/14] treewide: avoid strftime %k for portability Eric Wong
` (8 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Eric Wong @ 2023-12-13 0:50 UTC (permalink / raw)
To: meta
`lei inspect' uses the `iso8601' sub from LeiOverview.
---
lib/PublicInbox/LeiInspect.pm | 1 -
1 file changed, 1 deletion(-)
diff --git a/lib/PublicInbox/LeiInspect.pm b/lib/PublicInbox/LeiInspect.pm
index 88d7949c..576ab2c7 100644
--- a/lib/PublicInbox/LeiInspect.pm
+++ b/lib/PublicInbox/LeiInspect.pm
@@ -12,7 +12,6 @@ use parent qw(PublicInbox::IPC);
use PublicInbox::Config;
use PublicInbox::MID qw(mids);
use PublicInbox::NetReader qw(imap_uri nntp_uri);
-use POSIX qw(strftime);
use PublicInbox::LeiOverview;
*iso8601 = \&PublicInbox::LeiOverview::iso8601;
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 06/14] treewide: avoid strftime %k for portability
2023-12-13 0:50 [PATCH 00/14] Alpine Linux support Eric Wong
` (4 preceding siblings ...)
2023-12-13 0:50 ` [PATCH 05/14] lei inspect: drop unneeded strftime import Eric Wong
@ 2023-12-13 0:50 ` Eric Wong
2023-12-13 0:50 ` [PATCH 07/14] xap_helper_cxx: decouple from Inline::C Eric Wong
` (7 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Eric Wong @ 2023-12-13 0:50 UTC (permalink / raw)
To: meta
The musl strftime(3) implementation on AlpineLinux 3.19.0
doesn't support `%k' and `%k' isn't in POSIX, either. So we
fall back to using the `sprintf' perlop in the user-facing UI
since leading zeroes require needless overhead for my eyes and
brain to parse in the time.
---
lib/PublicInbox/Admin.pm | 10 +++++++++-
lib/PublicInbox/ExtSearchIdx.pm | 4 ++--
lib/PublicInbox/Hval.pm | 6 +++++-
lib/PublicInbox/LeiMirror.pm | 4 ++--
lib/PublicInbox/LeiXSearch.pm | 3 ++-
lib/PublicInbox/WwwStatic.pm | 5 ++---
xt/msgtime_cmp.t | 2 +-
7 files changed, 23 insertions(+), 11 deletions(-)
diff --git a/lib/PublicInbox/Admin.pm b/lib/PublicInbox/Admin.pm
index cc9d2171..a1b1fc07 100644
--- a/lib/PublicInbox/Admin.pm
+++ b/lib/PublicInbox/Admin.pm
@@ -6,7 +6,7 @@
package PublicInbox::Admin;
use v5.12;
use parent qw(Exporter);
-our @EXPORT_OK = qw(setup_signals);
+our @EXPORT_OK = qw(setup_signals fmt_localtime);
use PublicInbox::Config;
use PublicInbox::Inbox;
use PublicInbox::Spawn qw(run_qx);
@@ -381,4 +381,12 @@ sub do_chdir ($) {
}
}
+sub fmt_localtime ($) {
+ require POSIX;
+ my @lt = localtime $_[0];
+ my (undef, $M, $H, $d, $m, $Y) = @lt;
+ sprintf('%u-%02u-%02u % 2u:%02u ', $Y + 1900, $m + 1, $d, $H, $M)
+ .POSIX::strftime('%z', @lt);
+}
+
1;
diff --git a/lib/PublicInbox/ExtSearchIdx.pm b/lib/PublicInbox/ExtSearchIdx.pm
index 7b7436ea..53078124 100644
--- a/lib/PublicInbox/ExtSearchIdx.pm
+++ b/lib/PublicInbox/ExtSearchIdx.pm
@@ -20,7 +20,6 @@ use parent qw(PublicInbox::ExtSearch PublicInbox::Umask PublicInbox::Lock);
use Carp qw(croak carp);
use Scalar::Util qw(blessed);
use Sys::Hostname qw(hostname);
-use POSIX qw(strftime);
use File::Glob qw(bsd_glob GLOB_NOSORT);
use PublicInbox::MultiGit;
use PublicInbox::Search;
@@ -34,6 +33,7 @@ use PublicInbox::ContentHash qw(content_hash);
use PublicInbox::Eml;
use PublicInbox::DS qw(now add_timer);
use DBI qw(:sql_types); # SQL_BLOB
+use PublicInbox::Admin qw(fmt_localtime);
sub new {
my (undef, $dir, $opt) = @_;
@@ -749,7 +749,7 @@ sub eidxq_lock_acquire ($) {
return $locked if $locked eq $cur;
}
my ($pid, $time, $euid, $ident) = split(/-/, $cur, 4);
- my $t = strftime('%Y-%m-%d %k:%M %z', localtime($time));
+ my $t = fmt_localtime($time);
local $self->{current_info} = 'eidxq';
if ($euid == $> && $ident eq host_ident) {
kill(0, $pid) and warn <<EOM and return;
diff --git a/lib/PublicInbox/Hval.pm b/lib/PublicInbox/Hval.pm
index b804254a..963dbb71 100644
--- a/lib/PublicInbox/Hval.pm
+++ b/lib/PublicInbox/Hval.pm
@@ -145,7 +145,11 @@ sub to_attr ($) {
sub ts2str ($) { strftime('%Y%m%d%H%M%S', gmtime($_[0])) };
# human-friendly format
-sub fmt_ts ($) { strftime('%Y-%m-%d %k:%M', gmtime($_[0])) }
+sub fmt_ts ($) {
+ # strftime %k is not portable and leading zeros in %H slow me down
+ my (undef, $M, $H, $d, $m, $Y) = gmtime $_[0];
+ sprintf '%u-%02u-%02u % 2u:%02u', $Y + 1900, $m + 1, $d, $H, $M;
+}
sub utf8_maybe ($) {
utf8::decode($_[0]);
diff --git a/lib/PublicInbox/LeiMirror.pm b/lib/PublicInbox/LeiMirror.pm
index e048a807..0c77a8b5 100644
--- a/lib/PublicInbox/LeiMirror.pm
+++ b/lib/PublicInbox/LeiMirror.pm
@@ -21,6 +21,7 @@ use PublicInbox::LeiCurl;
use PublicInbox::OnDestroy;
use PublicInbox::SHA qw(sha256_hex sha_all);
use POSIX qw(strftime);
+use PublicInbox::Admin qw(fmt_localtime);
use autodie qw(chdir chmod close open pipe readlink
seek symlink sysopen sysseek truncate unlink);
@@ -1232,8 +1233,7 @@ EOM
# set by clone_v2_prep/-I/--exclude
my $mis = delete $self->{chg}->{fp_mismatch};
if ($mis) {
- my $t = (stat($ft))[9];
- $t = strftime('%F %k:%M:%S %z', localtime($t));
+ my $t = fmt_localtime((stat($ft))[9]);
warn <<EOM;
W: Fingerprints for the following repositories do not match
W: $mf_url @ $t:
diff --git a/lib/PublicInbox/LeiXSearch.pm b/lib/PublicInbox/LeiXSearch.pm
index cee3ad07..fc95d401 100644
--- a/lib/PublicInbox/LeiXSearch.pm
+++ b/lib/PublicInbox/LeiXSearch.pm
@@ -298,8 +298,9 @@ sub fudge_qstr_time ($$$) {
$rft = $diff;
}
$lr -= ($rft || (48 * 60 * 60));
+ require PublicInbox::Admin;
$lei->qerr("# $uri limiting to ".
- strftime('%Y-%m-%d %k:%M %z', localtime($lr)). ' and newer');
+ PublicInbox::Admin::fmt_localtime($lr).' and newer');
# this should really be rt: (received-time), but no stable
# public-inbox releases support it, yet.
my $dt = 'dt:'.strftime('%Y%m%d%H%M%S', gmtime($lr)).'..';
diff --git a/lib/PublicInbox/WwwStatic.pm b/lib/PublicInbox/WwwStatic.pm
index 1c1a3d38..d8902193 100644
--- a/lib/PublicInbox/WwwStatic.pm
+++ b/lib/PublicInbox/WwwStatic.pm
@@ -12,13 +12,12 @@ use strict;
use v5.10.1;
use parent qw(Exporter);
use Fcntl qw(SEEK_SET O_RDONLY O_NONBLOCK);
-use POSIX qw(strftime);
use HTTP::Date qw(time2str);
use HTTP::Status qw(status_message);
use Errno qw(EACCES ENOTDIR ENOENT);
use URI::Escape qw(uri_escape_utf8);
use PublicInbox::GzipFilter qw(gzf_maybe);
-use PublicInbox::Hval qw(ascii_html);
+use PublicInbox::Hval qw(ascii_html fmt_ts);
use Plack::MIME;
our @EXPORT_OK = qw(@NO_CACHE r path_info_raw);
@@ -299,7 +298,7 @@ sub dir_response ($$$) {
$pad = 1 if $pad <= 0;
$entry = qq(\n<a\nhref="$href">$name</a>) .
(' ' x $pad) .
- strftime('%Y-%m-%d %k:%M', gmtime($mtime)) .
+ fmt_ts($mtime) .
sprintf('% 8s', $hsize);
}
diff --git a/xt/msgtime_cmp.t b/xt/msgtime_cmp.t
index a7ef5245..c63f785e 100644
--- a/xt/msgtime_cmp.t
+++ b/xt/msgtime_cmp.t
@@ -36,7 +36,7 @@ sub quiet_is_deeply ($$$$$) {
($old->[0] != $cur->[0]) ||
($old->[1] != $cur->[1]))) {
for ($cur, $old) {
- $_->[2] = strftime('%Y-%m-%d %k:%M:%S', gmtime($_->[0]))
+ $_->[2] = strftime('%F %T', gmtime($_->[0]))
}
is_deeply($cur, $old, "$func $oid");
diag('got: ', explain($cur));
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 07/14] xap_helper_cxx: decouple from Inline::C
2023-12-13 0:50 [PATCH 00/14] Alpine Linux support Eric Wong
` (5 preceding siblings ...)
2023-12-13 0:50 ` [PATCH 06/14] treewide: avoid strftime %k for portability Eric Wong
@ 2023-12-13 0:50 ` Eric Wong
2023-12-13 0:50 ` [PATCH 08/14] xap_helper_cxx: support clang w/o `c++' executable Eric Wong
` (6 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Eric Wong @ 2023-12-13 0:50 UTC (permalink / raw)
To: meta
We don't actually need Inline::C support to build a standalone
executable implemented in C++.
---
lib/PublicInbox/XapHelperCxx.pm | 11 ++++++-----
t/xap_helper.t | 6 ++++--
2 files changed, 10 insertions(+), 7 deletions(-)
diff --git a/lib/PublicInbox/XapHelperCxx.pm b/lib/PublicInbox/XapHelperCxx.pm
index 17f988ee..8e95ff42 100644
--- a/lib/PublicInbox/XapHelperCxx.pm
+++ b/lib/PublicInbox/XapHelperCxx.pm
@@ -16,8 +16,9 @@ use autodie;
my $cxx = which($ENV{CXX} // 'c++');
my $dir = substr("$cxx-$Config{archname}", 1); # drop leading '/'
$dir =~ tr!/!-!;
-$ENV{PERL_INLINE_DIRECTORY} // die('BUG: PERL_INLINE_DIRECTORY unset');
-substr($dir, 0, 0) = "$ENV{PERL_INLINE_DIRECTORY}/";
+my $idir = ($ENV{XDG_CACHE_HOME} //
+ (($ENV{HOME} // die('HOME unset')).'/.cache')).'/public-inbox/jaot';
+substr($dir, 0, 0) = "$idir/";
my $bin = "$dir/xap_helper";
my ($srcpfx) = (__FILE__ =~ m!\A(.+/)[^/]+\z!);
my @srcs = map { $srcpfx.$_ } qw(xh_mset.h xh_cidx.h xap_helper.h);
@@ -54,9 +55,9 @@ sub needs_rebuild () {
}
sub build () {
- if (!-d $dir && !CORE::mkdir($dir)) {
- my $err = $!;
- die "mkdir($dir): $err" if !-d $dir;
+ if (!-d $dir) {
+ require File::Path;
+ File::Path::make_path($dir);
}
require PublicInbox::CodeSearch;
require PublicInbox::Lock;
diff --git a/t/xap_helper.t b/t/xap_helper.t
index be010c75..0f474608 100644
--- a/t/xap_helper.t
+++ b/t/xap_helper.t
@@ -149,8 +149,10 @@ unless ($ENV{TEST_XH_CXX_ONLY}) {
no_pollerfd($ar->{pid});
}
SKIP: {
- require PublicInbox::XapHelperCxx;
- my $cmd = eval { PublicInbox::XapHelperCxx::cmd() };
+ my $cmd = eval {
+ require PublicInbox::XapHelperCxx;
+ PublicInbox::XapHelperCxx::cmd();
+ };
skip "XapHelperCxx build: $@", 1 if $@;
@NO_CXX = $ENV{TEST_XH_CXX_ONLY} ? (0) : (0, 1);
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 08/14] xap_helper_cxx: support clang w/o `c++' executable
2023-12-13 0:50 [PATCH 00/14] Alpine Linux support Eric Wong
` (6 preceding siblings ...)
2023-12-13 0:50 ` [PATCH 07/14] xap_helper_cxx: decouple from Inline::C Eric Wong
@ 2023-12-13 0:50 ` Eric Wong
2023-12-13 0:50 ` [PATCH 09/14] install: updates for Alpine Linux and apk Eric Wong
` (5 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Eric Wong @ 2023-12-13 0:50 UTC (permalink / raw)
To: meta
This makes the C++ build work on Alpine Linux (tested 3.19.0)
without having to install g++ to get the `c++' executable.
I've tested this change with and without g++ on Alpine so it'll
continue to work if a user decides to install g++.
This should continue to work if the Xapian package on Alpine is
changed to link against libc++ instead of libstdc++, since we
only add `-lstdc++' as a fallback. For reference, Xapian is
already linked against libc++ and not libstdc++ on FreeBSD 13.x
---
lib/PublicInbox/XapHelperCxx.pm | 15 ++++++++++++---
1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/lib/PublicInbox/XapHelperCxx.pm b/lib/PublicInbox/XapHelperCxx.pm
index 8e95ff42..6bd165b8 100644
--- a/lib/PublicInbox/XapHelperCxx.pm
+++ b/lib/PublicInbox/XapHelperCxx.pm
@@ -7,13 +7,13 @@
# The resulting executable is not linked to Perl in any way.
package PublicInbox::XapHelperCxx;
use v5.12;
-use PublicInbox::Spawn qw(run_die run_qx which);
+use PublicInbox::Spawn qw(run_die run_qx run_wait which);
use PublicInbox::IO qw(try_cat write_file);
use PublicInbox::Search;
use Fcntl qw(SEEK_SET);
use Config;
use autodie;
-my $cxx = which($ENV{CXX} // 'c++');
+my $cxx = which($ENV{CXX} // 'c++') // which('clang') // die 'no C++ compiler';
my $dir = substr("$cxx-$Config{archname}", 1); # drop leading '/'
$dir =~ tr!/!-!;
my $idir = ($ENV{XDG_CACHE_HOME} //
@@ -81,7 +81,16 @@ sub build () {
my @xflags = split(' ', "$fl $xflags"); # ' ' awk-mode eats leading WS
my @cflags = ('-I', $srcpfx, grep(!/\A-(?:Wl|l|L)/, @xflags));
run_die([$cxx, '-o', "$dir/$prog.o", '-c', "$dir/$prog.cpp", @cflags]);
- run_die([$cxx, '-o', "$dir/$prog.tmp", "$dir/$prog.o", @xflags]);
+
+ # xapian on Alpine Linux (tested 3.19.0) is linked against libstdc++,
+ # and clang needs to be told to use it (rather than libc++):
+ my @try = rindex($cxx, 'clang') >= 0 ? qw(-lstdc++) : ();
+ my @cmd = ($cxx, '-o', "$dir/$prog.tmp", "$dir/$prog.o", @xflags);
+ while (run_wait(\@cmd) and @try) {
+ warn("# attempting to link again with $try[0]...\n");
+ push(@cmd, shift(@try));
+ }
+ die "# @cmd failed: \$?=$?" if $?;
unlink "$dir/$prog.cpp", "$dir/$prog.o";
write_file '>', "$dir/XFLAGS.tmp", $xflags, "\n";
write_file '>', "$dir/xap_modversion.tmp", $xap_modversion, "\n";
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 09/14] install: updates for Alpine Linux and apk
2023-12-13 0:50 [PATCH 00/14] Alpine Linux support Eric Wong
` (7 preceding siblings ...)
2023-12-13 0:50 ` [PATCH 08/14] xap_helper_cxx: support clang w/o `c++' executable Eric Wong
@ 2023-12-13 0:50 ` Eric Wong
2023-12-13 0:50 ` [PATCH 10/14] test_common: extract oct_is from search.t Eric Wong
` (4 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Eric Wong @ 2023-12-13 0:50 UTC (permalink / raw)
To: meta
Somewhat surprising that BSD::Resource hasn't been packaged for
Alpine, but otherwise pretty straightforward mapping with some
dependencies filled in manually.
---
install/deps.perl | 38 +++++++++++++++++++++++++++++++++-----
install/os.perl | 12 +++++++++---
2 files changed, 42 insertions(+), 8 deletions(-)
diff --git a/install/deps.perl b/install/deps.perl
index 3fed4f10..6563c3ce 100755
--- a/install/deps.perl
+++ b/install/deps.perl
@@ -130,33 +130,48 @@ my $non_auto = { # git and perl (+autodie) are essential
pkg_add => [ qw(curl p5-Time-TimeDate git) ],
},
perl => {
+ apk => [ qw(perl perl-utils) ],
pkg => 'perl5',
pkgin => 'perl',
pkg_add => [], # Perl is part of OpenBSD base
},
# optional stuff:
+ 'BSD::Resource' => {
+ apk => [], # not packaged for Alpine 3.19
+ },
'Date::Parse' => {
+ apk => 'perl-timedate',
deb => 'libtimedate-perl',
pkg => 'p5-TimeDate',
rpm => 'perl-TimeDate',
pkg_add => 'p5-Time-TimeDate',
},
'Inline::C' => {
+ apk => [ qw(perl-inline-c perl-dev) ],
pkg_add => 'p5-Inline', # tested OpenBSD 7.3
rpm => 'perl-Inline', # for CentOS 7.x, at least
},
'DBD::SQLite' => { deb => 'libdbd-sqlite3-perl' },
+ 'Plack::Middleware::ReverseProxy' => {
+ apk => [], # not packaged for Alpine 3.19.0
+ },
'Plack::Test' => {
+ apk => 'perl-plack',
deb => 'libplack-perl',
pkg => 'p5-Plack',
},
+ 'Plack::Test::ExternalServer' => {
+ apk => [], # not packaged for Alpine 3.19.0
+ },
'Xapian' => {
+ apk => 'xapian-bindings-perl',
deb => 'libsearch-xapian-perl',
pkg => 'p5-Xapian',
pkg_add => 'xapian-bindings-perl',
rpm => [], # xapian14-bindings-perl in 3rd-party repo
},
'highlight.pm' => {
+ apk => [],
deb => 'libhighlight-perl',
pkg => [],
pkgin => 'p5-highlight',
@@ -171,6 +186,7 @@ my $non_auto = { # git and perl (+autodie) are essential
# some distros have both sqlite 2 and 3, we've only ever used 3
'libsqlite3' => {
+ apk => [], # handled by apk w/ perl-dbd-sqlite
pkg => 'sqlite3',
rpm => [], # `sqlite' is not removable due to yum/systemd
deb => [], # libsqlite3-0, but no need to specify
@@ -184,22 +200,26 @@ my $non_auto = { # git and perl (+autodie) are essential
rpm => 'xapian-core',
},
'libxapian-dev' => {
+ apk => 'xapian-core-dev',
pkg => 'xapian-core',
pkgin => 'xapian',
rpm => 'xapian-core-devel',
},
'pkg-config' => {
+ apk => [], # handled by apk w/ xapian-core-dev
pkg_add => [], # part of the OpenBSD base system
pkg => 'pkgconf', # pkg-config is a symlink to pkgconf
pkgin => 'pkg-config',
},
'sqlite3' => { # this is just the executable binary on deb
+ apk => 'sqlite',
rpm => [], # `sqlite' is not removable due to yum/systemd
},
# we call xapian-compact(1) in public-inbox-compact(1) and
# xapian-delve(1) in public-inbox-cindex(1)
'xapian-tools' => {
+ apk => 'xapian-core',
pkg => 'xapian-core',
pkgin => 'xapian',
rpm => 'xapian-core', # ???
@@ -207,6 +227,7 @@ my $non_auto = { # git and perl (+autodie) are essential
# OS-specific
'IO::KQueue' => {
+ apk => [],
deb => [],
rpm => [],
},
@@ -226,6 +247,7 @@ for (qw(autodie Digest::SHA ExtUtils::MakeMaker IO::Compress Sys::Syslog
deb => 'perl', # libperl5.XX, but the XX varies
pkg => 'perl5',
pkg_add => [], # perl is in the OpenBSD base system
+ apk => 'perl',
pkgin => 'perl',
rpm => "perl-$rpm",
};
@@ -240,8 +262,9 @@ if ($pkg_fmt =~ /\A(?:pkg_add|pkgin)\z/) {
}
my %inst_check = ( # subs which return true if a package is intalled
- pkg => sub { system(qw(pkg info -q), $_[0]) == 0 },
+ apk => sub { system(qw(apk info -q -e), $_[0]) == 0 },
deb => sub { system("dpkg -s $_[0] >/dev/null 2>&1") == 0 },
+ pkg => sub { system(qw(pkg info -q), $_[0]) == 0 },
pkg_add => sub { system(qw(pkg_info -q -e), "$_[0]->=0") == 0 },
pkgin => sub { system(qw(pkg_info -q -e), $_[0]) == 0 },
rpm => sub { system("rpm -qs $_[0] >/dev/null 2>&1") == 0 },
@@ -290,7 +313,10 @@ my (%add, %rm); # uniquify lists
(@pkg_remove || @pkg_install) or warn "# no packages to install nor remove\n";
# OS-specific cleanups appreciated
-if ($pkg_fmt eq 'deb') {
+if ($pkg_fmt eq 'apk') {
+ root('apk', 'add', @pkg_install) if @pkg_install;
+ root('apk', 'del', @pkg_remove) if @pkg_remove;
+} elsif ($pkg_fmt eq 'deb') {
my @apt_opt = qw(-o APT::Install-Recommends=false
-o APT::Install-Suggests=false);
push @apt_opt, '-y' if $opt->{yes};
@@ -340,10 +366,12 @@ sub pkg2ospkg {
# check common Perl module name patterns:
if ($pkg =~ /::/ || $pkg =~ /\A[A-Z]/) {
- if ($fmt eq 'deb') {
+ if ($fmt eq 'apk') {
+ $pkg =~ s/::/-/g;
+ return "perl-\L$pkg"
+ } elsif ($fmt eq 'deb') {
$pkg =~ s/::/-/g;
- $pkg =~ tr/A-Z/a-z/;
- return "lib$pkg-perl";
+ return "lib\L$pkg-perl";
} elsif ($fmt eq 'rpm') {
$pkg =~ s/::/-/g;
return "perl-$pkg"
diff --git a/install/os.perl b/install/os.perl
index bf5c55c2..00edbadf 100644
--- a/install/os.perl
+++ b/install/os.perl
@@ -50,8 +50,13 @@ EOM
die "$^O unsupported";
}
$VERSION_ID //= 0; # numeric? could be 'sid', actually...
-my %MIN_VER = (freebsd => v11, openbsd => v7.3, netbsd => v9.3,
- dragonfly => v6.4);
+my %MIN_VER = ( # likely older versions work for many of these...
+ alpine => v3.19,
+ dragonfly => v6.4,
+ freebsd => v11,
+ netbsd => v9.3,
+ openbsd => v7.3,
+);
if (defined(my $min_ver = $MIN_VER{$^O})) {
my $vid = $VERSION_ID;
@@ -64,7 +69,8 @@ EOM
}
sub pkg_fmt () {
- if ($ID =~ /\A(?:freebsd|dragonfly)\z/) { 'pkg' }
+ if ($ID eq 'alpine') { 'apk' }
+ elsif ($ID =~ /\A(?:freebsd|dragonfly)\z/) { 'pkg' }
# *shrug*, as long as the (Net|Open)BSD names don't conflict w/ FreeBSD
elsif ($ID eq 'netbsd') { 'pkgin' }
elsif ($ID eq 'openbsd') { 'pkg_add' }
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 10/14] test_common: extract oct_is from search.t
2023-12-13 0:50 [PATCH 00/14] Alpine Linux support Eric Wong
` (8 preceding siblings ...)
2023-12-13 0:50 ` [PATCH 09/14] install: updates for Alpine Linux and apk Eric Wong
@ 2023-12-13 0:50 ` Eric Wong
2023-12-13 0:50 ` [PATCH 11/14] t/convert-compact: allow S_ISGID bit Eric Wong
` (3 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Eric Wong @ 2023-12-13 0:50 UTC (permalink / raw)
To: meta
And use it in convert-compact.t This gives us nicer errors for
debugging a problem I noticed on Alpine Linux (tested 3.19.0)
---
lib/PublicInbox/TestCommon.pm | 8 +++++++-
t/convert-compact.t | 18 +++++++++---------
t/search.t | 5 -----
3 files changed, 16 insertions(+), 15 deletions(-)
diff --git a/lib/PublicInbox/TestCommon.pm b/lib/PublicInbox/TestCommon.pm
index 9c413f43..22c50675 100644
--- a/lib/PublicInbox/TestCommon.pm
+++ b/lib/PublicInbox/TestCommon.pm
@@ -29,7 +29,7 @@ BEGIN {
tcp_host_port test_lei lei lei_ok $lei_out $lei_err $lei_opt
test_httpd xbail require_cmd is_xdeeply tail_f
ignore_inline_c_missing no_pollerfd no_coredump cfg_new
- strace strace_inject lsof_pid);
+ strace strace_inject lsof_pid oct_is);
require Test::More;
my @methods = grep(!/\W/, @Test::More::EXPORT);
eval(join('', map { "*$_=\\&Test::More::$_;" } @methods));
@@ -1033,6 +1033,12 @@ sub strace_inject (;$) {
$cmd
}
+sub oct_is ($$$) {
+ my ($got, $exp, $msg) = @_;
+ @_ = (sprintf('0%03o', $got), sprintf('0%03o', $exp), $msg);
+ goto &is; # tail recursion to get lineno from callers on failure
+}
+
package PublicInbox::TestCommon::InboxWakeup;
use strict;
sub on_inbox_unlock { ${$_[0]}->($_[1]) }
diff --git a/t/convert-compact.t b/t/convert-compact.t
index 1ac3517d..c7b7f77e 100644
--- a/t/convert-compact.t
+++ b/t/convert-compact.t
@@ -35,14 +35,14 @@ EOF
$im->add($eml) or BAIL_OUT '->add';
};
umask(077) or BAIL_OUT "umask: $!";
-is(((stat("$ibx->{inboxdir}/public-inbox"))[2]) & 07777, 0755,
+oct_is(((stat("$ibx->{inboxdir}/public-inbox"))[2]) & 07777, 0755,
'sharedRepository respected for v1');
-is(((stat("$ibx->{inboxdir}/public-inbox/msgmap.sqlite3"))[2]) & 07777, 0644,
- 'sharedRepository respected for v1 msgmap');
+oct_is(((stat("$ibx->{inboxdir}/public-inbox/msgmap.sqlite3"))[2]) & 07777,
+ 0644, 'sharedRepository respected for v1 msgmap');
my @xdir = glob("$ibx->{inboxdir}/public-inbox/xap*/*");
foreach (@xdir) {
my @st = stat($_);
- is($st[2] & 07777, -f _ ? 0644 : 0755,
+ oct_is($st[2] & 07777, -f _ ? 0644 : 0755,
'sharedRepository respected on file after convert');
}
@@ -55,7 +55,7 @@ ok(run_script($cmd, undef, $rdr), 'v1 compact works');
@xdir = glob("$ibx->{inboxdir}/public-inbox/xap*");
is(scalar(@xdir), 1, 'got one xapian directory after compact');
-is(((stat($xdir[0]))[2]) & 07777, 0755,
+oct_is(((stat($xdir[0]))[2]) & 07777, 0755,
'sharedRepository respected on v1 compact');
my $hwm = do {
@@ -73,7 +73,7 @@ ok(run_script($cmd, undef, $rdr), 'convert works');
@xdir = glob("$tmpdir/x/v2/xap*/*");
foreach (@xdir) {
my @st = stat($_);
- is($st[2] & 07777, -f _ ? 0644 : 0755,
+ oct_is($st[2] & 07777, -f _ ? 0644 : 0755,
'sharedRepository respected after convert');
}
@@ -87,17 +87,17 @@ is($ibx->mm->num_highwater, $hwm, 'highwater mark unchanged in v2 inbox');
@xdir = glob("$tmpdir/x/v2/xap*/*");
foreach (@xdir) {
my @st = stat($_);
- is($st[2] & 07777, -f _ ? 0644 : 0755,
+ oct_is($st[2] & 07777, -f _ ? 0644 : 0755,
'sharedRepository respected after v2 compact');
}
-is(((stat("$tmpdir/x/v2/msgmap.sqlite3"))[2]) & 07777, 0644,
+oct_is(((stat("$tmpdir/x/v2/msgmap.sqlite3"))[2]) & 07777, 0644,
'sharedRepository respected for v2 msgmap');
@xdir = (glob("$tmpdir/x/v2/git/*.git/objects/*/*"),
glob("$tmpdir/x/v2/git/*.git/objects/pack/*"));
foreach (@xdir) {
my @st = stat($_);
- is($st[2] & 07777, -f _ ? 0444 : 0755,
+ oct_is($st[2] & 07777, -f _ ? 0444 : 0755,
'sharedRepository respected after v2 compact');
}
my $msgs = $ibx->over->recent({limit => 1000});
diff --git a/t/search.t b/t/search.t
index 282ae586..9fda6694 100644
--- a/t/search.t
+++ b/t/search.t
@@ -34,11 +34,6 @@ my $rw_commit = sub {
$ibx->search->reopen;
};
-sub oct_is ($$$) {
- my ($got, $exp, $msg) = @_;
- is(sprintf('0%03o', $got), sprintf('0%03o', $exp), $msg);
-}
-
{
# git repository perms
use_ok 'PublicInbox::Umask';
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 11/14] t/convert-compact: allow S_ISGID bit
2023-12-13 0:50 [PATCH 00/14] Alpine Linux support Eric Wong
` (9 preceding siblings ...)
2023-12-13 0:50 ` [PATCH 10/14] test_common: extract oct_is from search.t Eric Wong
@ 2023-12-13 0:50 ` Eric Wong
2023-12-13 0:50 ` [PATCH 12/14] www_coderepo: fix read buffering Eric Wong
` (2 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Eric Wong @ 2023-12-13 0:50 UTC (permalink / raw)
To: meta
My user home directory on Alpine has S_ISGID set on it and every
subdirectory inherits it. This includes my work tree and the
t/data-gen/* subdirectories. So just ignore the presence (or
non-presence) of the S_ISGID bit on directories descended from
the cached t/data-gen/* directories.
Now, public-inbox-convert may want to preserve S_ISGID on the
newly-created v2 inbox, but that's a separate discussion.
---
t/convert-compact.t | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/t/convert-compact.t b/t/convert-compact.t
index c7b7f77e..b123f17b 100644
--- a/t/convert-compact.t
+++ b/t/convert-compact.t
@@ -35,14 +35,14 @@ EOF
$im->add($eml) or BAIL_OUT '->add';
};
umask(077) or BAIL_OUT "umask: $!";
-oct_is(((stat("$ibx->{inboxdir}/public-inbox"))[2]) & 07777, 0755,
+oct_is(((stat("$ibx->{inboxdir}/public-inbox"))[2]) & 05777, 0755,
'sharedRepository respected for v1');
-oct_is(((stat("$ibx->{inboxdir}/public-inbox/msgmap.sqlite3"))[2]) & 07777,
+oct_is(((stat("$ibx->{inboxdir}/public-inbox/msgmap.sqlite3"))[2]) & 05777,
0644, 'sharedRepository respected for v1 msgmap');
my @xdir = glob("$ibx->{inboxdir}/public-inbox/xap*/*");
foreach (@xdir) {
my @st = stat($_);
- oct_is($st[2] & 07777, -f _ ? 0644 : 0755,
+ oct_is($st[2] & 05777, -f _ ? 0644 : 0755,
'sharedRepository respected on file after convert');
}
@@ -55,7 +55,7 @@ ok(run_script($cmd, undef, $rdr), 'v1 compact works');
@xdir = glob("$ibx->{inboxdir}/public-inbox/xap*");
is(scalar(@xdir), 1, 'got one xapian directory after compact');
-oct_is(((stat($xdir[0]))[2]) & 07777, 0755,
+oct_is(((stat($xdir[0]))[2]) & 05777, 0755,
'sharedRepository respected on v1 compact');
my $hwm = do {
@@ -71,7 +71,7 @@ ok(run_script($cmd, undef, $rdr), 'convert --no-index works');
$cmd = [ '-convert', $ibx->{inboxdir}, "$tmpdir/x/v2" ];
ok(run_script($cmd, undef, $rdr), 'convert works');
@xdir = glob("$tmpdir/x/v2/xap*/*");
-foreach (@xdir) {
+for (@xdir) { # TODO: should public-inbox-convert preserve S_ISGID bit?
my @st = stat($_);
oct_is($st[2] & 07777, -f _ ? 0644 : 0755,
'sharedRepository respected after convert');
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 12/14] www_coderepo: fix read buffering
2023-12-13 0:50 [PATCH 00/14] Alpine Linux support Eric Wong
` (10 preceding siblings ...)
2023-12-13 0:50 ` [PATCH 11/14] t/convert-compact: allow S_ISGID bit Eric Wong
@ 2023-12-13 0:50 ` Eric Wong
2023-12-13 0:50 ` [PATCH 13/14] gzip_filter: use OO ->zflush dispatch Eric Wong
2023-12-13 0:50 ` [PATCH 14/14] t/lei-import: relax EIO regexp Eric Wong
13 siblings, 0 replies; 15+ messages in thread
From: Eric Wong @ 2023-12-13 0:50 UTC (permalink / raw)
To: meta
Our read buffering only worked well with the stdout buffering on
glibc and *BSD libc, but not musl. When reading the stdout of
git(1), we are likely to get smaller buffers and require more
reads on musl-based systems (tested Alpine Linux 3.19.0).
Thus we must prevent ->translate from being called with an empty
argument list (denoting EOF). We'll also avoid some local
variable assignments while at it and favor the non-OO ->zflush
dispatch inside RepoAtom and WwwCoderepo subclasses.
---
lib/PublicInbox/RepoAtom.pm | 4 ++--
lib/PublicInbox/WwwCoderepo.pm | 6 +++---
t/solver_git.t | 8 +++++---
3 files changed, 10 insertions(+), 8 deletions(-)
diff --git a/lib/PublicInbox/RepoAtom.pm b/lib/PublicInbox/RepoAtom.pm
index c1649d0a..ab0f2fcc 100644
--- a/lib/PublicInbox/RepoAtom.pm
+++ b/lib/PublicInbox/RepoAtom.pm
@@ -43,7 +43,7 @@ sub zflush { $_[0]->SUPER::zflush('</feed>') }
# called by GzipFilter->write or GetlineResponse->getline
sub translate {
my $self = shift;
- my $rec = $_[0] // return $self->zflush; # getline
+ $_[0] // return zflush($self); # getline caller
my @out;
my $lbuf = delete($self->{lbuf}) // shift;
$lbuf .= shift while @_;
@@ -87,7 +87,7 @@ xmlns="http://www.w3.org/1999/xhtml"><pre style="white-space:pre-wrap">
}
$self->{lbuf} = $lbuf;
chomp @out;
- $self->SUPER::translate(@out);
+ @out ? $self->SUPER::translate(@out) : ''; # not EOF, yet
}
# $REPO/tags.atom endpoint
diff --git a/lib/PublicInbox/WwwCoderepo.pm b/lib/PublicInbox/WwwCoderepo.pm
index d1354af5..3814f719 100644
--- a/lib/PublicInbox/WwwCoderepo.pm
+++ b/lib/PublicInbox/WwwCoderepo.pm
@@ -273,7 +273,7 @@ sub zflush { $_[0]->SUPER::zflush('</pre>', $_[0]->_html_end) }
# called by GzipFilter->write or GetlineResponse->getline
sub translate {
my $ctx = shift;
- my $rec = $_[0] // return zflush($ctx); # getline
+ $_[0] // return zflush($ctx); # getline caller
my @out;
my $fbuf = delete($ctx->{fbuf}) // shift;
$fbuf .= shift while @_;
@@ -290,8 +290,8 @@ sub translate {
$snap_pfx, @snap_fmt);
}
}
- $ctx->{fbuf} = $fbuf;
- $ctx->SUPER::translate(@out);
+ $ctx->{fbuf} = $fbuf; # may be incomplete
+ @out ? $ctx->SUPER::translate(@out) : ''; # not EOF, yet
}
sub _refs_parse_hdr { # {parse_hdr} for Qspawn
diff --git a/t/solver_git.t b/t/solver_git.t
index ab8aba15..db672904 100644
--- a/t/solver_git.t
+++ b/t/solver_git.t
@@ -405,14 +405,16 @@ EOF
is($res->code, 200, 'Atom feed');
SKIP: {
require_mods('XML::TreePP', 1);
- my $t = XML::TreePP->new->parse($res->content);
+ my $t = eval { XML::TreePP->new->parse($res->content) }
+ or diag explain($res);
is(scalar @{$t->{feed}->{entry}}, 50,
- 'got 50 entries');
+ 'got 50 entries') or diag explain([$t, $res]);
$res = $cb->(GET('/public-inbox/atom/COPYING'));
is($res->code, 200, 'file Atom feed');
$t = XML::TreePP->new->parse($res->content);
- ok($t->{feed}->{entry}, 'got entry');
+ ok($t->{feed}->{entry}, 'got entry') or
+ diag explain([ $t, $res ]);
$res = $cb->(GET('/public-inbox/atom/README.md'));
is($res->code, 404, '404 on missing file Atom feed');
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 13/14] gzip_filter: use OO ->zflush dispatch
2023-12-13 0:50 [PATCH 00/14] Alpine Linux support Eric Wong
` (11 preceding siblings ...)
2023-12-13 0:50 ` [PATCH 12/14] www_coderepo: fix read buffering Eric Wong
@ 2023-12-13 0:50 ` Eric Wong
2023-12-13 0:50 ` [PATCH 14/14] t/lei-import: relax EIO regexp Eric Wong
13 siblings, 0 replies; 15+ messages in thread
From: Eric Wong @ 2023-12-13 0:50 UTC (permalink / raw)
To: meta
While it's not in a code path intended WwwCoderepo and RepoAtom,
those classes provide their own ->zflush, this can future-proof
our code against future subclasses at a minor performance cost.
---
lib/PublicInbox/GzipFilter.pm | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/PublicInbox/GzipFilter.pm b/lib/PublicInbox/GzipFilter.pm
index fc471ea2..8b630f25 100644
--- a/lib/PublicInbox/GzipFilter.pm
+++ b/lib/PublicInbox/GzipFilter.pm
@@ -106,7 +106,7 @@ sub translate {
zmore($self, @_);
length($self->{zbuf}) >= 8192 ? delete($self->{zbuf}) : '';
} else { # undef == EOF
- zflush($self);
+ $self->zflush;
}
}
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 14/14] t/lei-import: relax EIO regexp
2023-12-13 0:50 [PATCH 00/14] Alpine Linux support Eric Wong
` (12 preceding siblings ...)
2023-12-13 0:50 ` [PATCH 13/14] gzip_filter: use OO ->zflush dispatch Eric Wong
@ 2023-12-13 0:50 ` Eric Wong
13 siblings, 0 replies; 15+ messages in thread
From: Eric Wong @ 2023-12-13 0:50 UTC (permalink / raw)
To: meta
musl uses "I/O error" while glibc uses "Input/output error"
I wish something like strerrorname_np(3) were portable
and built into Perl so we could just match on /EIO/.
---
t/lei-import.t | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/t/lei-import.t b/t/lei-import.t
index b4446b56..89eb1492 100644
--- a/t/lei-import.t
+++ b/t/lei-import.t
@@ -172,12 +172,13 @@ SKIP: {
tick; # wait for strace to attach
ok(!lei(qw(import -F eml t/plack-qp.eml)),
'-F eml import fails on pathname error injection');
- like($lei_err, qr!error reading t/plack-qp\.eml: .*Input/output error!,
+ my $IO = '[Ii](?:nput)?/[Oo](?:utput)?';
+ like($lei_err, qr!error reading t/plack-qp\.eml: .*?$IO error!,
'EIO noted in stderr');
open $fh, '<', 't/plack-qp.eml';
ok(!lei(qw(import -F eml -), undef, { %$lei_opt, 0 => $fh }),
'-F eml import fails on stdin error injection');
- like($lei_err, qr!error reading .*?: .*Input/output error!,
+ like($lei_err, qr!error reading .*?: .*?$IO error!,
'EIO noted in stderr');
}
^ permalink raw reply related [flat|nested] 15+ messages in thread
end of thread, other threads:[~2023-12-13 0:50 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-12-13 0:50 [PATCH 00/14] Alpine Linux support Eric Wong
2023-12-13 0:50 ` [PATCH 01/14] t/io: strace is optional on Linux Eric Wong
2023-12-13 0:50 ` [PATCH 02/14] tests: account for missing git-http-backend Eric Wong
2023-12-13 0:50 ` [PATCH 03/14] t/cindex*: skip --join when join(1) is missing Eric Wong
2023-12-13 0:50 ` [PATCH 04/14] tests: attempt compatibility w/ busybox lsof Eric Wong
2023-12-13 0:50 ` [PATCH 05/14] lei inspect: drop unneeded strftime import Eric Wong
2023-12-13 0:50 ` [PATCH 06/14] treewide: avoid strftime %k for portability Eric Wong
2023-12-13 0:50 ` [PATCH 07/14] xap_helper_cxx: decouple from Inline::C Eric Wong
2023-12-13 0:50 ` [PATCH 08/14] xap_helper_cxx: support clang w/o `c++' executable Eric Wong
2023-12-13 0:50 ` [PATCH 09/14] install: updates for Alpine Linux and apk Eric Wong
2023-12-13 0:50 ` [PATCH 10/14] test_common: extract oct_is from search.t Eric Wong
2023-12-13 0:50 ` [PATCH 11/14] t/convert-compact: allow S_ISGID bit Eric Wong
2023-12-13 0:50 ` [PATCH 12/14] www_coderepo: fix read buffering Eric Wong
2023-12-13 0:50 ` [PATCH 13/14] gzip_filter: use OO ->zflush dispatch Eric Wong
2023-12-13 0:50 ` [PATCH 14/14] t/lei-import: relax EIO regexp 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).