+# not documenting m: and mid: for now, the using the URLs works w/o Xapian
+# not documenting lid: for now, either, it is probably redundant with l:,
+# especially since we don't offer boolean searches for To/Cc/From
+# headers, either
+our @HELP = (
+ 's:' => 'match within Subject e.g. s:"a quick brown fox"',
+ 'd:' => <<EOF,
+date range as YYYYMMDD e.g. d:19931002..20101002
+Open-ended ranges such as d:19931002.. and d:..20101002
+are also supported
+EOF
+ 'dt:' => <<EOF,
+date-time range as YYYYMMDDhhmmss (e.g. dt:19931002011000..19931002011200)
+EOF
+ 'b:' => 'match within message body, including text attachments',
+ 'nq:' => 'match non-quoted text within message body',
+ 'q:' => 'match quoted text within message body',
+ 'n:' => 'match filename of attachment(s)',
+ 't:' => 'match within the To header',
+ 'c:' => 'match within the Cc header',
+ 'f:' => 'match within the From header',
+ 'a:' => 'match within the To, Cc, and From headers',
+ 'tc:' => 'match within the To and Cc headers',
+ 'l:' => 'match contents of the List-Id header',
+ 'bs:' => 'match within the Subject and body',
+ 'dfn:' => 'match filename from diff',
+ 'dfa:' => 'match diff removed (-) lines',
+ 'dfb:' => 'match diff added (+) lines',
+ 'dfhh:' => 'match diff hunk header context (usually a function name)',
+ 'dfctx:' => 'match diff context lines',
+ 'dfpre:' => 'match pre-image git blob ID',
+ 'dfpost:' => 'match post-image git blob ID',
+ 'dfblob:' => 'match either pre or post-image git blob ID',
+);
+chomp @HELP;
+
+sub xdir ($;$) {
+ my ($self, $rdonly) = @_;
+ if ($rdonly || !defined($self->{shard})) {
+ $self->{xpfx};
+ } else { # v2 only:
+ "$self->{xpfx}/$self->{shard}";
+ }
+}
+
+sub _xdb ($) {
+ my ($self) = @_;
+ my $dir = xdir($self, 1);
+ my ($xdb, $slow_phrase);
+ my $qpf = \($self->{qp_flags} ||= $QP_FLAGS);
+ if ($self->{ibx_ver} >= 2) {
+ my @xdb;
+ opendir(my $dh, $dir) or return; # not initialized yet
+
+ # We need numeric sorting so shard[0] is first for reading
+ # Xapian metadata, if needed
+ for (sort { $a <=> $b } grep(/\A[0-9]+\z/, readdir($dh))) {
+ my $shard_dir = "$dir/$_";
+ if (-d $shard_dir && -r _) {
+ push @xdb, $X{Database}->new($shard_dir);
+ $slow_phrase ||= -f "$shard_dir/iamchert";
+ } else { # gaps from missing epochs throw off mdocid()
+ warn "E: $shard_dir missing or unreadable\n";
+ return;
+ }
+ }
+ $self->{nshard} = scalar(@xdb);
+ $xdb = shift @xdb;
+ $xdb->add_database($_) for @xdb;
+ } else {
+ $slow_phrase = -f "$dir/iamchert";
+ $xdb = $X{Database}->new($dir);
+ }
+ $$qpf |= FLAG_PHRASE() unless $slow_phrase;
+ $xdb;
+}