From 9d0d07a7a37c8a0a81646cb3a1e72ec1c937651c Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Sun, 23 Aug 2015 18:14:04 +0000 Subject: search: respect core.sharedRepository in for Xapian DB Extend the purpose of core.sharedRepository to apply to the $GIT_DIR/public-inbox/xapian* directory. --- lib/PublicInbox/SearchIdx.pm | 67 ++++++++++++++++++++++++++++++++++++++++++-- public-inbox-learn | 4 +-- public-inbox-mda | 4 +-- t/search.t | 25 +++++++++++++++++ 4 files changed, 92 insertions(+), 8 deletions(-) diff --git a/lib/PublicInbox/SearchIdx.pm b/lib/PublicInbox/SearchIdx.pm index 408b21fd..5664c385 100644 --- a/lib/PublicInbox/SearchIdx.pm +++ b/lib/PublicInbox/SearchIdx.pm @@ -8,6 +8,14 @@ use base qw(PublicInbox::Search); use PublicInbox::MID qw/mid_clean mid_compressed/; *xpfx = *PublicInbox::Search::xpfx; +use constant { + PERM_UMASK => 0, + OLD_PERM_GROUP => 1, + OLD_PERM_EVERYBODY => 2, + PERM_GROUP => 0660, + PERM_EVERYBODY => 0664, +}; + sub new { my ($class, $git_dir, $writable) = @_; my $dir = $class->xdir($git_dir); @@ -18,8 +26,15 @@ sub new { File::Path::mkpath($dir); $flag = Search::Xapian::DB_CREATE_OR_OPEN; } - my $db = Search::Xapian::WritableDatabase->new($dir, $flag); - bless { xdb => $db, git_dir => $git_dir }, $class; + my $self = bless { git_dir => $git_dir }, $class; + my $umask = _umask_for($self->_git_config_perm); + my $old_umask = umask $umask; + my $db = eval { Search::Xapian::WritableDatabase->new($dir, $flag) }; + my $err = $@; + umask $old_umask; + die $err if $err; + $self->{xdb} = $db; + $self; } sub add_message { @@ -360,4 +375,52 @@ 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 $perm = <$fh>; + close $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) || !length($perm)); + 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); +} + 1; diff --git a/public-inbox-learn b/public-inbox-learn index c89ffb54..f0bbd421 100755 --- a/public-inbox-learn +++ b/public-inbox-learn @@ -79,9 +79,7 @@ foreach my $recipient (keys %dests) { $err or eval { require PublicInbox::SearchIdx; - umask 0022; # XXX FIXME use git config core.sharedRepository - my $s = PublicInbox::SearchIdx->new($git_dir, 2); - $s->index_sync; + PublicInbox::SearchIdx->new($git_dir, 2)->index_sync; }; } diff --git a/public-inbox-mda b/public-inbox-mda index 630ffcb9..8e98d6eb 100755 --- a/public-inbox-mda +++ b/public-inbox-mda @@ -89,8 +89,6 @@ sub search_index_sync { my ($git_dir) = @_; eval { require PublicInbox::Search; - umask 0022; # XXX FIXME use git config core.sharedRepository - my $s = PublicInbox::SearchIdx->new($git_dir, 2); - $s->index_sync; + PublicInbox::SearchIdx->new($git_dir, 2)->index_sync; }; } diff --git a/t/search.t b/t/search.t index be39410f..17e9eaf4 100644 --- a/t/search.t +++ b/t/search.t @@ -23,6 +23,31 @@ my $rw_commit = sub { $rw = PublicInbox::SearchIdx->new($git_dir, 1); }; +{ + # git repository perms + is(PublicInbox::SearchIdx->_git_config_perm(undef), + &PublicInbox::SearchIdx::PERM_GROUP, + "undefined permission is group"); + is(PublicInbox::SearchIdx::_umask_for( + PublicInbox::SearchIdx->_git_config_perm('0644')), + 0022, "644 => umask(0022)"); + is(PublicInbox::SearchIdx::_umask_for( + PublicInbox::SearchIdx->_git_config_perm('0600')), + 0077, "600 => umask(0077)"); + is(PublicInbox::SearchIdx::_umask_for( + PublicInbox::SearchIdx->_git_config_perm('0640')), + 0027, "640 => umask(0027)"); + is(PublicInbox::SearchIdx::_umask_for( + PublicInbox::SearchIdx->_git_config_perm('group')), + 0007, 'group => umask(0007)'); + is(PublicInbox::SearchIdx::_umask_for( + PublicInbox::SearchIdx->_git_config_perm('everybody')), + 0002, 'everybody => umask(0002)'); + is(PublicInbox::SearchIdx::_umask_for( + PublicInbox::SearchIdx->_git_config_perm('umask')), + umask, 'umask => existing umask'); +} + { my $root = Email::MIME->create( header_str => [ -- cgit v1.2.3-24-ge0c7