Let me summarise:
* you want to allow pushing to 'master'
* you want to allow writing a file say 'foo' (or files in
manifests/hosts/, in your case)
* but not when both are combined (for some users)
Assuming that is correct, here's something that I just tested:
repo testing
# explicitly permit the refs you want to check later.
# In some cases you may need them *before* more generic
# rules
RW+ refs/heads/master = u1 u2
RW+ = @all
RW+ VREF/NAME/foo = u1 u2
RW+ VREF/NAME/ = u1 u2
# set up a deny combo and call it rule 'r1'. Do NOT use
# globs here (like refs/.* or refs/heads/.*)
option deny-combo.r1 = refs/heads/master VREF/NAME/foo
# now deny users u1 and u2 if they push combo 'r1'
- VREF/deny-combo/r1 = u1 u2
You also need to add
'RecordRefs::access_2',
to the 'ACCESS_2' list in the rc file.
----
The code behind all this is in the following two files, with
explanations following:
(I am not sure if the mailing list archive preserves
attachments, and I want this email to be useful by itself for
anyone searching for something like this later, so I in-lined
them. They're not very big).
src/lib/Gitolite/Triggers/RecordRefs.pm:
package Gitolite::Triggers::RecordRefs;
use strict;
use warnings;
sub access_2 {
$ENV{GL_REFS} .= "$_[5] " unless $_[5] =~ /DENIED/;
}
1;
All this is doing is recording each ref that got matched. See
the 'triggers' doc for arguments. Briefly, this is the refex
that allowed any specific match to proceed. For the master
branch, this will be 'refs/heads/master'. For any other, it
will be 'refs/.*' because that is what an empty refex becomes,
internally. This is why you need to explicitly make sure the
correct rule matches.
src/VREF/deny-combo:
#!/bin/bash
rule=$8
refs=`gitolite git-config $GL_REPO gitolite-options\\.deny-combo\\.$rule`
echo >&2 "refs=$refs."
echo >&2 "GL_REFS=$GL_REFS."
for i in $refs
do
echo " $GL_REFS " | grep " $i " || exit 0
done >/dev/null
echo $7 bad combo: $GL_REFS
When you invoke a VREF by saying 'VREF/deny-combo/r1', argument
8 is 'r1'. That's our 'rule number/name', so you then get the
option value out for that rule.
Split it out into fields, and if any of the fields does *not*
exist in the list of recorded refs, exit without printing
anything.
Other print the refex with an additional message. See the vref
document for how this gets treatedm but basically it triggers
the "-" in the VREF invocation in the conf file.