]> Sergey Matveev's repositories - public-inbox.git/blobdiff - lib/PublicInbox/SearchIdx.pm
search: support searching on List-Id
[public-inbox.git] / lib / PublicInbox / SearchIdx.pm
index fe00df53c268ffbc77bd4872fa6fb7ab5b4918e0..998341a7d4d5bfa069f02e6beca5e75ad04def74 100644 (file)
@@ -64,6 +64,7 @@ sub new {
                $self->{lock_path} = "$inboxdir/ssoma.lock";
                my $dir = $self->xdir;
                $self->{over} = PublicInbox::OverIdx->new("$dir/over.sqlite3");
+               $self->{index_max_size} = $ibx->{index_max_size};
        } elsif ($version == 2) {
                defined $shard or die "shard is required for v2\n";
                # shard is a number
@@ -275,22 +276,8 @@ sub index_diff ($$$) {
        index_text($self, join("\n", @xnq), 1, 'XNQ');
 }
 
-sub index_body ($$$) {
-       my ($self, $txt, $doc) = @_;
-       if ($doc) {
-               # does it look like a diff?
-               if ($txt =~ /^(?:diff|---|\+\+\+) /ms) {
-                       index_diff($self, $txt, $doc);
-               } else {
-                       index_text($self, $txt, 1, 'XNQ');
-               }
-       } else {
-               index_text($self, $txt, 0, 'XQUOT');
-       }
-}
-
 sub index_xapian { # msg_iter callback
-       my ($part, $depth, @idx) = @{$_[0]};
+       my $part = $_[0]->[0]; # ignore $depth and @idx
        my ($self, $doc) = @{$_[1]};
        my $ct = $part->content_type || 'text/plain';
        my $fn = $part->filename;
@@ -300,11 +287,24 @@ sub index_xapian { # msg_iter callback
 
        my ($s, undef) = msg_part_text($part, $ct);
        defined $s or return;
+       $_[0]->[0] = $part = undef; # free memory
 
        # split off quoted and unquoted blocks:
-       my @sections = split(/((?:^>[^\n]*\n)+)/sm, $s);
-       $part = $s = undef;
-       index_body($self, $_, /\A>/ ? 0 : $doc) for @sections;
+       my @sections = PublicInbox::MsgIter::split_quotes($s);
+       undef $s; # free memory
+       for my $txt (@sections) {
+               if ($txt =~ /\A>/) {
+                       index_text($self, $txt, 0, 'XQUOT');
+               } else {
+                       # does it look like a diff?
+                       if ($txt =~ /^(?:diff|---|\+\+\+) /ms) {
+                               index_diff($self, $txt, $doc);
+                       } else {
+                               index_text($self, $txt, 1, 'XNQ');
+                       }
+               }
+               undef $txt; # free memory
+       }
 }
 
 sub add_xapian ($$$$) {
@@ -352,6 +352,12 @@ sub add_xapian ($$$$) {
                }
        }
        $doc->add_boolean_term('Q' . $_) foreach @$mids;
+       for my $l ($hdr->header_raw('List-Id')) {
+               $l =~ /<([^>]+)>/ or next;
+               my $lid = $1;
+               $doc->add_boolean_term('G' . $lid);
+               index_text($self, $lid, 1, 'XL'); # probabilistic
+       }
        $self->{xdb}->replace_document($smsg->{num}, $doc);
 }
 
@@ -552,13 +558,9 @@ sub unindex_both {
 
 sub do_cat_mail {
        my ($git, $blob, $sizeref) = @_;
-       my $mime = eval {
-               my $str = $git->cat_file($blob, $sizeref);
-               # fixup bugs from import:
-               $$str =~ s/\A[\r\n]*From [^\r\n]*\r?\n//s;
-               PublicInbox::MIME->new($str);
-       };
-       $@ ? undef : $mime;
+       my $str = $git->cat_file($blob, $sizeref) or
+               die "BUG: $blob not found in $git->{git_dir}";
+       PublicInbox::MIME->new($str);
 }
 
 # called by public-inbox-index
@@ -577,6 +579,16 @@ sub batch_adjust ($$$$$) {
        }
 }
 
+sub too_big ($$$) {
+       my ($self, $git, $oid) = @_;
+       my $max_size = $self->{index_max_size} or return;
+       my (undef, undef, $size) = $git->check($oid);
+       die "E: bad $oid in $git->{git_dir}\n" if !defined($size);
+       return if $size <= $max_size;
+       warn "W: skipping $oid ($size > $max_size)\n";
+       1;
+}
+
 # only for v1
 sub read_log {
        my ($self, $log, $add_cb, $del_cb, $batch_cb) = @_;
@@ -603,7 +615,8 @@ sub read_log {
                                }
                                next;
                        }
-                       my $mime = do_cat_mail($git, $blob, \$bytes) or next;
+                       next if too_big($self, $git, $blob);
+                       my $mime = do_cat_mail($git, $blob, \$bytes);
                        my $smsg = bless {}, 'PublicInbox::Smsg';
                        batch_adjust(\$max, $bytes, $batch_cb, $latest, ++$nr);
                        $smsg->{blob} = $blob;
@@ -611,7 +624,7 @@ sub read_log {
                        $add_cb->($self, $mime, $smsg);
                } elsif ($line =~ /$delmsg/o) {
                        my $blob = $1;
-                       $D{$blob} = 1;
+                       $D{$blob} = 1 unless too_big($self, $git, $blob);
                } elsif ($line =~ /^commit ($h40)/o) {
                        $latest = $1;
                        $newest ||= $latest;
@@ -624,7 +637,7 @@ sub read_log {
        close($log) or die "git log failed: \$?=$?";
        # get the leftovers
        foreach my $blob (keys %D) {
-               my $mime = do_cat_mail($git, $blob, \$bytes) or next;
+               my $mime = do_cat_mail($git, $blob, \$bytes);
                $del_cb->($self, $mime);
        }
        $batch_cb->($nr, $latest, $newest);
@@ -635,7 +648,7 @@ sub _git_log {
        my $git = $self->{git};
 
        if (index($range, '..') < 0) {
-               # don't show annoying git errrors to users who run -index
+               # don't show annoying git errors to users who run -index
                # on empty inboxes
                $git->qx(qw(rev-parse -q --verify), "$range^0");
                if ($?) {