Eric Wong [Fri, 3 Jan 2020 08:45:58 +0000 (08:45 +0000)]
searchidx: index_diff: allow /^$/ line as diff context
As discovered by solver bug hunting, "git apply" also handles
the case where blank lines w/o leading space are treated as diff
context, apparently because GNU diff once did it:
Eric Wong [Sat, 4 Jan 2020 04:19:33 +0000 (04:19 +0000)]
solver: allow literal '\r' character in diff lines
While filenames are escaped, the actual diff contents may
contain an unescaped "\r" carriage return byte not in front
of the "\n" line feed. So just allow "\r" to appear in the
middle of a line.
Eric Wong [Sat, 4 Jan 2020 03:34:15 +0000 (03:34 +0000)]
solver: minor cleanups to diff extraction
Initialize the $di hashref at use to make it more obvious it's
a local variable. We can also use the :utf8 IO layer via
open+print to save ourselves the trouble of converting the UTF-8
patch to an octet stream.
Eric Wong [Sat, 4 Jan 2020 03:34:13 +0000 (03:34 +0000)]
xt/solver.t: real-world regression tests
There's a lot of test cases which we should probably
make self-contained at some point, but right now it's
easier to just mark them off in a maintainer test.
Eric Wong [Thu, 2 Jan 2020 09:24:59 +0000 (09:24 +0000)]
qspawn: use per-call quiet flag for solver
solver can spawn multiple processes per HTTP request, but
"git apply" failures are needlessly noisy due to corrupt
patches. We also don't want to silence "git ls-files"
or "git update-index" errors using $env->{'qspawn.quiet'},
either, so this granularity is needed.
Admins can check for 500 errors in access logs to detect
(and reproduce) solver failures, anyways, so there's no
need to log every time "git apply" rejects a corrupt patch.
Eric Wong [Fri, 3 Jan 2020 00:56:05 +0000 (00:56 +0000)]
solver: extract_diff: deal with missing "diff --git" line
Rewrite the patch extraction loop using a single regexp which
accounts for missing "diff --git ..." lines and is capable of
extracting pathnames off the "+++ b/foo" line.
This fixes the solving of blob "96f1c7f" off
<2841d2de-32ad-eae8-6039-9251a40bb00e@tngtech.com>
in git@vger archives.
v2:
* Fix regressions in git@vger archives:
- git/776fa90f7f/s/?b=contrib/git-jump/git-jump
(fallback to "old mode" properly)
- git/5cd8845/s/?b=submodule.c
(no leading space in context)
Eric Wong [Thu, 2 Jan 2020 09:24:57 +0000 (09:24 +0000)]
solver: try the next patch on apply failures
Sometimes a patch is corrupted and resent to create the same
OID. We need to account for that case and actually move onto
the next patch instead of blindly trying "git ls-files" to get
nothing out of it.
Eric Wong [Thu, 2 Jan 2020 23:29:28 +0000 (23:29 +0000)]
build: allow "check" to work in non-git subdirs of worktrees
Some people will place the contents of an unpacked tarball
inside another directory controlled by git (e.g. a ports tree
or even git-versioned home directory). "git ls-files" will
succeed in those cases, so we must check for the existence
of a ".git" dir, instead.
Eric Wong [Thu, 2 Jan 2020 03:09:30 +0000 (03:09 +0000)]
config: support multi-value inbox.*.*url
Since the beginning of this project, we've implicitly supported
inboxes with multiple URLs by relying on the Host: header sent
by the client ($env->{HTTP_HOST}).
We now offer the option to explicitly configure multiple URLs for
every inbox along with the ability to do a best-effort match for
matching hostnames.
Eric Wong [Thu, 2 Jan 2020 03:09:29 +0000 (03:09 +0000)]
wwwlisting: show configured "infourl" properly
git's config file keys lack underscores, but my mind is wired
for underscores :x. Fix the whitespace around the info URL
while we're at it, so that it shows up right under the inbox
description.
Eric Wong [Wed, 1 Jan 2020 09:57:51 +0000 (09:57 +0000)]
build: remove NEWS from dist-git target
mknews doesn't require any optional dependencies a user wouldn't
normally have. We can save storage and bandwidth costs by
letting cgit serve the exact tar.gz which "git archive | gzip -n"
generates.
Eric Wong [Wed, 1 Jan 2020 09:57:50 +0000 (09:57 +0000)]
doc: allow NEWS file to be built without Plack::Util
Plack pulls in a lot of dependencies which can be time-consuming
to install. It should not be necessary for somebody who just
wants to run -mda/-watch and -nntpd and forego WWW.
Eric Wong [Wed, 1 Jan 2020 10:38:59 +0000 (10:38 +0000)]
wwwstatic: add directory listing + index.html support
It's now possible to use WwwStatic as a standalone PSGI
app to serve static files and recreate the award-winning
web design of https://public-inbox.org/ :>
Eric Wong [Wed, 1 Jan 2020 10:38:58 +0000 (10:38 +0000)]
wwwstatic: avoid TOCTTOU for FIFO check
We can use Perl's sysopen function to pass O_NONBLOCK to open(2)
and avoid blocking on FIFOs. This avoids a TOCTTOU race where
somebody can change a regular to FIFO in between the stat(2) and
open(2) syscalls.
Eric Wong [Wed, 1 Jan 2020 10:38:56 +0000 (10:38 +0000)]
wwwstatic: move r(...) functions here
Remove redundant "r" functions for generating short error
responses. These responses will no longer be cached by clients,
which is probably a good thing since most errors ought to be
transient, anyways. This also fixes error responses for our
cgit wrapper when static files are missing.
Eric Wong [Tue, 31 Dec 2019 10:30:13 +0000 (10:30 +0000)]
cgit: type declaration for PublicInbox::Git
AFAIK this doesn't do anything for Perl internally since
PublicInbox::Git doesn't "use fields", but it makes it easier for
humans readers to follow and ensure we're not passing unblessed
or non-ref scalars to PublicInbox::GitHTTPBackend::serve.
Eric Wong [Tue, 31 Dec 2019 10:30:12 +0000 (10:30 +0000)]
filter/base: export REJECT as a constant
And update callers to use it, as it makes the code a bit cleaner.
Probably irrelvant, but it should be faster, too, as
"perl -I lib -w -MO=Deparse $FILE" shows REJECT() calls are
constant-folded.
Eric Wong [Tue, 31 Dec 2019 10:30:11 +0000 (10:30 +0000)]
githttpbackend: remove ancient compatibility check
The ref() call could be hitting memory leaks on Perl 5.16.x.
It's been 3 years (2016-12-25) since 292ca34140489da2
("githttpbackend: simplify compatibility code") back when
this project was barely known and probably nobody used
examples/public-inbox.psgi...
Eric Wong [Tue, 31 Dec 2019 10:30:09 +0000 (10:30 +0000)]
wwwstatic: getline: die on missing psgix.io
"psgix." extensions aren't guaranteed, so make we should
try and support some theoretical generic PSGI servers
without "psgix.io" on errors by die-ing.
While we're at it, make the error handling path more obvious by
sharing more code between the EOF and errno ($!) cases.
Eric Wong [Tue, 31 Dec 2019 22:34:16 +0000 (22:34 +0000)]
spamcheck/spamc: pass GLOB handles instead of FD numbers
The spawn() interface improvements[1] propagate to popen_rd,
too, so we can avoid weird dances to keep the GLOB handle
references live and just pass the handle around.
Eric Wong [Wed, 1 Jan 2020 03:28:22 +0000 (03:28 +0000)]
nntp: handle 2-digit year "70" properly
Time::Local has the concept of a "rolling century" which is
defined at 50 years on either side of the current year. Since
it's now 2020 and >50 years since the Unix epoch, the year "70"
gets interpreted by Time::Local as 2070-01-01 instead of
1970-01-01.
Since NNTP servers are unlikely to store messages from the
future, we'll feed 4-digit year to Time::Local::{timegm,timelocal}
and hopefully not have to worry about things until Y10K.
This fixes test failures on t/v2writable.t and t/nntpd.t since
2020-01-01.
Eric Wong [Mon, 30 Dec 2019 05:04:16 +0000 (05:04 +0000)]
spawn: better error handling
Since vfork always shares memory between the child and parent,
we can propagate errors to the parent errno using shared memory
instead of just dumping to stderr and hoping somebody sees it.
Eric Wong [Sat, 28 Dec 2019 21:43:17 +0000 (21:43 +0000)]
Merge branch 'no-closure'
* no-closure: (30 commits)
search: retry_reopen passes user arg to callback
solvergit: allow passing arg to user-supplied callback
viewvcs: avoid anonymous sub for HTML response
wwwattach: avoid anonymous sub for msg_iter
view: msg_iter calls add_body_text directly
searchview: remove anonymous sub when sorting threads by relevance
view: thread_html: pass named sub to WwwStream
searchview: pass named subs to Www*Stream
wwwtext: avoid anonymous sub in response
contentid: no anonymous sub
view: msg_html: stop using an anonymous sub
view: avoid anon sub in stream_thread
config: each_inbox: pass user arg to callback
feed: avoid anonymous subs
mboxgz: pass $ctx to callback to avoid anon subs
www: lazy load Plack::Util
githttpbackend: split out wwwstatic
qspawn: psgi_return: allow non-anon parse_hdr callback
qspawn: drop "qspawn.filter" support, for now
qspawn: psgi_qx: eliminate anonymous subs
...
Eric Wong [Sat, 28 Dec 2019 20:55:16 +0000 (20:55 +0000)]
ds: use MSG_MORE when wbuf is empty during long responses
HTTP::getline_pull and NNTP::long_step will both populate {wbuf}
manually to avoid recursion, so we need to account for an
empty-but-present {wbuf} while dispatching msg_more().
Eric Wong [Wed, 25 Dec 2019 07:51:03 +0000 (07:51 +0000)]
solvergit: allow passing arg to user-supplied callback
This allows us to get rid of the requirement to capture
on-stack variables with an anonymous sub, as illustrated
with the update to viewvcs to take advantage of this.
Eric Wong [Wed, 25 Dec 2019 07:50:59 +0000 (07:50 +0000)]
searchview: remove anonymous sub when sorting threads by relevance
We don't need to return a closure or have a separate hash
for sorting threads by relevance. Instead, we can stuff
the relevance {pct} into the SearchMsg object itself and
use that.
Note: upon reviewing this code, the sort-by-relevance seems
bogus as it only considers the relevance of the topmost message.
Instead, it would make more sense to the user to sort by the
highest relevance of all messages in that particular thread.
Eric Wong [Wed, 25 Dec 2019 07:50:53 +0000 (07:50 +0000)]
view: avoid anon sub in stream_thread
WwwStream already passes the WWW $ctx to the callback sub, so we
don't need to create a new sub every call to capture local variables
for the callback.
Eric Wong [Wed, 25 Dec 2019 07:50:51 +0000 (07:50 +0000)]
feed: avoid anonymous subs
WwwStream already passes the WWW $ctx to the user-supplied
callback, and it's a trivial change for WwwAtomStream to do
the same. Callers in Feed.pm can now take advantage of that
to save a few kilobytes of memory on every response.
Eric Wong [Wed, 25 Dec 2019 07:50:41 +0000 (07:50 +0000)]
qspawn: reduce local vars, de-anonymize rd_hdr
rd_hdr() now becomes a named subroutine instead of a per-call
local variable, so kilobytes of memory will not have to be
allocated for it on every ->psgi_return call.
This will tie into the DS event loop if that's used, but
event_step an be called directly without relying on the
event loop from Apache or other HTTP servers (or PSGI tests).
Eric Wong [Wed, 25 Dec 2019 07:50:37 +0000 (07:50 +0000)]
qspawn: remove some anonymous subs for psgi_qx
By passing a user-supplied arg to $qx_cb, we can eliminate the
callers' need to capture on-stack variables with a closure.
This saves several kilobytes of memory allocation at the expense
of some extra hash table lookups in user-supplied callbacks. It
also reduces the risk of memory leaks by eliminating a common
source of circular references.
Eric Wong [Thu, 26 Dec 2019 10:47:12 +0000 (10:47 +0000)]
wwwlisting: do not rely on $? after ProcessPipe::CLOSE
ProcessPipe::CLOSE won't reliably set $? inside the event loop
if waitpid(..., WNOHANG) isn't successful. So use a blocking
waitpid() call, here, and hope "git show-ref" exits promptly
since we've already drained its stdout.
Eric Wong [Thu, 26 Dec 2019 06:48:04 +0000 (06:48 +0000)]
t/solver_git: test with -httpd, too
Solver uses the internal -httpd async API if available for
fairness when applying large patchsets. We must test those
code paths in addition to the generic PSGI code paths.
Eric Wong [Thu, 26 Dec 2019 06:48:02 +0000 (06:48 +0000)]
t/www_listing: quiet down stderr in -httpd
We need to init all.git for the v2 repo test to ensure
`git --git-dir=v2/all.git rev-parse --git-path objects/info/alternates`
doesn't warn or fail and clutter stderr. This is noticeable
when setting TAIL="tail -F" in env before running this test.
Eric Wong [Sun, 22 Dec 2019 22:17:39 +0000 (22:17 +0000)]
search: support SWIG-generated Xapian.pm
Xapian upstream is slowly phasing out the XS-based Search::Xapian
in favor of the SWIG-generated "Xapian" package. While Debian and
both FreeBSD have Search::Xapian, OpenBSD only includes the "Xapian"
binding.
More information about the status of the "Xapian" Perl module here:
https://trac.xapian.org/ticket/523
Eric Wong [Sun, 22 Dec 2019 22:17:38 +0000 (22:17 +0000)]
searchidx: call "++" on PostingIterator instead of "->inc"
The "++" is not yet available in the SWIG-based "Xapian.pm" Perl
bindings, so use "++" where it's supported in both the XS
(Search::Xapian) and SWIG-based Xapian binding.
Eric Wong [Sun, 22 Dec 2019 22:17:37 +0000 (22:17 +0000)]
testcommon: add require_mods method and use it
This cuts down on lines of code in individual test cases and
fixes some misnamed error messages by using "$0" consistently.
This will also provide us with a method of swapping out
dependencies which provide equivalent functionality (e.g
"Xapian" SWIG can replace "Search::Xapian" XS bindings).
Eric Wong [Mon, 23 Dec 2019 23:06:03 +0000 (23:06 +0000)]
remove "no warnings 'once'" in a few places
We can use "use" to get the namespace into the "BEGIN" phase of
the interpreter. While we're at it, use \&coderef syntax
explicitly instead of globbing everything.
Eric Wong [Sat, 21 Dec 2019 08:00:01 +0000 (08:00 +0000)]
nntp: remove cyclic refs from long_response
Leftover cyclic references are a source of memory leaks. While
our code is AFAIK unaffected by such leaks at the moment,
eliminating a potential source of bugs will make maintenance
easier.
We make the long_response API cycle-free by stashing the
callback into the NNTP object. However, callers will need
to be updated to get rid of the circular reference to $self.
We do that be replacing anonymous subs with name subroutine
references, such as xref_range_i replacing the formerly
anonymous sub inside hdr_xref.
Eric Wong [Sat, 21 Dec 2019 08:00:00 +0000 (08:00 +0000)]
nntp: get_range: return scalarref for $beg
...Instead of just returning a plain scalar inside an arrayref.
This is because we usually pass the result of NNTP::get_range to
Msgmap::msg_range. Upcoming changes will move us away from
anonymous subroutines, so this change will make followup commits
easier-to-digest as modifications to the underlying scalar can
be more easily propagated between non-anonymous-subs.
Eric Wong [Sat, 21 Dec 2019 23:53:18 +0000 (23:53 +0000)]
http: get rid of anonymous subs for write/close
Each sub costs us several kilobytes of memory for every
response we make. An arrayref only costs 80 bytes on
64-bit, so bless that to packages with appropriate ->write
and ->close methods.
Eric Wong [Thu, 19 Dec 2019 05:18:00 +0000 (05:18 +0000)]
searchthread: fix usage of user-supplied parameter
Instead of only passing an Inbox object, we'll pass the $ctx
reference as PublicInbox::SearchView::mset_thread did.
So although mset_thread was wrong, we now make it's usage
of SearchThread::thread correct and update other callers to
favor the new style of passing the entire $ctx (with ->{-inbox})
instead of just the Inbox object.
This makes the thread skeleton at the bottom of the search
page to show subjects of messages, but unfortunately links to
non-existent #anchors. The next commit will fix that.
While we're at it, favor "\&foo" over "*foo" since the former
makes the code reference (aka "function pointer) obvious so it
won't be confused for other things named "foo" in that
scope (e.g. $foo/@foo/%foo).
Eric Wong [Thu, 19 Dec 2019 08:38:51 +0000 (08:38 +0000)]
testcommon: fix run_script for older Perls
Using Perl "open" to dup(2) and save the old handles is required
since "local *STDIN = *STDIN" does not work on old Perls. Even
worse, this was silently a no-op when tested with Perl 5.24.1 on
Debian 9.x and led to confusing failures in the t/httpd-corner.t
lsof(1) tests when run after t/v2mirror.t from the same worker
process using t/run.perl.
Eric Wong [Wed, 18 Dec 2019 03:36:45 +0000 (03:36 +0000)]
t/run.perl: to avoid repeated process spawning for *.t
Spawning a new Perl interpreter for every test case
means Perl has to reparse and recompile every single file
it needs, costing us performance and development time.
Now that we've modified our code to avoid global state,
we can preload everything we need.
The new "check-run" test target is now 20-30% faster
than the original "check" target.
Eric Wong [Wed, 18 Dec 2019 03:36:44 +0000 (03:36 +0000)]
tests: move t/common.perl to PublicInbox::TestCommon
We want to be able to use run_script with *.t files, so
t/common.perl putting subs into the top-level "main" namespace
won't work. Instead, make it a module which uses Exporter
like other libraries.
Eric Wong [Wed, 18 Dec 2019 03:36:43 +0000 (03:36 +0000)]
t/*.t: avoid sharing "my" variables in subs
These usages of file-local global variables make the *.t files
incompatible with run_script(). Instead, use anonymous subs,
"our", or pass the parameter as appropriate.
Eric Wong [Wed, 18 Dec 2019 09:14:43 +0000 (09:14 +0000)]
msgiter: msg_part_text returns undef on text/html
We want HTML parts to be downloadable, but not displayed as
unreadable (but injection-safe) HTML source in our own web
and Atom interfaces.
This affects indexing, too, as HTML tags/comments won't be
indexed anymore, but existing indices are only cleaned after
--reindex. HTML-only mail won't be indexed at all, but we won't
cross that bridge until somebody cares about that crap. We'll
continue to actively discourage such waste of CPU cycles,
bandwidth, cache and storage.
Fixes: 7d82a8bc04ce2e68 (handle "multipart/mixed" messages which are not multipart')
Eric Wong [Wed, 18 Dec 2019 03:36:41 +0000 (03:36 +0000)]
viewvcs: flesh out some functionality and test
Expose MAX_SIZE via "our" will make it possible
to use in tests, and configure, later.
Additionally, returning HTTP 500 code for big files is not an
Internal Server Error, just a memory limit... Some browsers
won't show our HTML response with the link to the raw file in
case of errors, either, so we'll return 200 to ensure users can
use the link to access the raw blob.
Finally, throw in some tests to the existing solver_git testcase,
since that was incomplete and was pointlessly loading Plack
modules without testing PSGI.