%HOSTNAME and new subconf enhancement

This commit is contained in:
Sitaram Chamarty 2012-03-30 18:00:02 +05:30
parent 0dfabe9f45
commit 2c1f46c055
7 changed files with 183 additions and 16 deletions

View file

@ -78,3 +78,55 @@ is effectively the same as this, for repo foo:
R = gitweb R = gitweb
This extends to patterns also, but I'll leave an example for later. This extends to patterns also, but I'll leave an example for later.
## #subconf the subconf command
This is just like the include command:
subconf "foo/bar.conf" # example 1
subconf "foo/*.conf" # example 2
with the difference that, for the duration of the file(s) being included, a
subconf restriction is in effect. This restrictions limits the repos that can
be access controlled by the lines within the included file(s).
Here's how it works. First, a subconf *name* is derived from the filename
being included, which is basically the basename of the file. For example 1
that is "bar". For example 2, assuming foo contains "a.conf" and "b.conf",
the subconf name is "a" while processing "a.conf", and "b" while processing
"b.conf".
A variation of the subconf command allows you to specify the subconf *name*
explicitly, while including files as before:
subconf frob "foo/bar.conf # example 3
subconf frob "foo/*.conf # example 4
In this case the subconf name is "frob" in both cases.
A subconf restricts the repos that can be named in 'repo' lines while the
subconf is in effect. If the subconf name is "foo", the conf lines parsed
while under the subconf restriction can only refer to
* a repo called 'foo'
* a repo group called '@foo'
* the members of the same repo group '@foo'
* match a regex that is a member of the repo group '@foo'
In the last 3 cases, the repo group '@foo' must be defined in the main conf
file (i.e., outside the subconf restriction).
For example, if you have this in the main conf file:
@foo = bar baz frob/..*
subconf "foo.conf"
then foo.conf can only refer to 'foo', '@foo', 'bar', 'baz', or any repo name
matching the pattern `frob/..*`.
## #HOSTNAME HOSTNAME substitution
Wherever gitolite sees the word `%HOSTNAME`, it will replace it with the
HOSTNAME supplied in the rc file, if one was supplied. This is mainly useful
in [mirroring][].

View file

