]> Sergey Matveev's repositories - public-inbox.git/blobdiff - lib/PublicInbox/SearchIdx.pm
search: move permissions handling to InboxWritable
[public-inbox.git] / lib / PublicInbox / SearchIdx.pm
index 3d80b002f709448776aada0b03033ebf38a9bad4..9638e0c559a956d96218552fdd720bfe7333e546 100644 (file)
@@ -11,6 +11,7 @@ use strict;
 use warnings;
 use base qw(PublicInbox::Search PublicInbox::Lock);
 use PublicInbox::MIME;
+use PublicInbox::InboxWritable;
 use PublicInbox::MID qw/mid_clean id_compress mid_mime mids references/;
 use PublicInbox::MsgIter;
 use Carp qw(croak);
@@ -18,11 +19,6 @@ use POSIX qw(strftime);
 require PublicInbox::Git;
 
 use constant {
-       PERM_UMASK => 0,
-       OLD_PERM_GROUP => 1,
-       OLD_PERM_EVERYBODY => 2,
-       PERM_GROUP => 0660,
-       PERM_EVERYBODY => 0664,
        BATCH_BYTES => 1_000_000,
        DEBUG => !!$ENV{DEBUG},
 };
@@ -62,20 +58,19 @@ sub new {
                                PublicInbox::AltId->new($ibx, $_);
                        } @$altid ];
                }
-               $git = $ibx->git;
-       } else {
-               $git = PublicInbox::Git->new($git_dir); # v1 only
+       } else { # v1
+               $ibx = { mainrepo => $git_dir, version => 1 };
        }
+       $ibx = PublicInbox::InboxWritable->new($ibx);
        require Search::Xapian::WritableDatabase;
        my $self = bless {
                mainrepo => $mainrepo,
-               git => $git,
+               -inbox => $ibx,
+               git => $ibx->git,
                -altid => $altid,
                version => $version,
        }, $class;
