public-inbox.git  about / heads / tags
an "archives first" approach to mailing lists
blob 2c859e65a6584fe31cb89b01fec5608f477f3036 1776 bytes (raw)
$ git show HEAD:lib/PublicInbox/Umask.pm	# shows this blob on the CLI

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
 
# Copyright (C) all contributors <meta@public-inbox.org>
# License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt>

# base class to ensures Xapian||SQLite files respect core.sharedRepository
# of git repos
package PublicInbox::Umask;
use v5.12;
use PublicInbox::OnDestroy;

use constant {
	PERM_UMASK => 0,
	OLD_PERM_GROUP => 1,
	OLD_PERM_EVERYBODY => 2,
	PERM_GROUP => 0660,
	PERM_EVERYBODY => 0664,
};

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);
	$perm //= '';
	return PERM_UMASK if $perm eq '' || $perm eq 'umask';
	return PERM_GROUP if $perm eq 'group';
	return PERM_EVERYBODY if $perm =~ /\A(?:all|world|everybody)\z/;
	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 $restore = on_destroy \&CORE::umask, $old;
	$cb ? $cb->(@arg) : $restore;
}

sub umask_prepare {
	my ($self) = @_;
	_umask_for(_git_config_perm($self));
}

1;

git clone https://public-inbox.org/public-inbox.git
git clone http://7fh6tueqddpjyxjmgtdiueylzoqt6pt7hec3pukyptlmohoowvhde4yd.onion/public-inbox.git