]> Sergey Matveev's repositories - public-inbox.git/blobdiff - lib/PublicInbox/Import.pm
Merge branch 'thread-view-skel'
[public-inbox.git] / lib / PublicInbox / Import.pm
index f9c05da80945297ec8d38055fcd9633fcad5a353..27f36a7e486b84337e1e4e4586ab9ec5251e4c65 100644 (file)
@@ -8,7 +8,6 @@ package PublicInbox::Import;
 use strict;
 use warnings;
 use Fcntl qw(:flock :DEFAULT);
-use Email::Address;
 use PublicInbox::Spawn qw(spawn);
 use PublicInbox::MID qw(mid_mime mid2path);
 
@@ -45,12 +44,13 @@ sub gfi_start {
                        --quiet --done --date-format=rfc2822));
        my $rdr = { 0 => fileno($out_r), 1 => fileno($in_w) };
        my $pid = spawn(\@cmd, undef, $rdr);
-       die "spawn failed: $!" unless defined $pid;
+       die "spawn fast-import failed: $!" unless defined $pid;
        $out_w->autoflush(1);
        $self->{in} = $in_r;
        $self->{out} = $out_w;
        $self->{lockfh} = $lockfh;
        $self->{pid} = $pid;
+       $self->{nchg} = 0;
        ($in_r, $out_w);
 }
 
@@ -65,6 +65,13 @@ sub now2822 () {
                $day, $t[3], $mon, $t[5] + 1900, $t[2], $t[1], $t[0]);
 }
 
+sub norm_body ($) {
+       my ($mime) = @_;
+       my $b = $mime->body_raw;
+       $b =~ s/(\r?\n)+\z//s;
+       $b
+}
+
 # returns undef on non-existent
 # ('MISMATCH', msg) on mismatch
 # (:MARK, msg) on success
@@ -105,8 +112,11 @@ sub remove {
        defined($n) or die "read final byte of cat-blob failed: $!";
        die "bad read on final byte: <$lf>" if $lf ne "\n";
        my $cur = Email::MIME->new($buf);
-       if ($cur->header('Subject') ne $mime->header('Subject') ||
-                       $cur->body ne $mime->body) {
+       my $cur_s = $cur->header('Subject');
+       $cur_s = '' unless defined $cur_s;
+       my $cur_m = $mime->header('Subject');
+       $cur_m = '' unless defined $cur_m;
+       if ($cur_s ne $cur_m || norm_body($cur) ne norm_body($mime)) {
                return ('MISMATCH', $cur);
        }
 
@@ -124,29 +134,30 @@ sub remove {
                "data 3\nrm\n\n",
                'from ', ($parent ? $parent : $tip), "\n" or wfail;
        print $w "D $path\n\n" or wfail;
+       $self->{nchg}++;
        (($self->{tip} = ":$commit"), $cur);
 }
 
 # returns undef on duplicate
 sub add {
-       my ($self, $mime) = @_; # mime = Email::MIME
+       my ($self, $mime, $check_cb) = @_; # mime = Email::MIME
 
        my $from = $mime->header('From');
-       my @from = Email::Address->parse($from);
-       my $name = $from[0]->name;
-       my $email = $from[0]->address;
+       my ($email) = ($from =~ /([^<\s]+\@[^>\s]+)/g);
+       my $name = $from;
+       $name =~ s/\s*\S+\@\S+\s*\z//;
+       # git gets confused with:
+       #  "'A U Thor <u@example.com>' via foo" <foo@example.com>
+       # ref:
+       # <CAD0k6qSUYANxbjjbE4jTW4EeVwOYgBD=bXkSu=akiYC_CB7Ffw@mail.gmail.com>
+       $name =~ tr/<>// and $name = $email;
+
        my $date = $mime->header('Date');
        my $subject = $mime->header('Subject');
        $subject = '(no subject)' unless defined $subject;
        my $mid = mid_mime($mime);
        my $path = mid2path($mid);
 
-       # git gets confused with:
-       #  "'A U Thor <u@example.com>' via foo" <foo@example.com>
-       # ref:
-       # <CAD0k6qSUYANxbjjbE4jTW4EeVwOYgBD=bXkSu=akiYC_CB7Ffw@mail.gmail.com>
-       $name =~ s/<([^>]+)>/($1)/g;
-
        my ($r, $w) = $self->gfi_start;
        my $tip = $self->{tip};
        if ($tip ne '') {
@@ -159,6 +170,10 @@ sub add {
 
        # kill potentially confusing/misleading headers
        $mime->header_set($_) for qw(bytes lines content-length status);
+       if ($check_cb) {
+               $mime = $check_cb->($mime) or return;
+       }
+
        $mime = $mime->as_string;
        my $blob = $self->{mark}++;
        print $w "blob\nmark :$blob\ndata ", length($mime), "\n" or wfail;
@@ -184,6 +199,7 @@ sub add {
                print $w 'from ', ($parent ? $parent : $tip), "\n" or wfail;
        }
        print $w "M 100644 :$blob $path\n\n" or wfail;
+       $self->{nchg}++;
        $self->{tip} = ":$commit";
 }
 
@@ -195,19 +211,34 @@ sub done {
        my $pid = delete $self->{pid} or die 'BUG: missing {pid} when done';
        waitpid($pid, 0) == $pid or die 'fast-import did not finish';
        $? == 0 or die "fast-import failed: $?";
+       my $nchg = delete $self->{nchg};
 
        # for compatibility with existing ssoma installations
        # we can probably remove this entirely by 2020
        my $git_dir = $self->{git}->{git_dir};
-       my $index = "$git_dir/ssoma.index";
        # XXX: change the following scope to: if (-e $index) # in 2018 or so..
-       unless ($ENV{FAST}) {
-               local $ENV{GIT_INDEX_FILE} = $index;
-               system('git', "--git-dir=$git_dir", qw(read-tree -m -v -i),
-                       $self->{ref}) == 0 or
-                       die "failed to update $git_dir/ssoma.index: $?\n";
+       my @cmd = ('git', "--git-dir=$git_dir");
+       if ($nchg && !$ENV{FAST}) {
+               my $index = "$git_dir/ssoma.index";
+               my $env = { GIT_INDEX_FILE => $index };
+               my @rt = (@cmd, qw(read-tree -m -v -i), $self->{ref});
+               $pid = spawn(\@rt, $env, undef);
+               defined $pid or die "spawn read-tree failed: $!";
+               waitpid($pid, 0) == $pid or die 'read-tree did not finish';
+               $? == 0 or die "failed to update $git_dir/ssoma.index: $?\n";
+       }
+       if ($nchg) {
+               $pid = spawn([@cmd, 'update-server-info'], undef, undef);
+               defined $pid or die "spawn update-server-info failed: $!\n";
+               waitpid($pid, 0) == $pid or
+                       die 'update-server-info did not finish';
+               $? == 0 or die "failed to update-server-info: $?\n";
+
+               eval {
+                       require PublicInbox::SearchIdx;
+                       PublicInbox::SearchIdx->new($git_dir, 2)->index_sync;
+               };
        }
-
 
        my $lockfh = delete $self->{lockfh} or die "BUG: not locked: $!";
        flock($lockfh, LOCK_UN) or die "unlock failed: $!";