2012-03-10 15:13:42 +01:00
|
|
|
# and now for something completely different...
|
|
|
|
|
|
|
|
package SugarBox;
|
|
|
|
|
|
|
|
sub run_sugar_script {
|
2012-03-12 16:24:30 +01:00
|
|
|
my ( $ss, $lref ) = @_;
|
2012-03-10 15:13:42 +01:00
|
|
|
do $ss if -x $ss;
|
|
|
|
$lref = sugar_script($lref);
|
|
|
|
return $lref;
|
|
|
|
}
|
|
|
|
|
|
|
|
# ----------------------------------------------------------------------
|
|
|
|
|
2012-03-08 09:00:13 +01:00
|
|
|
package Gitolite::Conf::Sugar;
|
|
|
|
|
|
|
|
# syntactic sugar for the conf file, including site-local macros
|
|
|
|
# ----------------------------------------------------------------------
|
|
|
|
|
|
|
|
@EXPORT = qw(
|
2012-03-09 16:53:16 +01:00
|
|
|
sugar
|
2012-03-08 09:00:13 +01:00
|
|
|
);
|
|
|
|
|
|
|
|
use Exporter 'import';
|
|
|
|
|
|
|
|
use Gitolite::Rc;
|
2012-03-09 16:53:16 +01:00
|
|
|
use Gitolite::Common;
|
|
|
|
use Gitolite::Conf::Explode;
|
2012-03-08 09:00:13 +01:00
|
|
|
|
|
|
|
use strict;
|
|
|
|
use warnings;
|
|
|
|
|
|
|
|
# ----------------------------------------------------------------------
|
|
|
|
|
2012-03-09 16:53:16 +01:00
|
|
|
sub sugar {
|
|
|
|
# gets a filename, returns a listref
|
2012-03-08 09:00:13 +01:00
|
|
|
|
2012-03-09 16:53:16 +01:00
|
|
|
my @lines = ();
|
2012-03-12 16:24:30 +01:00
|
|
|
explode( shift, 'master', \@lines );
|
2012-03-08 09:00:13 +01:00
|
|
|
|
2012-03-09 16:53:16 +01:00
|
|
|
my $lines;
|
|
|
|
$lines = \@lines;
|
2012-03-08 09:00:13 +01:00
|
|
|
|
2012-03-09 16:53:16 +01:00
|
|
|
# run through the sugar stack one by one
|
|
|
|
|
|
|
|
# first, user supplied sugar:
|
2012-03-12 16:24:30 +01:00
|
|
|
if ( exists $rc{SYNTACTIC_SUGAR} ) {
|
|
|
|
if ( ref( $rc{SYNTACTIC_SUGAR} ) ne 'ARRAY' ) {
|
2012-03-09 16:53:16 +01:00
|
|
|
_warn "bad syntax for specifying sugar scripts; see docs";
|
|
|
|
} else {
|
2012-03-12 16:24:30 +01:00
|
|
|
for my $s ( @{ $rc{SYNTACTIC_SUGAR} } ) {
|
2012-03-10 15:13:42 +01:00
|
|
|
|
|
|
|
# perl-ism; apart from keeping the full path separate from the
|
|
|
|
# simple name, this also protects %rc from change by implicit
|
|
|
|
# aliasing, which would happen if you touched $s itself
|
|
|
|
my $sfp = "$ENV{GL_BINDIR}/syntactic-sugar/$s";
|
|
|
|
|
|
|
|
_warn("skipped sugar script '$s'"), next if not -x $sfp;
|
2012-03-12 16:24:30 +01:00
|
|
|
$lines = SugarBox::run_sugar_script( $sfp, $lines );
|
2012-03-09 16:53:16 +01:00
|
|
|
$lines = [ grep /\S/, map { cleanup_conf_line($_) } @$lines ];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-03-08 09:00:13 +01:00
|
|
|
|
2012-03-09 16:53:16 +01:00
|
|
|
# then our stuff:
|
2012-03-08 09:00:13 +01:00
|
|
|
|
2012-03-17 18:00:02 +01:00
|
|
|
$lines = rw_cdm($lines);
|
|
|
|
$lines = option($lines); # must come after rw_cdm
|
2012-03-09 16:53:16 +01:00
|
|
|
$lines = owner_desc($lines);
|
2012-03-11 03:06:42 +01:00
|
|
|
$lines = name_vref($lines);
|
wildrepos almost done (except setperms etc)
implementation notes
- new sugar role_names() to prefix an "@" to CREATOR, and any role
names listed in the rc file.
- invalidate the cache in rules() if the repo was missing. Without
this, an auto-create operation succeeds the ^C check and calls
new_wild_repo(), but then -- due to the cached rules not containing
a rule for CREATOR, the actual read/write fails.
- treat roles (READERS, WRITERS, etc.) as group names that apply only
to that particular repo. Don't add them to %groups, because that
would screw up caching, but add them in when memberships() is called
for the user.
This is why the membership call for the user also has a reponame
tacked on -- i.e., a user's membership list varied depending on
which repo you're talking about.
- while we're about it, pretend we added "CREATOR = <content of
gl-creator>" as another "role". Makes things so much easier dealing
with "RW+ = CREATOR"
- searching for rules pertaining to foo/CREATOR/bar when looking at
repo foo/sitaram/bar is done backwards from what g2 used to do. G2
used to play tricks with the do-eval'd file using global variables
so that what you get after the do may not even contain 'CREATOR'.
We go the other way. We replace sitaram with CREATOR and start
looking for memberships of *both* foo/sitaram/bar and
foo/CREATOR/bar.
- this doesn't work (because we don't know *what* to replace) for
missing repos if GL_USER is not set. This means that 'gitolite
access ...' queries (which do not set GL_USER) cannot be used
reliably for non-existant repos.
Since a ^C check is the only meaningful one for a non-existent repo,
this means you cannot do that from 'gitolite access'.
'GL_USER=luser gitolite info' will still work though ;-)
all in all, much cleaner and simpler than g2.
2012-03-18 02:14:02 +01:00
|
|
|
$lines = role_names($lines);
|
2012-03-08 09:00:13 +01:00
|
|
|
|
2012-03-09 16:53:16 +01:00
|
|
|
return $lines;
|
2012-03-08 09:00:13 +01:00
|
|
|
}
|
|
|
|
|
2012-03-17 18:00:02 +01:00
|
|
|
sub rw_cdm {
|
|
|
|
my $lines = shift;
|
|
|
|
my @ret;
|
|
|
|
|
|
|
|
# repo foo <...> RWC = ...
|
|
|
|
# -> option CREATE_IS_C = 1
|
|
|
|
# (and similarly DELETE_IS_D and MERGE_CHECK)
|
|
|
|
# but only once per repo of course
|
|
|
|
|
|
|
|
my %seen = ();
|
|
|
|
for my $line (@$lines) {
|
|
|
|
push @ret, $line;
|
|
|
|
if ( $line =~ /^repo / ) {
|
|
|
|
%seen = ();
|
|
|
|
} elsif ( $line =~ /^(-|C|R|RW\+?(?:C?D?|D?C?)M?) (.* )?= (.+)/ ) {
|
|
|
|
my $perms = $1;
|
|
|
|
push @ret, "option DELETE_IS_D = 1" if $perms =~ /D/ and not $seen{D}++;
|
|
|
|
push @ret, "option CREATE_IS_C = 1" if $perms =~ /RW.*C/ and not $seen{C}++;
|
|
|
|
push @ret, "option MERGE_CHECK = 1" if $perms =~ /M/ and not $seen{M}++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return \@ret;
|
|
|
|
}
|
|
|
|
|
2012-03-10 09:26:02 +01:00
|
|
|
sub option {
|
|
|
|
my $lines = shift;
|
|
|
|
my @ret;
|
|
|
|
|
|
|
|
# option foo = bar
|
|
|
|
# -> config gitolite-options.foo = bar
|
|
|
|
|
|
|
|
for my $line (@$lines) {
|
|
|
|
if ( $line =~ /^option (\S+) = (\S.*)/ ) {
|
|
|
|
push @ret, "config gitolite-options.$1 = $2";
|
|
|
|
} else {
|
|
|
|
push @ret, $line;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return \@ret;
|
|
|
|
}
|
|
|
|
|
2012-03-08 09:00:13 +01:00
|
|
|
sub owner_desc {
|
2012-03-09 16:53:16 +01:00
|
|
|
my $lines = shift;
|
2012-03-08 09:00:13 +01:00
|
|
|
my @ret;
|
|
|
|
|
2012-03-09 16:53:16 +01:00
|
|
|
# owner = "owner name"
|
|
|
|
# -> config gitweb.owner = owner name
|
|
|
|
# description = "some long description"
|
|
|
|
# -> config gitweb.description = some long description
|
|
|
|
# category = "whatever..."
|
|
|
|
# -> config gitweb.category = whatever...
|
|
|
|
|
|
|
|
# older formats:
|
|
|
|
# repo = "some long description"
|
|
|
|
# repo = "owner name" = "some long description"
|
|
|
|
# -> config gitweb.owner = owner name
|
|
|
|
# -> config gitweb.description = some long description
|
|
|
|
|
|
|
|
for my $line (@$lines) {
|
2012-03-08 09:00:13 +01:00
|
|
|
if ( $line =~ /^(\S+)(?: "(.*?)")? = "(.*)"$/ ) {
|
|
|
|
my ( $repo, $owner, $desc ) = ( $1, $2, $3 );
|
2012-03-09 16:53:16 +01:00
|
|
|
push @ret, "repo $repo";
|
|
|
|
push @ret, "config gitweb.description = $desc";
|
|
|
|
push @ret, "config gitweb.owner = $owner" if $owner;
|
2012-03-08 09:00:13 +01:00
|
|
|
} elsif ( $line =~ /^desc = (\S.*)/ ) {
|
2012-03-09 16:53:16 +01:00
|
|
|
push @ret, "config gitweb.description = $1";
|
2012-03-08 09:00:13 +01:00
|
|
|
} elsif ( $line =~ /^owner = (\S.*)/ ) {
|
2012-03-09 16:53:16 +01:00
|
|
|
push @ret, "config gitweb.owner = $1";
|
|
|
|
} elsif ( $line =~ /^category = (\S.*)/ ) {
|
|
|
|
push @ret, "config gitweb.category = $1";
|
2012-03-08 09:00:13 +01:00
|
|
|
} else {
|
|
|
|
push @ret, $line;
|
|
|
|
}
|
|
|
|
}
|
2012-03-09 16:53:16 +01:00
|
|
|
return \@ret;
|
2012-03-08 09:00:13 +01:00
|
|
|
}
|
|
|
|
|
2012-03-11 03:06:42 +01:00
|
|
|
sub name_vref {
|
|
|
|
my $lines = shift;
|
|
|
|
my @ret;
|
|
|
|
|
|
|
|
# <perm> NAME/foo = <user>
|
|
|
|
# -> <perm> VREF/NAME/foo = <user>
|
|
|
|
|
|
|
|
for my $line (@$lines) {
|
|
|
|
if ( $line =~ /^(-|R\S+) \S.* = \S.*/ ) {
|
|
|
|
$line =~ s( NAME/)( VREF/NAME/)g;
|
|
|
|
}
|
|
|
|
push @ret, $line;
|
|
|
|
}
|
|
|
|
return \@ret;
|
|
|
|
}
|
|
|
|
|
wildrepos almost done (except setperms etc)
implementation notes
- new sugar role_names() to prefix an "@" to CREATOR, and any role
names listed in the rc file.
- invalidate the cache in rules() if the repo was missing. Without
this, an auto-create operation succeeds the ^C check and calls
new_wild_repo(), but then -- due to the cached rules not containing
a rule for CREATOR, the actual read/write fails.
- treat roles (READERS, WRITERS, etc.) as group names that apply only
to that particular repo. Don't add them to %groups, because that
would screw up caching, but add them in when memberships() is called
for the user.
This is why the membership call for the user also has a reponame
tacked on -- i.e., a user's membership list varied depending on
which repo you're talking about.
- while we're about it, pretend we added "CREATOR = <content of
gl-creator>" as another "role". Makes things so much easier dealing
with "RW+ = CREATOR"
- searching for rules pertaining to foo/CREATOR/bar when looking at
repo foo/sitaram/bar is done backwards from what g2 used to do. G2
used to play tricks with the do-eval'd file using global variables
so that what you get after the do may not even contain 'CREATOR'.
We go the other way. We replace sitaram with CREATOR and start
looking for memberships of *both* foo/sitaram/bar and
foo/CREATOR/bar.
- this doesn't work (because we don't know *what* to replace) for
missing repos if GL_USER is not set. This means that 'gitolite
access ...' queries (which do not set GL_USER) cannot be used
reliably for non-existant repos.
Since a ^C check is the only meaningful one for a non-existent repo,
this means you cannot do that from 'gitolite access'.
'GL_USER=luser gitolite info' will still work though ;-)
all in all, much cleaner and simpler than g2.
2012-03-18 02:14:02 +01:00
|
|
|
sub role_names {
|
|
|
|
my $lines = shift;
|
|
|
|
my @ret;
|
|
|
|
|
|
|
|
# <perm> [<ref>] = <user list containing CREATOR|READERS|WRITERS>
|
|
|
|
# -> same but with "@" prepended to rolenames
|
|
|
|
|
|
|
|
for my $line (@$lines) {
|
|
|
|
if ( $line =~ /^(-|C|R|RW\+?(?:C?D?|D?C?)M?) (.* )?= (.+)/ ) {
|
2012-03-19 03:19:01 +01:00
|
|
|
my ( $p, $r ) = ( $1, $2 );
|
wildrepos almost done (except setperms etc)
implementation notes
- new sugar role_names() to prefix an "@" to CREATOR, and any role
names listed in the rc file.
- invalidate the cache in rules() if the repo was missing. Without
this, an auto-create operation succeeds the ^C check and calls
new_wild_repo(), but then -- due to the cached rules not containing
a rule for CREATOR, the actual read/write fails.
- treat roles (READERS, WRITERS, etc.) as group names that apply only
to that particular repo. Don't add them to %groups, because that
would screw up caching, but add them in when memberships() is called
for the user.
This is why the membership call for the user also has a reponame
tacked on -- i.e., a user's membership list varied depending on
which repo you're talking about.
- while we're about it, pretend we added "CREATOR = <content of
gl-creator>" as another "role". Makes things so much easier dealing
with "RW+ = CREATOR"
- searching for rules pertaining to foo/CREATOR/bar when looking at
repo foo/sitaram/bar is done backwards from what g2 used to do. G2
used to play tricks with the do-eval'd file using global variables
so that what you get after the do may not even contain 'CREATOR'.
We go the other way. We replace sitaram with CREATOR and start
looking for memberships of *both* foo/sitaram/bar and
foo/CREATOR/bar.
- this doesn't work (because we don't know *what* to replace) for
missing repos if GL_USER is not set. This means that 'gitolite
access ...' queries (which do not set GL_USER) cannot be used
reliably for non-existant repos.
Since a ^C check is the only meaningful one for a non-existent repo,
this means you cannot do that from 'gitolite access'.
'GL_USER=luser gitolite info' will still work though ;-)
all in all, much cleaner and simpler than g2.
2012-03-18 02:14:02 +01:00
|
|
|
my $u = '';
|
2012-03-19 03:19:01 +01:00
|
|
|
for ( split ' ', $3 ) {
|
wildrepos almost done (except setperms etc)
implementation notes
- new sugar role_names() to prefix an "@" to CREATOR, and any role
names listed in the rc file.
- invalidate the cache in rules() if the repo was missing. Without
this, an auto-create operation succeeds the ^C check and calls
new_wild_repo(), but then -- due to the cached rules not containing
a rule for CREATOR, the actual read/write fails.
- treat roles (READERS, WRITERS, etc.) as group names that apply only
to that particular repo. Don't add them to %groups, because that
would screw up caching, but add them in when memberships() is called
for the user.
This is why the membership call for the user also has a reponame
tacked on -- i.e., a user's membership list varied depending on
which repo you're talking about.
- while we're about it, pretend we added "CREATOR = <content of
gl-creator>" as another "role". Makes things so much easier dealing
with "RW+ = CREATOR"
- searching for rules pertaining to foo/CREATOR/bar when looking at
repo foo/sitaram/bar is done backwards from what g2 used to do. G2
used to play tricks with the do-eval'd file using global variables
so that what you get after the do may not even contain 'CREATOR'.
We go the other way. We replace sitaram with CREATOR and start
looking for memberships of *both* foo/sitaram/bar and
foo/CREATOR/bar.
- this doesn't work (because we don't know *what* to replace) for
missing repos if GL_USER is not set. This means that 'gitolite
access ...' queries (which do not set GL_USER) cannot be used
reliably for non-existant repos.
Since a ^C check is the only meaningful one for a non-existent repo,
this means you cannot do that from 'gitolite access'.
'GL_USER=luser gitolite info' will still work though ;-)
all in all, much cleaner and simpler than g2.
2012-03-18 02:14:02 +01:00
|
|
|
$_ = "\@$_" if $_ eq 'CREATOR' or $rc{ROLES}{$_};
|
|
|
|
$u .= " $_";
|
|
|
|
}
|
|
|
|
$r ||= '';
|
|
|
|
# mind the spaces (or play safe and run cleanup_conf_line again)
|
|
|
|
push @ret, cleanup_conf_line("$p $r = $u");
|
|
|
|
} else {
|
|
|
|
push @ret, $line;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return \@ret;
|
|
|
|
}
|
|
|
|
|
2012-03-08 09:00:13 +01:00
|
|
|
1;
|
|
|
|
|