diff options
Diffstat (limited to 'lib/PublicInbox/InboxWritable.pm')
-rw-r--r-- | lib/PublicInbox/InboxWritable.pm | 105 |
1 files changed, 33 insertions, 72 deletions
diff --git a/lib/PublicInbox/InboxWritable.pm b/lib/PublicInbox/InboxWritable.pm index 65539781..8e95cb28 100644 --- a/lib/PublicInbox/InboxWritable.pm +++ b/lib/PublicInbox/InboxWritable.pm @@ -1,25 +1,18 @@ -# Copyright (C) 2018-2021 all contributors <meta@public-inbox.org> +# Copyright (C) all contributors <meta@public-inbox.org> # License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt> # Extends read-only Inbox for writing package PublicInbox::InboxWritable; use strict; use v5.10.1; -use parent qw(PublicInbox::Inbox Exporter); +use parent qw(PublicInbox::Inbox PublicInbox::Umask Exporter); use PublicInbox::Import; +use PublicInbox::IO qw(read_all); use PublicInbox::Filter::Base qw(REJECT); use Errno qw(ENOENT); our @EXPORT_OK = qw(eml_from_path); use Fcntl qw(O_RDONLY O_NONBLOCK); -use constant { - PERM_UMASK => 0, - OLD_PERM_GROUP => 1, - OLD_PERM_EVERYBODY => 2, - PERM_GROUP => 0660, - PERM_EVERYBODY => 0664, -}; - sub new { my ($class, $ibx, $creat_opt) = @_; return $ibx if ref($ibx) eq $class; @@ -47,7 +40,7 @@ sub _init_v1 { require PublicInbox::Msgmap; my $sidx = PublicInbox::SearchIdx->new($self, 1); # just create $sidx->begin_txn_lazy; - my $mm = PublicInbox::Msgmap->new($self->{inboxdir}, 1); + my $mm = PublicInbox::Msgmap->new_file($self, 1); if (defined $skip_artnum) { $mm->{dbh}->begin_work; $mm->skip_artnum($skip_artnum); @@ -122,9 +115,8 @@ sub filter { sub eml_from_path ($) { my ($path) = @_; if (sysopen(my $fh, $path, O_RDONLY|O_NONBLOCK)) { - return unless -f $fh; # no FIFOs or directories - my $str = do { local $/; <$fh> } or return; - PublicInbox::Eml->new(\$str); + return unless -f $fh && -s _; # no FIFOs or directories + PublicInbox::Eml->new(\(my $str = read_all($fh, -s _))); } else { # ENOENT is common with Maildir warn "failed to open $path: $!\n" if $! != ENOENT; undef; @@ -176,64 +168,6 @@ sub import_mbox { $im->done; } -sub _read_git_config_perm { - my ($self) = @_; - chomp(my $perm = $self->git->qx('config', 'core.sharedRepository')); - $perm; -} - -sub _git_config_perm { - my $self = shift; - my $perm = scalar @_ ? $_[0] : _read_git_config_perm($self); - return PERM_UMASK 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, @arg) = @_; - my $old = umask($self->{umask} //= umask_prepare($self)); - my $rv = eval { $cb->(@arg) }; - my $err = $@; - umask $old; - die $err if $err; - $rv; -} - -sub umask_prepare { - my ($self) = @_; - my $perm = _git_config_perm($self); - _umask_for($perm); -} - sub cleanup ($) { delete @{$_[0]}{qw(over mm git search)}; } @@ -245,4 +179,31 @@ sub git_dir_latest { "$self->{inboxdir}/git/$$max.git" : undef; } +# for unconfigured inboxes +sub detect_indexlevel ($) { + my ($ibx) = @_; + + my $over = $ibx->over; + my $srch = $ibx->search; + delete @$ibx{qw(over search)}; # don't leave open FDs lying around + + # brand new or never before indexed inboxes default to full + return 'full' unless $over; + my $l = 'basic'; + return $l unless $srch; + if (my $xdb = $srch->xdb) { + $l = 'full'; + my $m = $xdb->get_metadata('indexlevel'); + if ($m eq 'medium') { + $l = $m; + } elsif ($m ne '') { + warn <<""; +$ibx->{inboxdir} has unexpected indexlevel in Xapian: $m + + } + $ibx->{-skip_docdata} = 1 if $xdb->get_metadata('skip_docdata'); + } + $l; +} + 1; |