-sub ext_msg {
- my ($ctx) = @_;
- my $pi_config = $ctx->{pi_config};
- my $listname = $ctx->{listname};
- my $mid = $ctx->{mid};
- my $cgi = $ctx->{cgi};
- my $env = $cgi->{env};
-
- eval { require PublicInbox::Search };
- my $have_xap = $@ ? 0 : 1;
- my (@nox, @pfx);
-
- foreach my $k (keys %$pi_config) {
- $k =~ /\Apublicinbox\.([A-Z0-9a-z-]+)\.url\z/ or next;
- my $list = $1;
- next if $list eq $listname;
-
- my $git_dir = $pi_config->{"publicinbox.$list.mainrepo"};
- defined $git_dir or next;
-
- my $url = $pi_config->{"publicinbox.$list.url"};
- defined $url or next;
-
- $url =~ s!/+\z!!;
- $url = PublicInbox::Hval::prurl($env, $url);
-
- # try to find the URL with Xapian to avoid forking
- if ($have_xap) {
- my $s;
- my $doc_id = eval {
- $s = PublicInbox::Search->new($git_dir);
- $s->find_unique_doc_id('mid', $mid);
- };
- if ($@) {
- # xapian not configured for this repo
- } else {
- # maybe we found it!
- return r302($url, $mid) if (defined $doc_id);
-
- # no point in trying the fork fallback if we
- # know Xapian is up-to-date but missing the
- # message in the current repo
- push @pfx, { git_dir => $git_dir, url => $url };
- next;
- }
+sub PARTIAL_MAX () { 100 }
+
+sub search_partial ($$) {
+ my ($ibx, $mid) = @_;
+ return if length($mid) < $MIN_PARTIAL_LEN;
+ my $srch = $ibx->search or return;
+ my $opt = { limit => PARTIAL_MAX, mset => 2 };
+ my @try = ("m:$mid*");
+ my $chop = $mid;
+ if ($chop =~ s/(\W+)(\w*)\z//) {
+ my ($delim, $word) = ($1, $2);
+ if (length($word)) {
+ push @try, "m:$chop$delim";
+ push @try, "m:$chop$delim*";
+ }
+ push @try, "m:$chop";
+ push @try, "m:$chop*";
+ }
+
+ # break out long words individually to search for, because
+ # too many messages begin with "Pine.LNX." (or "alpine" or "nycvar")
+ if ($mid =~ /\w{9,}/) {
+ my @long = ($mid =~ m!(\w{3,})!g);
+ push(@try, join(' ', map { "m:$_" } @long));
+
+ # is the last element long enough to not trigger excessive
+ # wildcard matches?
+ if (length($long[-1]) > 8) {
+ $long[-1] .= '*';
+ push(@try, join(' ', map { "m:$_" } @long));