allow @groups in setperms command also

This should hopefully be the final step in making wildrepos as close to
normal repos as possible.  You can now do pretty much anything with them
that you can do with normal repos [1]

Implementation notes:

  - compile puts out %groups into the compiled config file regardless of
    GL_BIG_CONFIG because this feature needs it
  - wild_repo_rights caches %groups because the part of the %groups hash
    we care about will not change between calls in the same run

----

[1] **except** use the full-blown config file syntax within the gl-perms
    file :-)  I don't plan to do that; it's too complicated! [2]

[2] yeah yeah I know -- famous last words!
This commit is contained in:
Sitaram Chamarty 2010-08-21 09:56:11 +05:30
parent 34965b1b03
commit 6e2db12302
7 changed files with 305 additions and 23 deletions

View file

@ -255,28 +255,53 @@ sub new_repo
# metaphysics (like, "is there a god?", "who created me?", etc)
# ----------------------------------------------------------------------------
# "who created this repo", "am I on the R list", and "am I on the RW list"?
sub wild_repo_rights
{
my ($repo, $user) = @_;
# creator
my $c = '';
if ( -f "$ENV{GL_REPO_BASE_ABS}/$repo.git/gl-creater") {
my $fh = wrap_open("<", "$ENV{GL_REPO_BASE_ABS}/$repo.git/gl-creater");
chomp($c = <$fh>);
}
# $user's R and W rights
my ($r, $w); $r = ''; $w = '';
if ($user and -f "$ENV{GL_REPO_BASE_ABS}/$repo.git/gl-perms") {
my $fh = wrap_open("<", "$ENV{GL_REPO_BASE_ABS}/$repo.git/gl-perms");
my $perms = join ("", <$fh>);
if ($perms) {
$r = $user if $perms =~ /^\s*R(?=\s).*\s(\@all|$user)(\s|$)/m;
$w = $user if $perms =~ /^\s*RW(?=\s).*\s(\@all|$user)(\s|$)/m;
}
}
# the following sub needs some persistent data, so we make a closure
my $cache_filled = 0;
my %cached_groups;
return ($c, $r, $w);
# "who created this repo", "am I on the R list", and "am I on the RW list"?
sub wild_repo_rights
{
my ($repo, $user) = @_;
# pull in basic group info
unless ($cache_filled) {
local(%repos, %groups);
# read group info from compiled config. At the time we're called
# this info has not yet been pulled in by the rest of the code, so
# we need to do this specially here. However, the info we're
# looking for is not subject to variable substitutions so we don't
# really care; we just pull it in once and save it for the rest of
# the run
do $GL_CONF_COMPILED;
%cached_groups = %groups;
$cache_filled++;
}
# creator
my $c = '';
if ( -f "$ENV{GL_REPO_BASE_ABS}/$repo.git/gl-creater") {
my $fh = wrap_open("<", "$ENV{GL_REPO_BASE_ABS}/$repo.git/gl-creater");
chomp($c = <$fh>);
}
# $user's R and W rights
my ($r, $w); $r = ''; $w = '';
if ($user and -f "$ENV{GL_REPO_BASE_ABS}/$repo.git/gl-perms") {
my $fh = wrap_open("<", "$ENV{GL_REPO_BASE_ABS}/$repo.git/gl-perms");
my $perms = join ("", <$fh>);
# $perms is say "R alice @foo @bar\nRW bob @baz" (the entire gl-perms
# file). We replace each @foo with $user if $cached_groups{'@foo'}{$user}
# exists (i.e., $user is a member of @foo)
for my $g ($perms =~ /\s(\@\S+)/g) {
$perms =~ s/ $g(?!\S)/ $user/ if $cached_groups{$g}{$user};
}
if ($perms) {
$r = $user if $perms =~ /^\s*R(?=\s).*\s(\@all|$user)(\s|$)/m;
$w = $user if $perms =~ /^\s*RW(?=\s).*\s(\@all|$user)(\s|$)/m;
}
}
return ($c, $r, $w);
}
}
# ----------------------------------------------------------------------------

View file

@ -393,7 +393,7 @@ $dumped_data .= Data::Dumper->Dump([\%repo_config], [qw(*repo_config)]) if %repo
# much...
$dumped_data =~ s/'(?=[^']*\$(?:creator|readers|writers|gl_user))~?(.*?)'/"$1"/g;
print $compiled_fh $dumped_data;
if ($GL_BIG_CONFIG and %groups) {
if (%groups) {
$dumped_data = Data::Dumper->Dump([\%groups], [qw(*groups)]);
$dumped_data =~ s/\bCREAT[EO]R\b/\$creator/g;
$dumped_data =~ s/'(?=[^']*\$(?:creator|readers|writers|gl_user))~?(.*?)'/"$1"/g;

105
t/out/t01-repo-groups.1b Normal file
View file