@ -9,6 +9,7 @@ package Gitolite::Conf::Explode;
use Exporter 'import'; use Exporter 'import';
use Gitolite::Rc;
use Gitolite::Common; use Gitolite::Common;
use strict; use strict;
@ -33,10 +34,13 @@ sub explode {
my $line = cleanup_conf_line($_); my $line = cleanup_conf_line($_);
next unless $line =~ /\S/; next unless $line =~ /\S/;
# subst %HOSTNAME word if rc defines a hostname, else leave as is
$line =~ s/%HOSTNAME\b/$rc{HOSTNAME}/g if $rc{HOSTNAME};
$line = prefix_groupnames( $line, $subconf ) if $subconf ne 'master'; $line = prefix_groupnames( $line, $subconf ) if $subconf ne 'master';
if ( $line =~ /^(include|subconf) (\S.+)$/ ) { if ( $line =~ /^(include|subconf) (?:(\S+) )?(\S.+)$/ ) {
incsub( $1, $2, $subconf, $out ); incsub( $1, $2, $3, $subconf, $out );
} else { } else {
# normal line, send it to the callback function # normal line, send it to the callback function
push @{$out}, $line; push @{$out}, $line;
@ -46,9 +50,9 @@ sub explode {
sub incsub { sub incsub {
my $is_subconf = ( +shift eq 'subconf' ); my $is_subconf = ( +shift eq 'subconf' );
my ( $include_glob, $subconf, $out ) = @_; my ( $new_subconf, $include_glob, $current_subconf, $out ) = @_;
_die "subconf $subconf attempting to run 'subconf'\n" if $is_subconf and $subconf ne 'master'; _die "subconf $current_subconf attempting to run 'subconf'\n" if $is_subconf and $current_subconf ne 'master';
_die "invalid include/subconf file/glob '$include_glob'" _die "invalid include/subconf file/glob '$include_glob'"
unless $include_glob =~ /^"(.+)"$/ unless $include_glob =~ /^"(.+)"$/
@ -65,11 +69,11 @@ sub incsub {
next if already_included($file); next if already_included($file);
if ($is_subconf) { if ($is_subconf) {
push @{$out}, "subconf $basename"; push @{$out}, "subconf " . ( $new_subconf || $basename );
explode( $file, $basename, $out ); explode( $file, ( $new_subconf || $basename ), $out );
push @{$out}, "subconf $subconf"; push @{$out}, "subconf $current_subconf";
} else { } else {
explode( $file, $subconf, $out ); explode( $file, $current_subconf, $out );
} }
} }
} }

View file

@ -218,7 +218,7 @@ sub store {
sub parse_done { sub parse_done {
for my $ig ( sort keys %ignored ) { for my $ig ( sort keys %ignored ) {
_warn "$ig.conf attempting to set access for " . join( ", ", sort keys %{ $ignored{$ig} } ); _warn "subconf '$ig' attempting to set access for " . join( ", ", sort keys %{ $ignored{$ig} } );
} }
} }

View file

@ -81,7 +81,7 @@ put "conf/fragments/u3r.conf", '
RW+ = u6 RW+ = u6
'; ';
try "SUBCONF_PUSH u3 u3; try "SUBCONF_PUSH u3 u3;
/WARNING: u3r.conf attempting to set access for r2a/ /WARNING: subconf 'u3r' attempting to set access for r2a/
"; ";
try "git reset --hard origin/master; ok"; try "git reset --hard origin/master; ok";
@ -95,5 +95,5 @@ put "conf/fragments/u3r.conf", '
'; ';
try "SUBCONF_PUSH u3 u3 try "SUBCONF_PUSH u3 u3
/WARNING: u3r.conf attempting to set access for locally modified \@u3r/ /WARNING: subconf 'u3r' attempting to set access for locally modified \@u3r/
"; ";

View file

@ -103,7 +103,7 @@ put "conf/fragments/u3r.conf", '
RW+ = u6 RW+ = u6
'; ';
try "SUBCONF_PUSH u3 u3; try "SUBCONF_PUSH u3 u3;
/WARNING: u3r.conf attempting to set access for r2a/ /WARNING: subconf 'u3r' attempting to set access for r2a/
"; ";
try "git reset --hard origin/master; ok"; try "git reset --hard origin/master; ok";
@ -117,5 +117,5 @@ put "conf/fragments/u3r.conf", '
'; ';
try "SUBCONF_PUSH u3 u3 try "SUBCONF_PUSH u3 u3
/WARNING: u3r.conf attempting to set access for locally modified \@u3r/ /WARNING: subconf 'u3r' attempting to set access for locally modified \@u3r/
"; ";

77
t/hostname.t Executable file
View file

@ -0,0 +1,77 @@
#!/usr/bin/perl
use strict;
use warnings;
# this is hardcoded; change it if needed
use lib "src";
use Gitolite::Test;
# %HOSTNAME tests
# ----------------------------------------------------------------------
try "plan 60";
try "pwd";
my $od = text();
chomp($od);
# without setting HOSTNAME in rc
confreset;confadd '
repo foo
RW dev/%HOSTNAME = u1
';
try "ADMIN_PUSH set1; /FATAL/";
try "/bad ref 'refs/heads/dev/%HOSTNAME'/";
# make a hostname entry
$ENV{G3T_RC} = "$ENV{HOME}/g3trc";
put "$ENV{G3T_RC}", "\$rc{HOSTNAME} = 'frodo';\n";
confreset;confadd '
repo bar
RW %HOSTNAME_baz = u1
';
try "ADMIN_PUSH set1; /FATAL/";
try "/bad ref 'refs/heads/%HOSTNAME_baz'/";
confreset;confadd '
repo bar
RW %HOSTNAME/ = u1
RW %HOSTNAME-baz = u1
';
try "ADMIN_PUSH set1; !/FATAL/";
try "
gitolite access bar u2 R any; /R any bar u2 DENIED by fallthru/
gitolite access bar u2 W any; /W any bar u2 DENIED by fallthru/
gitolite access bar u1 W any; !/DENIED/; /refs/heads/frodo/; !/baz/
gitolite access bar u1 R any; !/DENIED/; /refs/heads/frodo/; !/baz/
gitolite access bar u1 R refs/heads/frodo; /R refs/heads/frodo bar u1 DENIED by fallthru/
gitolite access bar u1 W refs/heads/frodo; /W refs/heads/frodo bar u1 DENIED by fallthru/
gitolite access bar u1 R refs/heads/frodo/1; !/DENIED/; /refs/heads/frodo/; !/baz/
gitolite access bar u1 W refs/heads/frodo/1; !/DENIED/; /refs/heads/frodo/; !/baz/
gitolite access bar u1 R refs/heads/sam; /R refs/heads/sam bar u1 DENIED by fallthru/
gitolite access bar u1 W refs/heads/sam; /W refs/heads/sam bar u1 DENIED by fallthru/
gitolite access bar u1 R refs/heads/master; /R refs/heads/master bar u1 DENIED by fallthru/
gitolite access bar u1 W refs/heads/master; /W refs/heads/master bar u1 DENIED by fallthru/
gitolite access bar u1 R refs/heads/frodo-baz; !/DENIED/; /refs/heads/frodo-baz/
gitolite access bar u1 W refs/heads/frodo-baz; !/DENIED/; /refs/heads/frodo-baz/
";
confreset;confadd '
repo foo-%HOSTNAME
RW = u1
';
try "ADMIN_PUSH set1; !/FATAL/";
try "
gitolite list-repos; /foo-frodo/
gitolite list-phy-repos; /foo-frodo/
";

View file

@ -9,7 +9,7 @@ use Gitolite::Test;
# include and subconf # include and subconf
# ---------------------------------------------------------------------- # ----------------------------------------------------------------------
try 'plan 37'; try 'plan 55';
confreset; confadd ' confreset; confadd '
include "i1.conf" include "i1.conf"
@ -39,7 +39,7 @@ try "ADMIN_PUSH set2; !/FATAL/" or die text();
try " try "
/i1.conf already included/ /i1.conf already included/
/i2.conf attempting to set access for \@i1, b2, bar, i1, locally modified \@g2/ /subconf 'i2' attempting to set access for \@i1, b2, bar, i1, locally modified \@g2/
!/attempting to set access.*i2/ !/attempting to set access.*i2/
/Initialized.*empty.*baz.git/ /Initialized.*empty.*baz.git/
/Initialized.*empty.*foo.git/ /Initialized.*empty.*foo.git/
@ -62,7 +62,7 @@ confadd 'g2.conf', '
try "ADMIN_PUSH set3; !/FATAL/" or die text(); try "ADMIN_PUSH set3; !/FATAL/" or die text();
try " try "
/g2.conf attempting to set access for locally modified \@g2/ /subconf 'g2' attempting to set access for locally modified \@g2/
!/Initialized.*empty/ !/Initialized.*empty/
"; ";
@ -80,3 +80,37 @@ confadd 'g2.conf', '
try " try "
ADMIN_PUSH set3; ok; /FATAL: subconf g2 attempting to run 'subconf'/ ADMIN_PUSH set3; ok; /FATAL: subconf g2 attempting to run 'subconf'/
"; ";
# ----------------------------------------------------------------------
confreset; confadd '
include "i1.conf"
@i2 = b1
subconf i2 "eye2.conf"
';
confadd 'eye2.conf', '
repo @eye2
RW = u2
';
try "ADMIN_PUSH set2; !/FATAL/" or die text();
try "
/subconf 'i2' attempting to set access for \@eye2/
";
confreset; confadd '
include "i1.conf"
@i2 = b1
subconf i2 "eye2.conf"
';
confadd 'eye2.conf', '
repo @i2
RW = u2
';
try "ADMIN_PUSH set2; !/FATAL/" or die text();
try "
!/subconf 'i2' attempting to set access for \@eye2/
";