-       my $perm = $self->_git_config_perm;
-       my $umask = _umask_for($perm);
-       $self->{umask} = $umask;
+       $ibx->umask_prepare;
        if ($version == 1) {
                $self->{lock_path} = "$mainrepo/ssoma.lock";
        } elsif ($version == 2) {
@@ -134,7 +129,9 @@ sub add_values ($$) {
        my $lines = $values->[PublicInbox::Search::LINES];
        add_val($doc, PublicInbox::Search::LINES, $lines);
 
-       my $yyyymmdd = strftime('%Y%m%d', gmtime($ts));
+       my $ds = $values->[PublicInbox::Search::DS];
+       add_val($doc, PublicInbox::Search::DS, $ds);
+       my $yyyymmdd = strftime('%Y%m%d', gmtime($ds));
        add_val($doc, PublicInbox::Search::YYYYMMDD, $yyyymmdd);
 }
 
@@ -298,7 +295,7 @@ sub add_message {
                }
 
                my $lines = $mime->body_raw =~ tr!\n!\n!;
-               my @values = ($smsg->ts, $num, $bytes, $lines);
+               my @values = ($smsg->ds, $num, $bytes, $lines, $smsg->ts);
                add_values($doc, \@values);
 
                my $tg = $self->term_generator;
@@ -350,7 +347,7 @@ sub add_message {
 
                # populates smsg->references for smsg->to_doc_data
                my $refs = parse_references($smsg);
-               $mid0 = $mids->[0] unless defined $mid0;
+               $mid0 = $mids->[0] unless defined $mid0; # v1 compatibility
                my $data = $smsg->to_doc_data($oid, $mid0);
                foreach my $mid (@$mids) {
                        $tg->index_text($mid, 1, 'XM');
@@ -367,10 +364,12 @@ sub add_message {
                        }
                }
 
+               $self->delete_article($num) if defined $num; # for reindexing
                if ($skel) {
                        push @values, $mids, $xpath, $data;
                        $skel->index_skeleton(\@values);
                        $doc->add_boolean_term('Q' . $_) foreach @$mids;
+                       $doc->add_boolean_term('XNUM' . $num) if defined $num;
                        $doc_id = $self->{xdb}->add_document($doc);
                } else {
                        $doc_id = link_and_save($self, $doc, $mids, $refs,
@@ -385,6 +384,14 @@ sub add_message {
        $doc_id;
 }
 
+# returns begin and end PostingIterator
+sub find_doc_ids {
+       my ($self, $termval) = @_;
+       my $db = $self->{xdb};
+
+       ($db->postlist_begin($termval), $db->postlist_end($termval));
+}
+
 sub batch_do {
        my ($self, $termval, $cb) = @_;
        my $batch_size = 1000; # don't let @ids grow too large to avoid OOM
@@ -419,6 +426,16 @@ sub remove_message {
        }
 }
 
+sub delete_article {
+       my ($self, $num) = @_;
+       my $ndel = 0;
+       batch_do($self, 'XNUM' . $num, sub {
+               my ($ids) = @_;
+               $ndel += scalar @$ids;
+               $self->{xdb}->delete_document($_) for @$ids;
+       });
+}
+
 # MID is a hint in V2
 sub remove_by_oid {
        my ($self, $oid, $mid) = @_;
@@ -547,6 +564,10 @@ sub link_and_save {
                        1;
                });
        }
+       if ($vivified > 1) {
+               my $id = '<'.join('> <', @$mids).'>';
+               warn "BUG: vivified multiple ($vivified) ghosts for $id\n";
+       }
        # not really important, but we return any vivified ghost docid, here:
        return $doc_id if defined $doc_id;
        link_doc($self, $doc, $refs, $old_tid);
@@ -622,7 +643,7 @@ sub do_cat_mail {
 
 sub index_sync {
        my ($self, $opts) = @_;
-       with_umask($self, sub { $self->_index_sync($opts) });
+       $self->{-inbox}->with_umask(sub { $self->_index_sync($opts) })
 }
 
 sub batch_adjust ($$$$) {
@@ -820,65 +841,6 @@ sub merge_threads {
        });
 }
 
-sub _read_git_config_perm {
-       my ($self) = @_;
-       my @cmd = qw(config);
-       if ($self->{version} == 2) {
-               push @cmd, "--file=$self->{mainrepo}/all.git/config";
-       }
-       my $fh = $self->{git}->popen(@cmd, 'core.sharedRepository');
-       local $/ = "\n";
-       my $perm = <$fh>;
-       chomp $perm if defined $perm;
-       $perm;
-}
-
-sub _git_config_perm {
-       my $self = shift;
-       my $perm = scalar @_ ? $_[0] : _read_git_config_perm($self);
-       return PERM_GROUP if (!defined($perm) || $perm eq '');
-       return PERM_UMASK if ($perm eq 'umask');
-       return PERM_GROUP if ($perm eq 'group');
-       if ($perm =~ /\A(?:all|world|everybody)\z/) {
-               return PERM_EVERYBODY;
-       }
-       return PERM_GROUP if ($perm =~ /\A(?:true|yes|on|1)\z/);
-       return PERM_UMASK if ($perm =~ /\A(?:false|no|off|0)\z/);
-
-       my $i = oct($perm);
-       return PERM_UMASK if ($i == PERM_UMASK);
-       return PERM_GROUP if ($i == OLD_PERM_GROUP);
-       return PERM_EVERYBODY if ($i == OLD_PERM_EVERYBODY);
-
-       if (($i & 0600) != 0600) {
-               die "core.sharedRepository mode invalid: ".
-                   sprintf('%.3o', $i) . "\nOwner must have permissions\n";
-       }
-       ($i & 0666);
-}
-
-sub _umask_for {
-       my ($perm) = @_; # _git_config_perm return value
-       my $rv = $perm;
-       return umask if $rv == 0;
-
-       # set +x bit if +r or +w were set
-       $rv |= 0100 if ($rv & 0600);
-       $rv |= 0010 if ($rv & 0060);
-       $rv |= 0001 if ($rv & 0006);
-       (~$rv & 0777);
-}
-
-sub with_umask {
-       my ($self, $cb) = @_;
-       my $old = umask $self->{umask};
-       my $rv = eval { $cb->() };
-       my $err = $@;
-       umask $old;
-       die $err if $err;
-       $rv;
-}
-
 sub DESTROY {
        # order matters for unlocking
        $_[0]->{xdb} = undef;