#!/usr/bin/perl use strict; use warnings; # see bottom of this file for instructons and IMPORTANT WARNINGS! # ---------------------------------------------------------------------- my $rule = $ARGV[7]; die "\n\nFATAL: GL_REFEX_EXPR_ doesn't exist\n(your admin probably forgot the rc file change needed for this to work)\n\n" unless exists $ENV{ "GL_REFEX_EXPR_" . $rule }; my $res = $ENV{ "GL_REFEX_EXPR_" . $rule } || 0; print "$ARGV[6] ($res)\n" if $res; exit 0; __END__ ------------------------------------------------------------------------ IMPORTANT WARNINGS: * has not been tested heavily * SO PLEASE TEST YOUR SPECIFIC USE CASE THOROUGHLY! * read the NOTES section below * syntax and semantics are to be considered beta and may change as I find better use cases ------------------------------------------------------------------------ Refex expressions, like VREFs, are best used as additional "deny" rules, to deny combinations that the normal ruleset cannot detect. To enable this, uncomment 'refex-expr' in the ENABLE list in the rc file. It allows you to say things like "don't allow users u3 and u4 to change the Makefile in the master branch" (i.e., they can change any other file in master, or the Makefile in any other branch, but not that specific combo). repo foo RW+ = u1 u2 # line 1 RW+ master = u3 u4 # line 2 RW+ = u3 u4 # line 3 RW+ VREF/NAME/Makefile = u3 u4 # line 4 - master and VREF/NAME/Makefile = u3 u4 # line 5 Line 5 is a "refex expression". Here are the rules: * for each refex in the expression ("master" and "VREF/NAME/Makefile" in this example), a count is kept of the number of times the EXACT refex was matched and allowed in the *normal* rules (here, lines 2 and 4) during this push. * the expression is evaluated based on these counts. 0 is false, and any non-zero is true (see more examples later). The truth value of the expression determines whether the refex expression matched. You can use any logical or arithmetic expression using refexes as operands and using these operators: not and or xor + - == -lt -gt -eq -le -ge -ne Parens are not allowed. Precedence is as you might expect for those operators. It's actually perl that is evaluating it (you can guess what the '-lt' etc., get translated to) so if in doubt, check 'man perlop'. * the refexes that form the terms of the expression (in this case, lines 2 and 4) MUST come before the expression itself (i.e., line 5). * note the words "EXACT refex was matched" above. Let's say you add "u3" to line 1. Then the refex expression in line 5 would never match for u3. This is because line 1 prevents line 2 from matching (being more general *and* appearing earlier), so the count for the "master" refex would be 0. If "master" is 0 (false), then "master and " is also false. (Same thing is you swap lines 2 and 3; i.e., put the "RW+ = ..." before the "RW+ master = ..."). Put another way, the terms in the refex expression are refexes, not refs. Merely pushing the master branch does not mean the count for "master" increases; it has to *match* on a line that has "master" as the refex. Here are some more examples: * user u2 is allowed to push either 'doc/' or 'src/' but not both repo foo RW+ = u1 u2 u3 RW+ VREF/NAME/doc/ = u2 RW+ VREF/NAME/src/ = u2 - VREF/NAME/doc/ and VREF/NAME/src/ = u2 * user u3 is allowed to push at most 2 files to conf/ repo foo RW+ = u1 u2 u3 RW+ VREF/NAME/conf/ = u3 - VREF/NAME/conf/ -gt 2 = u3