@ -0,0 +1,105 @@
$data_version = '1.5';
%repos = (
'aa' => {
'R' => {
'u1' => 1,
'u2' => 1,
'u3' => 1
},
'W' => {
'u1' => 1,
'u2' => 1,
'u3' => 1
},
'u1' => [
[
2,
'refs/.*',
'RW+'
]
],
'u2' => [
[
4,
'refs/.*',
'RW'
]
],
'u3' => [
[
5,
'refs/.*',
'RW'
]
]
},
'bb' => {
'R' => {
'u1' => 1,
'u2' => 1,
'u3' => 1
},
'W' => {
'u1' => 1,
'u2' => 1,
'u3' => 1
},
'u1' => [
[
3,
'refs/.*',
'RW+'
]
],
'u2' => [
[
6,
'refs/.*',
'RW'
]
],
'u3' => [
[
7,
'refs/.*',
'RW'
]
]
},
'gitolite-admin' => {
'R' => {
'tester' => 1
},
'W' => {
'tester' => 1
},
'tester' => [
[
0,
'refs/.*',
'RW+'
]
]
},
'testing' => {
'@all' => [
[
1,
'refs/.*',
'RW+'
]
],
'R' => {
'@all' => 1
},
'W' => {
'@all' => 1
}
}
);
%groups = (
'@g1' => {
'aa' => 'master',
'bb' => 'master'
}
);

80
t/out/t02-user-groups.1b Normal file
View file

@ -0,0 +1,80 @@
$data_version = '1.5';
%repos = (
'aa' => {
'R' => {
'u1' => 1,
'u2' => 1,
'u3' => 1
},
'W' => {
'u1' => 1,
'u2' => 1,
'u3' => 1
},
'u1' => [
[
2,
'refs/.*',
'RW+'
]
],
'u2' => [
[
3,
'refs/.*',
'RW'
]
],
'u3' => [
[
4,
'refs/.*',
'RW'
]
]
},
'gitolite-admin' => {
'R' => {
'tester' => 1
},
'W' => {
'tester' => 1
},
'tester' => [
[
0,
'refs/.*',
'RW+'
]
]
},
'testing' => {
'@all' => [
[
1,
'refs/.*',
'RW+'
]
],
'R' => {
'@all' => 1
},
'W' => {
'@all' => 1
}
}
);
%groups = (
'@g1' => {
'u1' => 'master'
},
'@g2' => {
'u2' => 'master',
'u3' => 'master'
},
'@g3' => {
'u4' => 'master',
'u5' => 'master',
'u6' => 'master'
}
);

View file

@ -26,7 +26,7 @@ echo "
" | ugc
catconf
expect_filesame $TESTDIR/out/t01-repo-groups.1
expect_filesame $TESTDIR/out/t01-repo-groups.1b
# ----------
$TESTDIR/rollback || die "rollback failed"

View file

@ -29,7 +29,7 @@ echo "
" | ugc
catconf
expect_filesame $TESTDIR/out/t02-user-groups.1
expect_filesame $TESTDIR/out/t02-user-groups.1b
# ----------
$TESTDIR/rollback || die "rollback failed"

72
t/t61-setperms-wild Normal file
View file

@ -0,0 +1,72 @@
# vim: syn=sh:
for bc in 0 1
do
cd $TESTDIR
$TESTDIR/rollback || die "rollback failed"
editrc GL_WILDREPOS 1
editrc GL_BIG_CONFIG $bc
name "INTERNAL"
echo "
@leads = u1 u2
@devs = u1 u2 u3 u4
@gbar = bar/CREATOR/..*
repo @gbar
C = @leads
RW+ = CREATOR
RW = WRITERS
R = READERS
" | ugc
name "nothing set yet"
expect_push_ok "master -> master"
name "u1 auto-creates a repo"
runlocal git ls-remote u1:bar/u1/try1
expect "Initialized empty Git repository in /home/gitolite-test/repositories/bar/u1/try1.git/"
name "default permissions for u2 and u4"
runlocal ssh u1 expand
expect R.*W.*u1.*bar/u1/try1
runlocal ssh u2 expand
notexpect R.*W.*u1.*bar/u1/try1
runlocal ssh u4 expand
notexpect R.*W.*u1.*bar/u1/try1
name "@leads can RW try1"
echo RW @leads | runlocal ssh u1 setperms bar/u1/try1
expect "RW @leads"
runlocal ssh u1 expand
expect R.*W.*u1.*bar/u1/try1
runlocal ssh u2 expand
expect R.*W.*u1.*bar/u1/try1
runlocal ssh u4 expand
notexpect R.*W.*u1.*bar/u1/try1
name "@devs can R try1"
echo R @devs | runlocal ssh u1 setperms bar/u1/try1
expect "R @devs"
notexpect "RW @leads"
runlocal ssh u1 expand
expect R.*W.*u1.*bar/u1/try1
runlocal ssh u2 expand
notexpect R.*W.*u1.*bar/u1/try1
expect R.*u1.*bar/u1/try1
runlocal ssh u4 expand
notexpect R.*W.*u1.*bar/u1/try1
expect R.*u1.*bar/u1/try1
name "combo of previous 2"
printf "R @devs\nRW @leads\n" | runlocal ssh u1 setperms bar/u1/try1
expect "R @devs"
expect "RW @leads"
runlocal ssh u1 expand
expect R.*W.*u1.*bar/u1/try1
runlocal ssh u2 expand
expect R.*W.*u1.*bar/u1/try1
runlocal ssh u4 expand
notexpect R.*W.*u1.*bar/u1/try1
expect R.*u1.*bar/u1/try1
name "INTERNAL"
done