]> Sergey Matveev's repositories - public-inbox.git/blobdiff - lib/PublicInbox/SearchIdx.pm
use raw header for Message-ID
[public-inbox.git] / lib / PublicInbox / SearchIdx.pm
index f98ba3e1b668d3177a8375ffc93680824a179204..63be68101b40c8ae7f4f8d8e39ee94492594a589 100644 (file)
@@ -1,13 +1,20 @@
 # Copyright (C) 2015 all contributors <meta@public-inbox.org>
 # License: AGPLv3 or later (https://www.gnu.org/licenses/agpl-3.0.txt)
 # based on notmuch, but with no concept of folders, files or flags
+#
+# Indexes mail with Xapian and our (SQLite-based) ::Msgmap for use
+# with the web and NNTP interfaces.  This index maintains thread
+# relationships for use by Mail::Thread.  This writes to the search
+# index.
 package PublicInbox::SearchIdx;
 use strict;
 use warnings;
 use base qw(PublicInbox::Search);
-use PublicInbox::MID qw/mid_clean mid_compress/;
+use PublicInbox::MID qw/mid_clean id_compress mid_mime/;
+require PublicInbox::Git;
 *xpfx = *PublicInbox::Search::xpfx;
 
+use constant MAX_MID_SIZE => 244; # max term size - 1 in Xapian
 use constant {
        PERM_UMASK => 0,
        OLD_PERM_GROUP => 1,
@@ -47,11 +54,12 @@ sub add_message {
        my $db = $self->{xdb};
 
        my $doc_id;
-       my $mid = mid_clean($mime->header('Message-ID'));
+       my $mid = mid_clean(mid_mime($mime));
        my $was_ghost = 0;
        my $ct_msg = $mime->header('Content-Type') || 'text/plain';
 
        eval {
+               die 'Message-ID too long' if length($mid) > MAX_MID_SIZE;
                my $smsg = $self->lookup_message($mid);
                my $doc;
 
@@ -81,7 +89,7 @@ sub add_message {
 
                if ($subj ne '') {
                        my $path = $self->subject_path($subj);
-                       $doc->add_term(xpfx('path') . mid_compress($path));
+                       $doc->add_term(xpfx('path') . id_compress($path));
                }
 
                add_val($doc, &PublicInbox::Search::TS, $smsg->ts);
@@ -214,9 +222,10 @@ sub link_message_to_parents {
        my $doc = $smsg->{doc};
        my $mid = $smsg->mid;
        my $mime = $smsg->mime;
-       my $refs = $mime->header('References');
+       my $hdr = $mime->header_obj;
+       my $refs = $hdr->header_raw('References');
        my @refs = $refs ? ($refs =~ /<([^>]+)>/g) : ();
-       if (my $irt = $mime->header('In-Reply-To')) {
+       if (my $irt = $hdr->header_raw('In-Reply-To')) {
                # last References should be $irt
                # we will de-dupe later
                push @refs, mid_clean($irt);
@@ -230,6 +239,9 @@ sub link_message_to_parents {
 
                # prevent circular references via References: here:
                foreach my $ref (@orig_refs) {
+                       if (length($ref) > MAX_MID_SIZE) {
+                               warn "References: <$ref> too long, ignoring\n";
+                       }
                        next if $uniq{$ref};
                        $uniq{$ref} = 1;
                        push @refs, $ref;
@@ -263,29 +275,29 @@ sub index_blob {
 
 sub unindex_blob {
        my ($self, $git, $mime) = @_;
-       my $mid = mid_clean($mime->header('Message-ID'));
+       my $mid = eval { mid_clean(mid_mime($mime)) };
        $self->remove_message($mid) if defined $mid;
 }
 
 sub index_mm {
        my ($self, $git, $mime) = @_;
-       $self->{mm}->mid_insert(mid_clean($mime->header('Message-ID')));
+       $self->{mm}->mid_insert(mid_clean(mid_mime($mime)));
 }
 
 sub unindex_mm {
        my ($self, $git, $mime) = @_;
-       $self->{mm}->mid_delete(mid_clean($mime->header('Message-ID')));
+       $self->{mm}->mid_delete(mid_clean(mid_mime($mime)));
 }
 
 sub index_mm2 {
        my ($self, $git, $mime, $bytes) = @_;
-       my $num = $self->{mm}->num_for(mid_clean($mime->header('Message-ID')));
+       my $num = $self->{mm}->num_for(mid_clean(mid_mime($mime)));
        index_blob($self, $git, $mime, $bytes, $num);
 }
 
 sub unindex_mm2 {
        my ($self, $git, $mime) = @_;
-       $self->{mm}->mid_delete(mid_clean($mime->header('Message-ID')));
+       $self->{mm}->mid_delete(mid_clean(mid_mime($mime)));
        unindex_blob($self, $git, $mime);
 }
 
@@ -321,17 +333,12 @@ sub rlog {
        my $h40 = $hex .'{40}';
        my $addmsg = qr!^:000000 100644 \S+ ($h40) A\t${hex}{2}/${hex}{38}$!;
        my $delmsg = qr!^:100644 000000 ($h40) \S+ D\t${hex}{2}/${hex}{38}$!;
-       my $git_dir = $self->{git_dir};
-       require PublicInbox::GitCatFile;
-       my $git = PublicInbox::GitCatFile->new($git_dir);
-       my @cmd = ('git', "--git-dir=$git_dir", "log",
-                   qw/--reverse --no-notes --no-color --raw -r --no-abbrev/,
-                   $range);
+       my $git = PublicInbox::Git->new($self->{git_dir});
+       my $log = $git->popen(qw/log --reverse --no-notes --no-color
+                               --raw -r --no-abbrev/, $range);
        my $latest;
        my $bytes;
-       my $pid = open(my $log, '-|', @cmd) or
-               die('open` '.join(' ', @cmd) . " pipe failed: $!\n");
-       while (my $line = <$log>) {
+       while (defined(my $line = <$log>)) {
                if ($line =~ /$addmsg/o) {
                        my $mime = do_cat_mail($git, $1, \$bytes) or next;
                        $add_cb->($self, $git, $mime, $bytes);
@@ -342,7 +349,6 @@ sub rlog {
                        $latest = $1;
                }
        }
-       close $log;
        $latest;
 }
 
@@ -437,12 +443,9 @@ sub merge_threads {
 
 sub _read_git_config_perm {
        my ($self) = @_;
-       my @cmd = ('git', "--git-dir=$self->{git_dir}",
-                  qw(config core.sharedRepository));
-       my $pid = open(my $fh, '-|', @cmd) or
-               die('open `'.join(' ', @cmd) . " pipe failed: $!\n");
+       my @cmd = qw(config core.sharedRepository);
+       my $fh = PublicInbox::Git->new($self->{git_dir})->popen(@cmd);
        my $perm = <$fh>;
-       close $fh;
        chomp $perm if defined $perm;
        $perm;
 }