logical expressions on refexes :-)
This commit is contained in:
parent
af437c3a7b
commit
db2cf23379
73
src/VREF/refex-expr
Executable file
73
src/VREF/refex-expr
Executable file
|
@ -0,0 +1,73 @@
|
|||
#!/usr/bin/perl
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
my $rule = $ARGV[7];
|
||||
my $res = $ENV{"GL_REFEX_EXPR_" . $rule} || 0;
|
||||
print "$ARGV[6] ($res)\n" if $res;
|
||||
|
||||
exit 0;
|
||||
|
||||
__END__
|
||||
|
||||
Documentation for the refex-expression evaluation feature
|
||||
|
||||
First, make sure you have both the VREF and the trigger scripts
|
||||
(src/VREF/refex-expr and src/lib/Gitolite/Triggers/RefexExpr.pm)
|
||||
|
||||
Next, add this to the ACCESS_2 list in the rc file:
|
||||
|
||||
'RefexExpr::access_2',
|
||||
|
||||
For the rest, we'll use this example:
|
||||
|
||||
* user u1 can push foo to some other branch, and anything else to the master
|
||||
branch, but not foo to the master branch
|
||||
|
||||
* user u2 is allowed to push either 'doc/' or 'src/' but not both
|
||||
|
||||
Here's the conf file extract:
|
||||
|
||||
repo testing
|
||||
RW+ master = u1 # line 1
|
||||
RW+ = @all # line 2
|
||||
|
||||
RW+ VREF/NAME/foo = u1
|
||||
RW+ VREF/NAME/doc/ = u2
|
||||
RW+ VREF/NAME/src/ = u2
|
||||
|
||||
# set up 2 refex expressions, named e1, e2
|
||||
option refex-expr.e1 = master and VREF/NAME/foo
|
||||
option refex-expr.e2 = VREF/NAME/doc/ and VREF/NAME/src/
|
||||
|
||||
# now deny users if the corresponding expression is true
|
||||
- VREF/refex-expr/e1 = u1
|
||||
- VREF/refex-expr/e2 = u2
|
||||
|
||||
Here are some IMPORTANT notes:
|
||||
|
||||
* You MUST place VREF/refex-expr rules at the end. (Only 'partial-copy', if
|
||||
you use it, must come later).
|
||||
|
||||
* You MUST explicitly permit the refexes used in your refex expressions. If
|
||||
you have more generic rules, the specific ones must come first.
|
||||
|
||||
For example, without line 1, the refex recorded for user u1 will come from
|
||||
line 2, (so it will be 'refs/.*'), and 'master' in the refex expressions
|
||||
will never have a true value.
|
||||
|
||||
* (corollary) make sure you use the exact same refex in the expression as
|
||||
you did on the original rule line. E.g., a missing slash at the end will
|
||||
mess things up.
|
||||
|
||||
* You can use any logical expression using refexes as operands and using
|
||||
these operators:
|
||||
|
||||
and not xor or
|
||||
|
||||
Parens are not allowed.
|
||||
|
||||
If a refex has passed, it will have a 'true' value, else it will be false.
|
||||
|
||||
The result of the evaluation, after these substitutions, will be the
|
||||
result of the refex-expr VREF.
|
80
src/lib/Gitolite/Triggers/RefexExpr.pm
Normal file
80
src/lib/Gitolite/Triggers/RefexExpr.pm
Normal file
|
@ -0,0 +1,80 @@
|
|||
package Gitolite::Triggers::RefexExpr;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
# track refexes passed and evaluate expressions on them
|
||||
# ----------------------------------------------------------------------
|
||||
# see instructions for use at the bottom of src/VREF/refex-expr
|
||||
|
||||
use Gitolite::Easy;
|
||||
|
||||
my %passed;
|
||||
my %rules;
|
||||
my $init_done = 0;
|
||||
|
||||
sub access_2 {
|
||||
# get out quick for repos that don't have any rules
|
||||
return if $init_done and not %rules;
|
||||
|
||||
# but we don't really know that the first time, heh!
|
||||
if (not $init_done) {
|
||||
my $repo = $_[1];
|
||||
init($repo);
|
||||
return unless %rules;
|
||||
}
|
||||
|
||||
my $refex = $_[5];
|
||||
return if $refex =~ /DENIED/;
|
||||
|
||||
$passed{$refex}++;
|
||||
|
||||
# evaluate the rules each time; it's not very expensive
|
||||
for my $k (sort keys %rules) {
|
||||
$ENV{"GL_REFEX_EXPR_" . $k} = eval_rule($rules{$k});
|
||||
}
|
||||
}
|
||||
|
||||
sub eval_rule {
|
||||
my $rule = shift;
|
||||
|
||||
my $e;
|
||||
$e = join " ", map { convert($_) } split ' ', $rule;
|
||||
|
||||
my $ret = eval $e;
|
||||
_die "eval '$e' -> '$@'" if $@;
|
||||
Gitolite::Common::trace(1, "RefexExpr", "'$rule' -> '$e' -> '$ret'");
|
||||
|
||||
return "'$rule' -> '$e'" if $ret;
|
||||
}
|
||||
|
||||
my %constant;
|
||||
%constant = map { $_ => $_ } qw(1 not and or xor + - ==);
|
||||
$constant{'-lt'} = '<';
|
||||
$constant{'-gt'} = '>';
|
||||
$constant{'-eq'} = '==';
|
||||
$constant{'-le'} = '<=';
|
||||
$constant{'-ge'} = '>=';
|
||||
$constant{'-ne'} = '!=';
|
||||
|
||||
sub convert {
|
||||
my $i = shift;
|
||||
return $i if $i =~ /^-?\d+$/;
|
||||
return $constant{$i} || $passed{$i} || $passed{"refs/heads/$i"} || 0;
|
||||
}
|
||||
|
||||
# called only once
|
||||
sub init {
|
||||
$init_done = 1;
|
||||
my $repo = shift;
|
||||
|
||||
# find all the rule expressions
|
||||
my %t = config($repo, "^gitolite-options\\.refex-expr\\.");
|
||||
my ($k, $v);
|
||||
# get rid of the cruft and store just the rule name as the key
|
||||
while ( ($k, $v) = each %t) {
|
||||
$k =~ s/^gitolite-options\.refex-expr\.//;
|
||||
$rules{$k} = $v;
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
Loading…
Reference in a new issue