summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Bremner <david@tethera.net>2018-09-15 12:35:56 -0300
committerDavid Bremner <david@tethera.net>2018-09-15 12:35:56 -0300
commit518e6f1ad5bd9ea43609f29e5ddac025e6652865 (patch)
tree4ff1b80de9c6c0508122cdaafe5585a250cf53a1
parent2837fcd4f1514f3fb29d0f6e11733c4b09409d75 (diff)
parent6a67ca1ab46267e2f7ceb5919fbbbf167f474dd8 (diff)
Merge tag 'upstream/3.6.9' into debian
merged from github
-rw-r--r--CHANGELOG17
-rw-r--r--README.markdown2
-rwxr-xr-xcontrib/commands/compile-1139
-rwxr-xr-xcontrib/utils/gitolite-local2
-rwxr-xr-xcontrib/utils/testconf2
-rw-r--r--contrib/vim/indent/gitolite.vim49
-rw-r--r--contrib/vim/syntax/gitolite.vim94
-rwxr-xr-xinstall2
-rw-r--r--src/VREF/MERGE-CHECK4
-rwxr-xr-xsrc/commands/access10
-rwxr-xr-xsrc/commands/compile-template-data101
-rwxr-xr-xsrc/commands/info16
-rwxr-xr-xsrc/gitolite5
-rwxr-xr-xsrc/gitolite-shell23
-rw-r--r--src/lib/Gitolite/Common.pm20
-rw-r--r--src/lib/Gitolite/Conf.pm10
-rw-r--r--src/lib/Gitolite/Conf/Load.pm9
-rw-r--r--src/lib/Gitolite/Conf/Store.pm18
-rw-r--r--src/lib/Gitolite/Conf/Sugar.pm1
-rw-r--r--src/lib/Gitolite/Hooks/Update.pm2
-rw-r--r--src/lib/Gitolite/Triggers/Mirroring.pm1
-rw-r--r--src/lib/Gitolite/Triggers/TProxy.pm1
-rwxr-xr-xsrc/triggers/expand-deny-messages14
-rwxr-xr-xsrc/triggers/post-compile/ssh-authkeys-split43
-rwxr-xr-xsrc/triggers/post-compile/update-git-configs12
-rwxr-xr-xsrc/triggers/post-compile/update-git-daemon-access-list17
-rwxr-xr-xsrc/triggers/post-compile/update-gitweb-access-list29
-rwxr-xr-xsrc/triggers/post-compile/update-gitweb-daemon-from-options11
-rwxr-xr-xsrc/triggers/repo-specific-hooks28
-rwxr-xr-xsrc/triggers/upstream8
-rwxr-xr-xt/access.t53
-rwxr-xr-xt/mirror-test8
-rwxr-xr-xt/partial-copy.t6
-rwxr-xr-xt/repo-specific-hooks.t12
-rwxr-xr-xt/smart-http4
-rwxr-xr-xt/smart-http.root-setup2
-rwxr-xr-xt/templates.t1322
37 files changed, 1977 insertions, 120 deletions
diff --git a/CHANGELOG b/CHANGELOG
index c117811..9c3998a 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,20 @@
+2018-08-07 v3.6.9 prevent racy access to repos in process of migration to
+ gitolite
+
+ 'info' learns new '-p' option to show only physical repos
+ (as opposed to wild repos)
+
+2018-07-12 v3.6.8 fix bug when deleting *all* hooks for a repo
+
+ allow trailing slashes in repo names
+
+ make pre-receive hook driver bail on non-zero exit of a
+ pre-receive hook
+
+ allow templates in gitolite.conf (new feature)
+
+ various optimiations
+
2017-07-02 v3.6.7 allow repo-specific hooks to be organised into
subdirectories, and allow the multi-hook driver to be
placed in some other location of your choice
diff --git a/README.markdown b/README.markdown
index 411b0bb..d821a1d 100644
--- a/README.markdown
+++ b/README.markdown
@@ -65,7 +65,7 @@ First, prepare the ssh key:
Next, install gitolite by running these commands:
- git clone git://github.com/sitaramc/gitolite
+ git clone https://github.com/sitaramc/gitolite
mkdir -p $HOME/bin
gitolite/install -to $HOME/bin
diff --git a/contrib/commands/compile-1 b/contrib/commands/compile-1
new file mode 100755
index 0000000..a5b5356
--- /dev/null
+++ b/contrib/commands/compile-1
@@ -0,0 +1,139 @@
+#!/usr/bin/perl -s
+use strict;
+use warnings;
+
+# DESCRIPTION:
+
+# This program is meant to re-compile the access rules (and 'config' or
+# 'option' lines) of exactly ONE actual repo (i.e., not a repo group or a
+# repo pattern).
+
+# MOTIVATION:
+
+# Fedora has a huge number of repos, as well as lot of churn in permissions.
+# The combination of having a large conf *and* frequent compiles were not
+# working out, hence this solution. Not sure if any others have such a
+# situation, so it's a standalone program, separate from "core" gitolite,
+# shipped in "contrib" instead of "src".
+
+# SETUP:
+
+# It expects to run as a gitolite sub-command, which means you will need to
+# copy it from contrib to src/commands, or the equivalent location inside
+# LOCAL_CODE; see non-core.html in the docs for details.
+
+# INVOCATION:
+
+# It takes one argument: the name of a file that contains the new ruleset
+# you want to use. (This cannot be STDIN or "-" or something).
+
+# example:
+#
+# gitolite compile-1 <file-containing-rules-for-exactly-one-repo>
+
+# WARNING:
+
+# If the main gitolite.conf changes significantly (specifically, if the
+# number of effective rules in it increase quite a bit), you may have to run
+# this command on ALL repos to update their individual gl-conf files.
+#
+# (TBD: explain this in more concrete terms)
+
+# ----------------------------------------------------------------------
+# THERE IS NO ERROR CHECKING ON THE WARNING ABOVE, NOR ON THE ASSUMPTIONS AND
+# REQUIREMENTS BELOW. PLEASE USE CAREFULLY!
+# ----------------------------------------------------------------------
+
+# ASSUMPTIONS/REQUIREMENTS:
+
+# The file given must contain exactly one 'repo' line, with exactly one repo
+# name, followed by the rules, configs, and options for that repo in the
+# normal gitolite.conf syntax.
+
+# The file must not have any group definitions, though it may use group
+# definitions already setup in the main gitolite.conf file.
+
+# Rules for this repo need not be already defined in the main gitolite.conf.
+# If they are, they will cease to have any effect once you run this command
+# - only the rules you supply in the file passed to this command will apply,
+# and they will be considered to be placed at the end of gitolite.conf.
+
+# If the repo does not exist, it must be first created using:
+#
+# GL_USER=admin gitolite create <reponame>
+#
+# where <reponame> is the gitolite-style name (i.e., "foo", not "foo.git" or
+# "~/repositories/foo" or "~/repositories/foo.git")
+#
+# This, of course, requires the main gitolite.conf to have the following
+# lines at the top:
+#
+# repo [A-Za-z].*
+# C = admin
+
+# Any change to the main gitolite.conf is followed by a full 'gitolite
+# compile'; i.e., ~/.gitolite/conf/gitolite.conf-compiled.pm, the main
+# "compiled" conf file, is consistent with the latest gitolite.conf.
+
+use 5.10.0;
+use Data::Dumper;
+
+use lib $ENV{GL_LIBDIR};
+use Gitolite::Rc;
+use Gitolite::Common;
+use Gitolite::Conf;
+use Gitolite::Conf::Store;
+use Gitolite::Conf::Sugar;
+
+my ($cf, $repo) = args(); # conffile from @ARGV, repo from first line of conffile
+my $startseq = getseq(); # get the starting sequence number by looking in the (common) compiled conf file
+parse_and_store($cf, $repo); # parse the ruleset and write out just the gl-conf file
+ # (this is the only part that uses core gitolite functions)
+update_seq($repo, $startseq); # update gl-conf with adjusted sequence numbers
+
+exit 0;
+
+# ----------------------------------------------------------------------
+
+sub args {
+ my $cf = shift @ARGV or _die "need conffile";
+ $cf = $ENV{PWD} . "/" . $cf unless $cf =~ m(^/);
+
+ my $t = slurp($cf);
+ _die "bad conf file" unless $t =~ /^\s*repo\s+(\S+)\s*$/m;
+ my $repo = $1;
+
+ return ($cf, $repo);
+}
+
+sub getseq {
+ my @main_cc = slurp "$rc{GL_ADMIN_BASE}/conf/gitolite.conf-compiled.pm";
+ my $max = 0;
+ for (@main_cc) {
+ $max = $1 if m/^ +(\d+),$/ and $max < $1;
+ }
+
+ return $max;
+}
+
+sub parse_and_store {
+ my ($cf, $repo) = @_;
+
+ parse(sugar($cf));
+ _chdir( $rc{GL_REPO_BASE} );
+ Gitolite::Conf::Store::store_1($repo);
+}
+
+sub update_seq {
+ my ($repo, $startseq) = @_;
+
+ _chdir("$rc{GL_REPO_BASE}/$repo.git");
+ my $text = slurp("gl-conf");
+
+ $startseq+=1000;
+ # just for safety, in case someone adds a few rules to the main conf later, but neglects to update repo confs
+
+ $text =~ s/^( +)(\d+),$/"$1" . ($2+$startseq) . ","/gme;
+
+ _print("gl-conf", $text);
+}
diff --git a/contrib/utils/gitolite-local b/contrib/utils/gitolite-local
index 5faf0c7..903b868 100755
--- a/contrib/utils/gitolite-local
+++ b/contrib/utils/gitolite-local
@@ -3,7 +3,7 @@
# ----------------------------------------------------------------------
# change these lines to suit
testconf=$HOME/GITOLITE-TESTCONF
-gitolite_url=git://github.com/sitaramc/gitolite
+gitolite_url=https://github.com/sitaramc/gitolite
# change it to something local for frequent use
# gitolite_url=file:///tmp/gitolite.git
diff --git a/contrib/utils/testconf b/contrib/utils/testconf
index fda7e79..5fa9194 100755
--- a/contrib/utils/testconf
+++ b/contrib/utils/testconf
@@ -19,7 +19,7 @@
# a semi-permanent area to play in (please delete it manually if you want to start afresh).
testconf=$HOME/GITOLITE-TESTCONF
# the gitolite source code
- gitolite_url=git://github.com/sitaramc/gitolite
+ gitolite_url=https://github.com/sitaramc/gitolite
# 3. go to your gitolite-admin clone and make suitable changes; see example
# below. No need to push to the server, yet.
diff --git a/contrib/vim/indent/gitolite.vim b/contrib/vim/indent/gitolite.vim
new file mode 100644
index 0000000..b36f30a
--- /dev/null
+++ b/contrib/vim/indent/gitolite.vim
@@ -0,0 +1,49 @@
+" Vim indent file
+" Language: gitolite configuration
+" URL: https://github.com/sitaramc/gitolite/blob/master/contrib/vim/indent/gitolite.vim
+" (https://raw.githubusercontent.com/sitaramc/gitolite/master/contrib/vim/indent/gitolite.vim)
+" Maintainer: Sitaram Chamarty <sitaramc@gmail.com>
+" (former Maintainer: Teemu Matilainen <teemu.matilainen@iki.fi>)
+" Last Change: 2017 Oct 05
+
+if exists("b:did_indent")
+ finish
+endif
+let b:did_indent = 1
+
+setlocal autoindent
+setlocal indentexpr=GetGitoliteIndent()
+setlocal indentkeys=o,O,*<Return>,!^F,=repo,\",=
+
+" Only define the function once.
+if exists("*GetGitoliteIndent")
+ finish
+endif
+
+let s:cpo_save = &cpo
+set cpo&vim
+
+function! GetGitoliteIndent()
+ let prevln = prevnonblank(v:lnum-1)
+ let pline = getline(prevln)
+ let cline = getline(v:lnum)
+
+ if cline =~ '^\s*\(C\|R\|RW\|RW+\|RWC\|RW+C\|RWD\|RW+D\|RWCD\|RW+CD\|-\)[ \t=]'
+ return shiftwidth()
+ elseif cline =~ '^\s*config\s'
+ return shiftwidth()
+ elseif cline =~ '^\s*option\s'
+ return shiftwidth()
+ elseif pline =~ '^\s*repo\s' && cline =~ '^\s*\(#.*\)\?$'
+ return shiftwidth()
+ elseif cline =~ '^\s*#'
+ return indent(prevln)
+ elseif cline =~ '^\s*$'
+ return -1
+ else
+ return 0
+ endif
+endfunction
+
+let &cpo = s:cpo_save
+unlet s:cpo_save
diff --git a/contrib/vim/syntax/gitolite.vim b/contrib/vim/syntax/gitolite.vim
new file mode 100644
index 0000000..3a6da26
--- /dev/null
+++ b/contrib/vim/syntax/gitolite.vim
@@ -0,0 +1,94 @@
+" Vim syntax file
+" Language: gitolite configuration
+" URL: https://github.com/sitaramc/gitolite/blob/master/contrib/vim/syntax/gitolite.vim
+" (https://raw.githubusercontent.com/sitaramc/gitolite/master/contrib/vim/syntax/gitolite.vim)
+" Maintainer: Sitaram Chamarty <sitaramc@gmail.com>
+" (former Maintainer: Teemu Matilainen <teemu.matilainen@iki.fi>)
+" Last Change: 2017 Oct 05
+
+if exists("b:current_syntax")
+ finish
+endif
+
+let s:cpo_save = &cpo
+set cpo&vim
+
+" this seems to be the best way, for now.
+syntax sync fromstart
+
+" ---- common stuff
+
+syn match gitoliteGroup '@\S\+'
+
+syn match gitoliteComment '#.*' contains=gitoliteTodo
+syn keyword gitoliteTodo TODO FIXME XXX NOT contained
+
+" ---- main section
+
+" catch template-data syntax appearing outside template-data section
+syn match gitoliteRepoError '^\s*repo.*='
+syn match gitoliteRepoError '^\s*\S\+\s*=' " this gets overridden later when first word is a perm, don't worry
+
+" normal gitolite group and repo lines
+syn match gitoliteGroupLine '^\s*@\S\+\s*=\s*\S.*$' contains=gitoliteGroup,gitoliteComment
+syn match gitoliteRepoLine '^\s*repo\s\+[^=]*$' contains=gitoliteRepo,gitoliteGroup,gitoliteComment
+syn keyword gitoliteRepo repo contained
+
+syn keyword gitoliteSpecialRepo CREATOR
+
+" normal gitolite rule lines
+syn match gitoliteRuleLine '^\s*\(-\|C\|R\|RW+\?C\?D\?\)\s[^#]*' contains=gitoliteRule,gitoliteCreateRule,gitoliteDenyRule,gitoliteRefex,gitoliteUsers,gitoliteGroup
+syn match gitoliteRule '\(^\s*\)\@<=\(-\|C\|R\|RW+\?C\?D\?\)\s\@=' contained
+syn match gitoliteRefex '\(^\s*\(-\|R\|RW+\?C\?D\?\)\s\+\)\@<=\S.\{-}\(\s*=\)\@=' contains=gitoliteSpecialRefex
+syn match gitoliteSpecialRefex 'NAME/'
+syn match gitoliteSpecialRefex '/USER/'
+syn match gitoliteCreateRule '\(^\s*C\s.*=\s*\)\@<=\S[^#]*[^# ]' contained contains=gitoliteGroup
+syn match gitoliteDenyRule '\(^\s*-\s.*=\s*\)\@<=\S[^#]*[^# ]' contained
+
+" normal gitolite config (and similar) lines
+syn match gitoliteConfigLine '^\s*\(config\|option\|include\|subconf\)\s[^#]*' contains=gitoliteConfigKW,gitoliteConfigKey,gitoliteConfigVal,gitoliteComment
+syn keyword gitoliteConfigKW config option include subconf contained
+syn match gitoliteConfigKey '\(\(config\|option\)\s\+\)\@<=[^ =]*' contained
+syn match gitoliteConfigVal '\(=\s*\)\@<=\S.*' contained
+
+" ---- template-data section
+
+syn region gitoliteTemplateLine matchgroup=PreProc start='^=begin template-data$' end='^=end$' contains=gitoliteTplRepoLine,gitoliteTplRoleLine,gitoliteGroup,gitoliteComment,gitoliteTplError
+
+syn match gitoliteTplRepoLine '^\s*repo\s\+\S.*=.*' contained contains=gitoliteTplRepo,gitoliteTplTemplates,gitoliteGroup
+syn keyword gitoliteTplRepo repo contained
+syn match gitoliteTplTemplates '\(=\s*\)\@<=\S.*' contained contains=gitoliteGroup,gitoliteComment
+
+syn match gitoliteTplRoleLine '^\s*\S\+\s*=\s*.*' contained contains=gitoliteTplRole,gitoliteGroup,gitoliteComment
+syn match gitoliteTplRole '\S\+\s*='he=e-1 contained
+
+" catch normal gitolite rules appearing in template-data section
+syn match gitoliteTplError '^\s*repo[^=]*$' contained
+syn match gitoliteTplError '^\s*\(-\|R\|RW+\?C\?D\?\)\s'he=e-1 contained
+syn match gitoliteTplError '^\s*\(config\|option\|include\|subconf\)\s'he=e-1 contained
+syn match gitoliteTplError '^\s*@\S\+\s*=' contained contains=NONE
+
+hi def link gitoliteGroup Identifier
+hi def link gitoliteComment Comment
+hi def link gitoliteTodo ToDo
+hi def link gitoliteRepoError Error
+hi def link gitoliteGroupLine PreProc
+hi def link gitoliteRepo Keyword
+hi def link gitoliteSpecialRepo PreProc
+hi def link gitoliteRule Keyword
+hi def link gitoliteCreateRule PreProc
+hi def link gitoliteDenyRule WarningMsg
+hi def link gitoliteRefex Constant
+hi def link gitoliteSpecialRefex PreProc
+hi def link gitoliteConfigKW Keyword
+hi def link gitoliteConfigKey Identifier
+hi def link gitoliteConfigVal String
+hi def link gitoliteTplRepo Keyword
+hi def link gitoliteTplTemplates Constant
+hi def link gitoliteTplRole Constant
+hi def link gitoliteTplError Error
+
+let b:current_syntax = "gitolite"
+
+let &cpo = s:cpo_save
+unlet s:cpo_save
diff --git a/install b/install
index 98d8aee..abafdd5 100755
--- a/install
+++ b/install
@@ -36,7 +36,7 @@ Usage (from gitolite clone directory):
Simplest use, if $HOME/bin exists and is in $PATH, is:
- git clone git://github.com/sitaramc/gitolite
+ git clone https://github.com/sitaramc/gitolite
gitolite/install -ln
# now run setup
diff --git a/src/VREF/MERGE-CHECK b/src/VREF/MERGE-CHECK
index 07f0351..a70fe23 100644
--- a/src/VREF/MERGE-CHECK
+++ b/src/VREF/MERGE-CHECK
@@ -9,9 +9,9 @@ use warnings;
# usage in conf/gitolite.conf goes like this:
-# - VREF/MERGE_CHECK/master = @all
+# - VREF/MERGE-CHECK/master = @all
# # reject only if the merge commit is being pushed to the master branch
-# - VREF/MERGE_CHECK = @all
+# - VREF/MERGE-CHECK = @all
# # reject merge commits to any branch
my $ref = $ARGV[0];
diff --git a/src/commands/access b/src/commands/access
index f02e533..7d4a5b9 100755
--- a/src/commands/access
+++ b/src/commands/access
@@ -51,7 +51,7 @@ $ref ||= 'any';
# fq the ref if needed
$ref =~ s(^)(refs/heads/) if $ref and $ref ne 'any' and $ref !~ m(^(refs|VREF)/);
_die "invalid perm" if not( $aa and $aa =~ /^(R|W|\+|C|D|M|\^C)$/ );
-_die "invalid ref name" if not( $ref and $ref =~ $REPONAME_PATT );
+_die "invalid ref name" if not( $ref and $ref =~ $REF_OR_FILENAME_PATT );
my $ret = '';
@@ -61,6 +61,9 @@ if ( $repo ne '%' and $user ne '%' ) {
show($ret) if $s;
+ # adjust for fallthru in VREFs
+ $ret =~ s/DENIED by fallthru/allowed by fallthru/ if $ref =~ m(^VREF/);
+
if ( $ret =~ /DENIED/ ) {
print "$ret\n" unless $q;
exit 1;
@@ -85,8 +88,9 @@ while (<>) {
sub adjust_aa {
my ($repo, $aa) = @_;
- $aa = '+' if $aa eq 'C' and not option($repo, 'CREATE_IS_C');
+ $aa = 'W' if $aa eq 'C' and not option($repo, 'CREATE_IS_C');
$aa = '+' if $aa eq 'D' and not option($repo, 'DELETE_IS_D');
+ $aa = 'W' if $aa eq 'M' and not option($repo, 'MERGE_CHECK');
return $aa;
}
@@ -103,7 +107,7 @@ sub show {
p => skipped due to perm (W, +, etc) not matching,
D => explicitly denied,
A => explicitly allowed,
- F => denied due to fallthru (no rules matched)
+ F => fallthru; access denied for normal refs, allowed for VREFs
";
diff --git a/src/commands/compile-template-data b/src/commands/compile-template-data
new file mode 100755
index 0000000..e4ef86e
--- /dev/null
+++ b/src/commands/compile-template-data
@@ -0,0 +1,101 @@
+#!/usr/bin/perl
+use strict;
+use warnings;
+
+# read template data to produce gl-perms and gl-repo-groups files in each
+# $repo dir. Create the repo if needed, using the wild repos create logic
+# (with a "creator" of "gitolite-admin"!), though they're not really wild
+# repos.
+
+# see rule-templates.html in the gitolite documentation site.
+
+# pure text manipulation (and very little of that!), no git or gitolite
+# functions, no access checks, no possibility of a performance drama (or at
+# least not a *complex* performance drama)
+
+use lib $ENV{GL_LIBDIR};
+use Gitolite::Rc;
+use Gitolite::Common;
+use Gitolite::Conf::Load;
+use Gitolite::Conf::Store;
+
+my $rb = $rc{GL_REPO_BASE};
+
+@ARGV = `find $rc{GL_ADMIN_BASE}/conf -type f -name "*.conf" | sort`; chomp(@ARGV);
+# we don't see the files in the exact same order that gitolite compile sees
+# them, but we don't need to, for the data we are interested in (as long as
+# you don't break up one repo's data across multiple files!)
+
+# XXX We also potentially see more; a conf file may be in the directory, but
+# not pulled in via an 'include' or 'subconf', so it doesn't exist as far as
+# 'gitolite compile' is concerned, but here we *do* pull it in.
+
+my $repos = '';
+my $perms = '';
+my $list = ''; # list of templates to apply
+my $lip = ''; # line in progress
+while (<>) {
+ chomp;
+ next unless /^=begin template-data$/ .. /^=end$/ and not /^=(begin|end)/;
+
+ next unless /\S/;
+ next if /^\s*#/;
+
+ s/\t/ /g; # all the same to us
+
+ # handle continuation lines (backslash as last character)
+ if (/\\$/) {
+ s/\\$//;
+ $lip .= $_;
+ next;
+ }
+ $_ = $lip . $_;
+ $lip = '';
+
+ _warn("bad line: $_"), next if m([^ \w.\@/=-]); # silently ignore lines that have characters we don't need
+ if (/^\s*repo\s+(\S.*)=\s*(\S.*)$/) {
+ flush($repos, $list, $perms);
+ $repos = $1;
+ $perms = '';
+ $list = $2;
+
+ } elsif (/^\s*(\S+)\s*=\s*(\S.*)$/) {
+ $perms .= "$1 = $2\n";
+ } else {
+ # probably a blank line or a comment line. If not, well *shrug*
+ }
+}
+flush($repos, $list, $perms);
+
+sub flush {
+ my ($r, $l, $p) = @_;
+ return unless $r and $l and $p;
+ $l =~ s/\s+/ /g;
+
+ my @r = split ' ', $r;
+ while (@r) {
+ my $r1 = shift @r;
+ if ($r1 =~ m(^@)) {
+ my @g = @{ Gitolite::Conf::Load::list_members($r1) };
+ _warn "undefined group '$r1'" unless @g;
+ unshift @r, @g;
+ next;
+ }
+
+ flush_1($r1, $l, $p);
+ }
+}
+sub flush_1 {
+ my ($repo, $list, $perms) = @_;
+
+ # beware of wild characters!
+ return unless $repo =~ $REPONAME_PATT;
+
+ if (not -d "$rb/$repo.git") {
+ new_wild_repo( $repo, 'gitolite-admin', 'template-data' );
+ }
+
+ _print("$rb/$repo.git/gl-repo-groups", $list);
+
+ _print("$rb/$repo.git/gl-perms", $perms);
+}
diff --git a/src/commands/info b/src/commands/info
index 5079cfa..b88e288 100755
--- a/src/commands/info
+++ b/src/commands/info
@@ -12,12 +12,13 @@ use Gitolite::Conf::Load;
=for args
Usage: gitolite info [-lc] [-ld] [-json] [<repo name pattern>]
-List all existing repos you can access, as well as repo name patterns you can
-create repos from (if any).
+List all existing repos you can access, as well as repo name patterns (see
+"wild repos") you have any kind of access to.
'-lc' lists creators as an additional field at the end.
'-ld' lists description as an additional field at the end.
'-json' produce JSON output instead of normal output
+ '-p' limits output to physical repos only (no wild repo regexes!)
The optional pattern is an unanchored regex that will limit the repos
searched, in both cases. It might speed up things a little if you have more
@@ -25,7 +26,7 @@ than a few thousand repos.
=cut
# these are globals
-my ( $lc, $ld, $json, $patt ) = args();
+my ( $lc, $ld, $json, $p, $patt ) = args();
my %out; # holds info to be json'd
$ENV{GL_USER} or _die "GL_USER not set";
@@ -35,8 +36,8 @@ if ($json) {
print greeting();
}
-print_patterns(); # repos he can create for himself
-print_phy_repos(); # repos already created
+print_patterns() unless $p; # repos he can create for himself
+print_phy_repos(); # repos already created
if ( $rc{SITE_INFO} ) {
$json
@@ -49,13 +50,14 @@ print JSON::to_json( \%out, { utf8 => 1, pretty => 1 } ) if $json;
# ----------------------------------------------------------------------
sub args {
- my ( $lc, $ld, $json, $patt ) = ( '', '', '', '' );
+ my ( $lc, $ld, $json, $p, $patt ) = ( '', '', '', '' );
my $help = '';
GetOptions(
'lc' => \$lc,
'ld' => \$ld,
'json' => \$json,
+ 'p' => \$p,
'h' => \$help,
) or usage();
@@ -64,7 +66,7 @@ sub args {
require JSON if $json;
- return ( $lc, $ld, $json, $patt );
+ return ( $lc, $ld, $json, $p, $patt );
}
sub print_patterns {
diff --git a/src/gitolite b/src/gitolite
index 4a4cbf5..c11e047 100755
--- a/src/gitolite
+++ b/src/gitolite
@@ -71,6 +71,11 @@ if ( $command eq 'setup' ) {
compile(@args);
} elsif ( $command eq 'trigger' ) {
+ my $s = $args[0];
+ _die "trigger section '$s' not found in rc"
+ unless $s eq 'POST_COMPILE'
+ or $s eq 'POST_CREATE'
+ or ( exists $rc{$s} and ref( $rc{$s} ) eq 'ARRAY' );
trigger(@args);
} elsif ( my $c = _which( "commands/$command", 'x' ) ) {
diff --git a/src/gitolite-shell b/src/gitolite-shell
index d9ec01f..6c4c462 100755
--- a/src/gitolite-shell
+++ b/src/gitolite-shell
@@ -113,6 +113,13 @@ sub main {
$ENV{GL_REPO} = $repo;
my $aa = ( $verb =~ 'upload' ? 'R' : 'W' );
+ # catch rare race when moving repos into gitolite control
+ _die "$aa any $repo $user DENIED by fallthru" .
+ "\n(or you mis-spelled the reponame)"
+ unless update_hook_present($repo);
+ # this error message is exactly the same as that from elsewhere in the
+ # code, for the usual reasons (avoid leaking information)
+
# set up env vars from options set for this repo
env_options($repo);
@@ -153,11 +160,19 @@ sub parse_soc {
$soc ||= 'info';
my $git_commands = "git-upload-pack|git-receive-pack|git-upload-archive";
- if ( $soc =~ m(^($git_commands) '?/?(.*?)(?:\.git(\d)?)?'?$) ) {
- my ( $verb, $repo, $trace_level ) = ( $1, $2, $3 );
- $ENV{D} = $trace_level if $trace_level;
- _die "invalid repo name: '$repo'" if $repo !~ $REPONAME_PATT;
+ # simplify the regex; we'll handle all the reponame nuances later
+ if ( $soc =~ m(^($git_commands) '?/?(.*?)'?$) ) {
+ my ( $verb, $repo ) = ( $1, $2 );
trace( 2, "git command", $soc );
+
+ # clean up the repo name; first extract the trace level if supplied
+ # (and no, you can't have a trace level *and* a trailing slash).
+ $ENV{D} = $1 if $repo =~ s/\.git(\d)$//;
+ # and then the git-daemon-compatibility trailers
+ $repo =~ s(/$)();
+ $repo =~ s(\.git$)();
+
+ _die "invalid repo name: '$repo'" if $repo !~ $REPONAME_PATT;
return ( $verb, $repo );
}
diff --git a/src/lib/Gitolite/Common.pm b/src/lib/Gitolite/Common.pm
index 7a52f4b..3f47b37 100644
--- a/src/lib/Gitolite/Common.pm
+++ b/src/lib/Gitolite/Common.pm
@@ -19,6 +19,8 @@ package Gitolite::Common;
ssh_fingerprint_file
ssh_fingerprint_line
+
+ update_hook_present
);
#>>>
use Exporter 'import';
@@ -235,14 +237,28 @@ sub cleanup_conf_line {
chomp($repo);
$repo =~ s/\.git$//;
$repo =~ s(^\./)();
- push @phy_repos, $repo unless $repo =~ m(/$);
- # tolerate bare repos within ~/repositories but silently ignore them
+ next if $repo =~ m(/$);
+ # tolerate non-bare repos within ~/repositories but silently ignore them
+ next unless update_hook_present($repo);
+ # ignore repos that don't yet have the update hook
+ push @phy_repos, $repo;
}
trace( 3, scalar(@phy_repos) . " physical repos found" );
return sort_u( \@phy_repos );
}
}
+sub update_hook_present {
+ my $repo = shift;
+
+ return 1 unless -d "$ENV{GL_REPO_BASE}/$repo.git"; # non-existent repo is fine
+
+ my $x = readlink("$ENV{GL_REPO_BASE}/$repo.git/hooks/update");
+ return 1 if $x and $x eq "$ENV{GL_ADMIN_BASE}/hooks/common/update";
+
+ return 0;
+}
+
# generate a timestamp
sub gen_ts {
my ( $s, $min, $h, $d, $m, $y ) = (localtime)[ 0 .. 5 ];
diff --git a/src/lib/Gitolite/Conf.pm b/src/lib/Gitolite/Conf.pm
index ce7adca..97b6c32 100644
--- a/src/lib/Gitolite/Conf.pm
+++ b/src/lib/Gitolite/Conf.pm
@@ -47,9 +47,19 @@ sub compile {
cache_control('start');
}
+ # remove entries from POST_CREATE which also exist in POST_COMPILE. This
+ # not only saves us having to implement an optimisation in *those*
+ # scripts, but more importantly, moves the optimisation one step up -- we
+ # don't even *call* those scripts now.
+ my %pco = map { $_ => 1 } @{ $rc{POST_COMPILE} };
+ @{ $rc{POST_CREATE} } = grep { ! exists $pco{$_} } @{ $rc{POST_CREATE} };
+
for my $repo ( @{ $rc{NEW_REPOS_CREATED} } ) {
trigger( 'POST_CREATE', $repo );
}
+
+ # process rule template data
+ _system("gitolite compile-template-data");
}
sub parse {
diff --git a/src/lib/Gitolite/Conf/Load.pm b/src/lib/Gitolite/Conf/Load.pm
index 4f42cdc..e0e4e92 100644
--- a/src/lib/Gitolite/Conf/Load.pm
+++ b/src/lib/Gitolite/Conf/Load.pm
@@ -305,7 +305,7 @@ sub load_1 {
}
if ( -f "gl-conf" ) {
- return if not $split_conf{$repo};
+ return if not $split_conf{$repo} and not $rc{ALLOW_ORPHAN_GL_CONF};
my $cc = "./gl-conf";
_die "parse '$cc' failed: " . ( $@ or $! ) unless do $cc;
@@ -384,6 +384,13 @@ sub memberships {
push @ret, $i;
}
}
+
+ # add in any group names explicitly given in (GIT_DIR)/gl-repo-groups
+ push @ret,
+ map { s/^\@?/\@/; $_ }
+ grep { ! /[^\w@-]/ }
+ split (' ', slurp("$ENV{GL_REPO_BASE}/$base.git/gl-repo-groups"))
+ if -f "$ENV{GL_REPO_BASE}/$base.git/gl-repo-groups";
}
push @ret, @{ $groups{$base} } if exists $groups{$base};
diff --git a/src/lib/Gitolite/Conf/Store.pm b/src/lib/Gitolite/Conf/Store.pm
index c7f9ab5..8757c89 100644
--- a/src/lib/Gitolite/Conf/Store.pm
+++ b/src/lib/Gitolite/Conf/Store.pm
@@ -188,10 +188,13 @@ sub new_repos {
next unless $repo =~ $REPONAME_PATT; # skip repo patterns
next if $repo =~ m(^\@|EXTCMD/); # skip groups and fake repos
- # use gl-conf as a sentinel
- hook_1($repo) if -d "$repo.git" and not -f "$repo.git/gl-conf";
+ # use gl-conf as a sentinel; if it exists, all is well
+ next if -f "$repo.git/gl-conf";
- if ( not -d "$repo.git" ) {
+ if (-d "$repo.git") {
+ # directory exists but sentinel missing? Maybe a freshly imported repo?
+ hook_1($repo);
+ } else {
push @{ $rc{NEW_REPOS_CREATED} }, $repo;
trigger( 'PRE_CREATE', $repo );
new_repo($repo);
@@ -239,9 +242,12 @@ sub store {
# first write out the ones for the physical repos
_chdir( $rc{GL_REPO_BASE} );
- my $phy_repos = list_phy_repos(1);
- for my $repo ( @{$phy_repos} ) {
+ # list of repos (union of keys of %repos plus %configs)
+ my %kr_kc;
+ @kr_kc{ keys %repos } = ();
+ @kr_kc{ keys %configs } = ();
+ for my $repo ( keys %kr_kc ) {
store_1($repo);
}
@@ -284,7 +290,7 @@ sub store_1 {
# warning: writes and *deletes* it from %repos and %configs
my ($repo) = shift;
trace( 3, $repo );
- return unless ( $repos{$repo} or $configs{$repo} ) and -d "$repo.git";
+ return unless -d "$repo.git";
my ( %one_repo, %one_config );
diff --git a/src/lib/Gitolite/Conf/Sugar.pm b/src/lib/Gitolite/Conf/Sugar.pm
index 68ad728..b054065 100644
--- a/src/lib/Gitolite/Conf/Sugar.pm
+++ b/src/lib/Gitolite/Conf/Sugar.pm
@@ -187,6 +187,7 @@ sub skip_block {
for (@$lines) {
my $skip = 0;
$skip = 1 if /^= *begin testconf$/;
+ $skip = 1 if /^= *begin template-data$/;
# add code for other types of blocks here as needed
next if $skip .. /^= *end$/;
diff --git a/src/lib/Gitolite/Hooks/Update.pm b/src/lib/Gitolite/Hooks/Update.pm
index 32cd6e0..2bc43a8 100644
--- a/src/lib/Gitolite/Hooks/Update.pm
+++ b/src/lib/Gitolite/Hooks/Update.pm
@@ -17,6 +17,8 @@ use Gitolite::Conf::Load;
use strict;
use warnings;
+$|++;
+
# ----------------------------------------------------------------------
sub update {
diff --git a/src/lib/Gitolite/Triggers/Mirroring.pm b/src/lib/Gitolite/Triggers/Mirroring.pm
index 860e6d0..c9dabce 100644
--- a/src/lib/Gitolite/Triggers/Mirroring.pm
+++ b/src/lib/Gitolite/Triggers/Mirroring.pm
@@ -7,7 +7,6 @@ use Gitolite::Conf::Load;
use strict;
use warnings;
-my $git_commands = "git-upload-pack|git-receive-pack|git-upload-archive";
my $hn = $rc{HOSTNAME};
my ( $mode, $master, %slaves, %trusted_slaves );
diff --git a/src/lib/Gitolite/Triggers/TProxy.pm b/src/lib/Gitolite/Triggers/TProxy.pm
index b2ab8df..a2820ec 100644
--- a/src/lib/Gitolite/Triggers/TProxy.pm
+++ b/src/lib/Gitolite/Triggers/TProxy.pm
@@ -58,7 +58,6 @@ use Gitolite::Conf::Load;
use strict;
use warnings;
-my $git_commands = "git-upload-pack|git-receive-pack|git-upload-archive";
my $soc = $ENV{SSH_ORIGINAL_COMMAND};
# ----------------------------------------------------------------------
diff --git a/src/triggers/expand-deny-messages b/src/triggers/expand-deny-messages
index a8b2289..107202c 100755
--- a/src/triggers/expand-deny-messages
+++ b/src/triggers/expand-deny-messages
@@ -2,6 +2,8 @@
use strict;
use warnings;
+$|++;
+
# program name: expand-deny-messages
# DOCUMENTATION IS AT THE BOTTOM OF THIS FILE; PLEASE READ
@@ -47,10 +49,14 @@ _info( "Operation", _op( $a12, $aa, $oldsha, $newsha ) );
if ( $ref =~ m((^VREF/[^/]+)) ) {
my $vref = $1;
- my $vref_text = slurp( _which( $vref, 'x' ) );
- my $etag = '(?:help|explain|explanation)';
- $vref_text =~ m(^\s*# $etag.start\n(.*)^\s*# $etag.end\n)sm
- and print STDERR "Explanation for $vref:\n$1";
+ if ($ref =~ s(^VREF/NAME/)()) {
+ print STDERR "You're apparently not allowed to push '$ref'";
+ } else {
+ my $vref_text = slurp( _which( $vref, 'x' ) );
+ my $etag = '(?:help|explain|explanation)';
+ $vref_text =~ m(^\s*# $etag.start\n(.*)^\s*# $etag.end\n)sm
+ and print STDERR "Explanation for $vref:\n$1";
+ }
}
print STDERR "\n";
diff --git a/src/triggers/post-compile/ssh-authkeys-split b/src/triggers/post-compile/ssh-authkeys-split
index b71f9eb..031bd07 100755
--- a/src/triggers/post-compile/ssh-authkeys-split
+++ b/src/triggers/post-compile/ssh-authkeys-split
@@ -18,13 +18,6 @@
# - assumes you don't have a subdir in keydir called "__split_keys__"
-# - RUNNING "GITOLITE SETUP" WILL LOSE ALL THESE KEYS. So if you ever do
-# that, you will then need to make a dummy push to the admin repo to add
-# them back. If all your **admin** keys were in split keys, then you lost
-# remote access. If that happens, log on to the server using "su - git" or
-# such, then use the methods described in the "bypassing gitolite" section
-# in "emergencies.html" instead of a remote push.
-
# SUPPORT
# -------
#
@@ -42,7 +35,29 @@ rm -rf __split_keys__
mkdir __split_keys__
export SKD=$PWD/__split_keys__
-find . -type f -name "*.pub" | while read k
+# if we're coming from a gitolite-admin push, delete all *.multi, and rename
+# all multi-line *.pub to *.multi
+if [ "$GL_REPO" = "gitolite-admin" ] || [ "$GL_BYPASS_ACCESS_CHECKS" = "1" ]
+then
+ find . -type f -name "*.multi" | while read k
+ do
+ rm -f "$k"
+ done
+ find . -type f -name "*.pub" | while read k
+ do
+ # is this a multi-key?
+ lines=`wc -l < $k`
+ case $lines in
+ (0|1) continue
+ esac
+
+ base=`basename $k .pub`
+ mv $k $base.multi
+ done
+fi
+
+# now process *.multi
+find . -type f -name "*.multi" | while read k
do
# do we need to split?
lines=`wc -l < $k`
@@ -50,14 +65,16 @@ do
(0|1) continue
esac
- # is it sane to split?
- base=`basename $k .pub`
+ base=`basename $k .multi`
+ # sanity check
echo $base | grep '@' >/dev/null && continue
# ok do it
- seq=1
+ seq=0
while read line
do
+ (( seq++ ))
+ [ -z "$line" ] && continue
f=$SKD/$base@$seq.pub
echo "$line" > $f
# similar sanity check as main ssh-authkeys script
@@ -66,9 +83,5 @@ do
echo 1>&2 "ssh-authkeys-split: bad line $seq in keydir/$k"
rm -f $f
fi
- (( seq++ ))
done < $k
-
- # now delete the original file
- rm $k
done
diff --git a/src/triggers/post-compile/update-git-configs b/src/triggers/post-compile/update-git-configs
index bdb83ac..6eb2f46 100755
--- a/src/triggers/post-compile/update-git-configs
+++ b/src/triggers/post-compile/update-git-configs
@@ -17,13 +17,6 @@ my $RB = $rc{GL_REPO_BASE};
_chdir($RB);
# ----------------------------------------------------------------------
-# skip if arg-0 is POST_CREATE and no arg-2 (user name) exists; this means
-# it's been triggered by a *normal* (not "wild") repo creation, which in turn
-# means a POST_COMPILE should be following so there's no need to waste time
-# running this once for each new repo
-exit 0 if @ARGV and $ARGV[0] eq 'POST_CREATE' and not $ARGV[2];
-
-# ----------------------------------------------------------------------
# if called from POST_CREATE, we have only a single repo to worry about
if ( @ARGV and $ARGV[0] eq 'POST_CREATE' ) {
my $repo = $ARGV[1];
@@ -46,12 +39,15 @@ sub fixup_config {
my $creator = creator($pr);
my $gc = git_config( $pr, '.', 1 );
+ my $ac = `git config --file $RB/$pr.git/config -l`;
while ( my ( $key, $value ) = each( %{$gc} ) ) {
next if $key =~ /^gitolite-options\./;
$value =~ s/(@\w+)/expand_group($1)/ge if $rc{EXPAND_GROUPS_IN_CONFIG};
+ my $lkey = lc $key;
+ next if $ac =~ /^\Q$lkey\E=\Q$value\E$/m;
if ( $value ne "" ) {
system( "git", "config", "--file", "$RB/$pr.git/config", $key, $value );
- } else {
+ } elsif ( $ac =~ /^\Q$lkey\E=/m ) {
system( "git", "config", "--file", "$RB/$pr.git/config", "--unset-all", $key );
}
}
diff --git a/src/triggers/post-compile/update-git-daemon-access-list b/src/triggers/post-compile/update-git-daemon-access-list
index 446b0da..ade97a8 100755
--- a/src/triggers/post-compile/update-git-daemon-access-list
+++ b/src/triggers/post-compile/update-git-daemon-access-list
@@ -11,21 +11,20 @@ use Gitolite::Common;
use strict;
use warnings;
-# ----------------------------------------------------------------------
-# skip if arg-0 is POST_CREATE and no arg-2 (user name) exists; this means
-# it's been triggered by a *normal* (not "wild") repo creation, which in turn
-# means a POST_COMPILE should be following so there's no need to waste time
-# running this once for each new repo
-exit 0 if @ARGV and $ARGV[0] eq 'POST_CREATE' and not $ARGV[2];
-
my $EO = "git-daemon-export-ok";
my $RB = $rc{GL_REPO_BASE};
-for my $d (`gitolite list-phy-repos | gitolite access % daemon R any`) {
+my $cmd = "gitolite list-phy-repos";
+if ( @ARGV and $ARGV[0] eq 'POST_CREATE' ) {
+ # only one repo to do
+ $cmd = "echo $ARGV[1]";
+}
+
+for my $d (`$cmd | gitolite access % daemon R any`) {
my @F = split "\t", $d;
if ($F[2] =~ /DENIED/) {
unlink "$RB/$F[0].git/$EO";
- } else {
+ } elsif (! -f "$RB/$F[0].git/$EO") {
textfile( file => $EO, repo => $F[0], text => "" );
}
}
diff --git a/src/triggers/post-compile/update-gitweb-access-list b/src/triggers/post-compile/update-gitweb-access-list
index 937226b..4085d59 100755
--- a/src/triggers/post-compile/update-gitweb-access-list
+++ b/src/triggers/post-compile/update-gitweb-access-list
@@ -11,13 +11,6 @@
# permissions changes for wild repos) and then you should not delete it.
[ "$1" = "POST_CREATE" ] && [ "$4" != "perms" ] && rm -f $GL_REPO_BASE/$2.git/description 2>/dev/null
-# ----------------------------------------------------------------------
-# skip if arg-1 is POST_CREATE and no arg-3 (user name) exists; this means
-# it's been triggered by a *normal* (not "wild") repo creation, which in turn
-# means a POST_COMPILE should be following so there's no need to waste time
-# running this once for each new repo
-[ "$1" = "POST_CREATE" ] && [ -z "$3" ] && exit 0;
-
plf=`gitolite query-rc GITWEB_PROJECTS_LIST`
[ -z "$plf" ] && plf=$HOME/projects.list
# since mktemp does not honor umask, we just use it to generate a temp
@@ -25,11 +18,23 @@ plf=`gitolite query-rc GITWEB_PROJECTS_LIST`
tmpfile=`mktemp $plf.tmp_XXXXXXXX`
rm -f $tmpfile;
-(
- gitolite list-phy-repos | gitolite access % gitweb R any | grep -v DENIED
- gitolite list-phy-repos | gitolite git-config -r % gitweb\\.
-) |
- cut -f1 | sort -u | sed -e 's/$/.git/' > $tmpfile
+if [ "$1" = "POST_CREATE" ] && [ -n "$2" ]
+then
+ # just one to be done
+ repo="$2"
+ grep -v "^$repo.git$" $plf > $tmpfile
+ if gitolite access -q $repo gitweb R any || gitolite git-config -q -r $repo gitweb\\.
+ then
+ echo "$repo.git" >> $tmpfile
+ fi
+else
+ # all of them
+ (
+ gitolite list-phy-repos | gitolite access % gitweb R any | grep -v DENIED
+ gitolite list-phy-repos | gitolite git-config -r % gitweb\\.
+ ) |
+ cut -f1 | sort -u | sed -e 's/$/.git/' > $tmpfile
+fi
[ -f $plf ] && perl -e "chmod ( ( (stat('$plf'))[2] & 07777 ), '$tmpfile')"
mv $tmpfile $plf
diff --git a/src/triggers/post-compile/update-gitweb-daemon-from-options b/src/triggers/post-compile/update-gitweb-daemon-from-options
index 9b499b2..1f5fd26 100755
--- a/src/triggers/post-compile/update-gitweb-daemon-from-options
+++ b/src/triggers/post-compile/update-gitweb-daemon-from-options
@@ -1,5 +1,9 @@
#!/bin/sh
+# TODO: look at the commit in which *this* line was added, and see the changes
+# to the other scripts. We need to make those changes here also, but I'm too
+# lazy right now. Plus I'm not even sure if anyone is using this!
+
# Update git-daemon and gitweb access using 'option' lines instead of special
# usernames.
@@ -21,13 +25,6 @@
# This is useful for people who don't like '@all' to be literally *all* users,
# including gitweb and daemon, and can't/won't use deny-rules properly.
-# ----------------------------------------------------------------------
-# skip if arg-1 is POST_CREATE and no arg-3 (user name) exists; this means
-# it's been triggered by a *normal* (not "wild") repo creation, which in turn
-# means a POST_COMPILE should be following so there's no need to waste time
-# running this once for each new repo
-[ "$1" = "POST_CREATE" ] && [ -z "$3" ] && exit 0;
-
# first do the gitweb stuff
plf=`gitolite query-rc GITWEB_PROJECTS_LIST`
diff --git a/src/triggers/repo-specific-hooks b/src/triggers/repo-specific-hooks
index bba7a58..7c16f2f 100755
--- a/src/triggers/repo-specific-hooks
+++ b/src/triggers/repo-specific-hooks
@@ -41,21 +41,23 @@ while (<>) {
$hook =~ s/\..*//;
my @codes = split /\s+/, $codes;
- next unless @codes;
- # this is a special case
- if ( $repo eq 'gitolite-admin' and $hook eq 'post-update' ) {
- _warn "repo-specific-hooks: ignoring attempts to set post-update hook for the admin repo";
- next;
- }
+ # check for disallowed hook types only if @codes is non-empty
+ if (@codes) {
+ # this is a special case
+ if ( $repo eq 'gitolite-admin' and $hook eq 'post-update' ) {
+ _warn "repo-specific-hooks: ignoring attempts to set post-update hook for the admin repo";
+ next;
+ }
- unless ( $hook =~ /^(pre-receive|post-receive|post-update|pre-auto-gc)$/ ) {
- _warn "repo-specific-hooks: '$hook' is not allowed, ignoring";
- _warn " (only pre-receive, post-receive, post-update, and pre-auto-gc are allowed)";
- next;
+ unless ( $hook =~ /^(pre-receive|post-receive|post-update|pre-auto-gc)$/ ) {
+ _warn "repo-specific-hooks: '$hook' is not allowed, ignoring";
+ _warn " (only pre-receive, post-receive, post-update, and pre-auto-gc are allowed)";
+ next;
+ }
}
- push @{ $repo_hooks{$repo}{$hook} }, @codes if @codes;
+ push @{ $repo_hooks{$repo}{$hook} }, @codes;
}
for my $repo (keys %repo_hooks) {
@@ -111,8 +113,8 @@ for h in $0.*; do
[ -x $h ] || continue
if [ $type = args ]
then
- $h $@
+ $h $@ || { [ $0 = hooks/pre-receive ] && exit 1; }
else
- echo "$stdin" | $h
+ echo "$stdin" | $h || { [ $0 = hooks/pre-receive ] && exit 1; }
fi
done
diff --git a/src/triggers/upstream b/src/triggers/upstream
index c64e2f2..611e11e 100755
--- a/src/triggers/upstream
+++ b/src/triggers/upstream
@@ -32,7 +32,7 @@ git fetch -q "$url" '+refs/*:refs/*'
# R = @all
# RW+ my-company/ = @developers
#
-# option upstream.url = git://git.kernel.org/pub/scm/git/git.git
+# option upstream.url = https://git.kernel.org/pub/scm/git/git.git
# option upstream.nice = 120
#
# * to force a fetch on the server shell (or via cron), run this command:
@@ -55,9 +55,9 @@ git fetch -q "$url" '+refs/*:refs/*'
# repo github/CREATOR/..*
# C = @all
# R = @all
-# option upstream.url = git://github.com/%GL_REPO.git
-# option upstream.nice = 120
-# config url.git://github.com/.insteadOf = git://github.com/github/
+# option upstream.url = https://github.com/%GL_REPO.git
+# option upstream.nice = 120
+# config url.https://github.com/.insteadOf = https://github.com/github/
#
# Now you can make local, read-only, clones of all your github repos with
#
diff --git a/t/access.t b/t/access.t
index c6c7b22..c3f3341 100755
--- a/t/access.t
+++ b/t/access.t
@@ -9,7 +9,7 @@ use Gitolite::Test;
# test 'gitolite access'
# ----------------------------------------------------------------------
-try "plan 216";
+try "plan 254";
confreset;confadd '
@admins = admin dev1
@@ -200,3 +200,54 @@ try "
gitolite access c1 u2 +; ok
gitolite access c1 u2 C; !ok
";
+
+confreset;confadd '
+ repo foo
+ R = u1
+ RW = u2
+ RW+ = u3
+
+ repo bar
+ R = u1
+ RW = u2
+ RW+ = u3
+ RW+CDM = u6
+
+';
+
+try "ADMIN_PUSH set4; !/FATAL/" or die text();
+
+try "
+ gitolite access foo u1 +; !ok
+ gitolite access foo u2 +; !ok
+ gitolite access foo u3 +; ok
+ gitolite access foo u1 C; !ok
+ gitolite access foo u2 C; ok
+ gitolite access foo u3 C; ok
+ gitolite access foo u1 D; !ok
+ gitolite access foo u2 D; !ok
+ gitolite access foo u3 D; ok
+ gitolite access foo u1 M; !ok
+ gitolite access foo u2 M; ok
+ gitolite access foo u3 M; ok
+
+ gitolite access bar u1 +; !ok
+ gitolite access bar u2 +; !ok
+ gitolite access bar u3 +; ok
+ gitolite access bar u1 C; !ok
+ gitolite access bar u2 C; !ok
+ gitolite access bar u3 C; !ok
+ gitolite access bar u1 D; !ok
+ gitolite access bar u2 D; !ok
+ gitolite access bar u3 D; !ok
+ gitolite access bar u1 M; !ok
+ gitolite access bar u2 M; !ok
+ gitolite access bar u3 M; !ok
+
+ gitolite access bar u6 R; ok
+ gitolite access bar u6 W; ok
+ gitolite access bar u6 +; ok
+ gitolite access bar u6 C; ok
+ gitolite access bar u6 D; ok
+ gitolite access bar u6 M; ok
+";
diff --git a/t/mirror-test b/t/mirror-test
index 627dc74..e0c4e36 100755
--- a/t/mirror-test
+++ b/t/mirror-test
@@ -91,7 +91,7 @@ try "
git add keydir; ok
git commit -m 6keys; ok
git push; ok
- /To frodo\@localhost:gitolite-admin/
+ /To localhost:gitolite-admin/
/master -> master/
sleep 5
git rev-parse HEAD
@@ -118,7 +118,7 @@ try "
cd sga; ok
empty; ok
git push; ok
- /To sam\@localhost:gitolite-admin/
+ /To localhost:gitolite-admin/
/master -> master/
sleep 5
git rev-parse HEAD
@@ -145,7 +145,7 @@ try "
cd gga; ok
empty; ok
git push; !ok
- !/To gollum\@localhost:gitolite-admin/
+ !/To localhost:gitolite-admin/
!/master -> master/
/gollum: pushing 'gitolite-admin' to slave 'gollum' not allowed/
git rev-parse HEAD
@@ -193,7 +193,7 @@ try "
cd fga; ok
empty; ok
git push; ok
- /To frodo\@localhost:gitolite-admin/
+ /To localhost:gitolite-admin/
/master -> master/
sleep 5
diff --git a/t/partial-copy.t b/t/partial-copy.t
index 5bff843..493f0d4 100755
--- a/t/partial-copy.t
+++ b/t/partial-copy.t
@@ -95,7 +95,7 @@ try "
/52c7716..ca37871 next -> next/
tag u4/nexttag; glt push u4 --tags
/To file:///foo-pc/
- /\\[new tag\\] u4/nexttag -> u4/nexttag/
+ /\\[new tag\\] u4/nexttag +-> +u4/nexttag/
/\\[new branch\\] ca3787119b7e8b9914bc22c939cefc443bc308da -> refs/partial/br-\\d+/
checkout master
@@ -112,8 +112,8 @@ try "
glt fetch u1
/From file:///foo/
/new branch\\] dev/u4/u4master -> origin/dev/u4/u4master/
- /new tag\\] u4/nexttag -> u4/nexttag/
- /52c7716..ca37871 next -> origin/next/
+ /new tag\\] u4/nexttag +-> +u4/nexttag/
+ /52c7716..ca37871 next +-> +origin/next/
checkout master; tc u1ma1 u1ma2;
/\\[master 8ab1ff5\\] u1ma2 at Thu Jul 7 06:23:20 2011/
tag mt2; PUSH u1 master; ok
diff --git a/t/repo-specific-hooks.t b/t/repo-specific-hooks.t
index 6cacdb2..90a23c6 100755
--- a/t/repo-specific-hooks.t
+++ b/t/repo-specific-hooks.t
@@ -173,10 +173,10 @@ try "
# Verify hooks are removed properly
-confreset;confadd '
+confadd '
repo foo
RW+ = @all
- option hook.post-receive =
+ option hook.post-receive = ""
repo bar
RW+ = @all
@@ -184,17 +184,17 @@ confreset;confadd '
repo baz
RW+ = @all
- option hook.post-receive =
+ option hook.post-receive = ""
option hook.post-update = second
';
try "ADMIN_PUSH repo-specific-hooks-02; !/FATAL/" or die text();
try "
- ls $rb/foo.git/hooks/*; ok; !/post-receive/
+ ls $rb/foo.git/hooks/*; ok; !/post-receive.h0/
ls $rb/bar.git/hooks/*; ok; !/pre-receive.*first/
/pre-receive.h00-second/
- ls $rb/baz.git/hooks/*; ok; !/post-receive/
+ ls $rb/baz.git/hooks/*; ok; !/post-receive.h0/
!/post-update.*first/
/post-update.h00-second/
";
@@ -216,7 +216,7 @@ try "
PUSH admin master; ok; /master -. master/
/hooks/pre-receive.h00-second/
!/hooks/pre-receive.*has args:/
- /hooks/pre-receive.h00-second has stdin: 0000000000000000000000000000000000000000 cc7808f77c7c7d705f82dc54dc3152146175768f refs/heads/master/
+ /hooks/pre-receive.h00-second has stdin: cfc8561c7827a8b94df6c5dad156383d4cb210f5 cc7808f77c7c7d705f82dc54dc3152146175768f refs/heads/master/
cd ..
diff --git a/t/smart-http b/t/smart-http
index 98fc8c0..9ae6d5b 100755
--- a/t/smart-http
+++ b/t/smart-http
@@ -63,7 +63,7 @@ tsh "
git push
ok
/Initialized.*usr.share.httpd.gitolite-home.repositories.t2.git/
- /To http:..admin:admin.localhost.git.gitolite-admin.git/
+ /To http:..localhost.git.gitolite-admin.git/
/master -. master/
## various ls-remotes
git ls-remote `url u1 gitolite-admin`
@@ -81,7 +81,7 @@ tsh "
## push to u1:t2
git push `url u1 t2` master:master
ok
- /To http:..u1:u1.localhost.git.t2.git/
+ /To http:..localhost.git.t2.git/
/master -. master/
git ls-remote `url u2 t2`
ok
diff --git a/t/smart-http.root-setup b/t/smart-http.root-setup
index 7a46dda..f22dcb5 100755
--- a/t/smart-http.root-setup
+++ b/t/smart-http.root-setup
@@ -51,7 +51,7 @@ export GITOLITE_HTTP_HOME=$PWD/gitolite-home
cd gitolite-home
git clone /tmp/gitolite.git gitolite-source
# NOTE: I use a bare repo in /tmp for convenience; you'd use
-# 'git://github.com/sitaramc/gitolite'
+# 'https://github.com/sitaramc/gitolite'
# make the bin directory, and add it to PATH
cd gitolite-source
diff --git a/t/templates.t b/t/templates.t
new file mode 100755
index 0000000..a705167
--- /dev/null
+++ b/t/templates.t
@@ -0,0 +1,1322 @@
+#!/usr/bin/perl
+use strict;
+use warnings;
+use 5.10.0;
+use Data::Dumper;
+
+# this is hardcoded; change it if needed
+use lib "$ENV{PWD}/src/lib";
+
+use Gitolite::Test;
+
+BEGIN {
+ $ENV{G3T_RC} = "$ENV{HOME}/g3trc";
+ put "$ENV{G3T_RC}", "\$rc{ROLES} = {
+ FORCERS => 1,
+ MASTERS => 1,
+ READERS => 1,
+ ROOT => 1,
+ TEAM => 1,
+ WRITERS => 1
+ }";
+}
+
+use Gitolite::Rc;
+use Gitolite::Common;
+use Gitolite::Conf::Load;
+
+# permissions using role names
+# ----------------------------------------------------------------------
+
+try "plan 1163";
+try "DEF POK = !/DENIED/; !/failed to push/";
+
+# basic push admin repo
+confreset; confadd '
+# order is important for these next few repo group definitions, because an
+# individual repo may pick and choose any combination of them, and they should
+# apply sensibly. In this example, "BASE" is pretty much required; the others
+# are optional.
+
+# if you want someone to have "ultimate" power over all refs in the repo,
+# add them to the ROOT role.
+repo @BASE
+ RW+CD = ROOT
+
+# add this to the repo group list to allow personal branches
+repo @PERSONAL
+ RW+CD dev/USER/ = TEAM
+ - dev/ = TEAM
+ RW+CD refs/tags/dev/USER/ = TEAM
+ - refs/tags/dev/ = TEAM
+
+# add this to the repo group list to control tagging for release versions
+repo @RELEASES
+ RWC refs/tags/v[0-9] = RELEASERS
+ - refs/tags/v[0-9] = @all
+
+# (the basic set of access rules continues)
+repo @BASE
+ # Note that "FORCERS" here, even though they have RW+CD,
+ # 1. cannot touch other users personal branches or tags if you added
+ # PER_BR to the repo group list, and
+ # 2. create a release tag unless they are also in RELEASE_TAGGERS if
+ # you added TAGS to the repo group list
+ RW+CD = FORCERS
+ RWC master = MASTERS
+ - master = @all
+ RWC = RELEASERS MASTERS WRITERS
+ # Note you can define "@all" to have the READERS role, and then this will
+ # effectively be public (albeit authenticated public) readable.
+ R = READERS
+
+=begin template-data
+
+repo base = BASE
+ FORCERS = u1
+ MASTERS = u2
+ WRITERS = u3
+ READERS = u4
+
+repo baseroot = BASE
+ ROOT = admin
+ FORCERS = u1
+ MASTERS = u2
+ WRITERS = u3
+ READERS = u4
+
+repo basepers = BASE PERSONAL
+ FORCERS = u1
+ MASTERS = u2
+ WRITERS = u3
+ READERS = u4 u5
+ TEAM = u1 u2 u3 u5 u6
+
+repo baserel = BASE RELEASES
+ FORCERS = u1
+ MASTERS = u2
+ WRITERS = u3
+ READERS = u4 u5
+ TEAM = u1 u2 u3 u5 u6
+
+repo baseall = BASE PERSONAL RELEASES
+ ROOT = admin
+ FORCERS = u1
+ MASTERS = u2
+ WRITERS = u3
+ READERS = u4 u5
+ TEAM = u1 u2 u3 u5 u6
+
+=end
+';
+
+try "ADMIN_PUSH set1; !/FATAL/" or die text();
+
+# now we step outside tsh, into pure perl
+
+sub _access {
+ push @_, 'any' if @_ < 4;
+ my $ref = pop;
+ $ref =~ s(^)(refs/heads/) if $ref ne 'any' and $ref !~ m(^(refs|VREF)/);
+ push @_, $ref;
+
+ return access(@_);
+}
+
+sub ok {
+ say STDOUT (_access(@_) !~ /DENIED/ ? "ok" : "not ok");
+}
+sub nok {
+ say STDOUT (_access(@_) =~ /DENIED/ ? "ok" : "not ok");
+}
+
+nok qw( base admin R );
+nok qw( base admin W master );
+nok qw( base admin W notmaster );
+nok qw( base admin W refs/tags/boo );
+nok qw( base admin W refs/tags/v1 );
+nok qw( base admin W dev/admin/foo );
+nok qw( base admin W refs/tags/dev/admin/foo );
+nok qw( base admin W dev/alice/foo );
+nok qw( base admin W refs/tags/dev/alice/foo );
+nok qw( base admin + master );
+nok qw( base admin + notmaster );
+nok qw( base admin + refs/tags/boo );
+nok qw( base admin + refs/tags/v1 );
+nok qw( base admin + dev/admin/foo );
+nok qw( base admin + refs/tags/dev/admin/foo );
+nok qw( base admin + dev/alice/foo );
+nok qw( base admin + refs/tags/dev/alice/foo );
+nok qw( base admin C master );
+nok qw( base admin C notmaster );
+nok qw( base admin C refs/tags/boo );
+nok qw( base admin C refs/tags/v1 );
+nok qw( base admin C dev/admin/foo );
+nok qw( base admin C refs/tags/dev/admin/foo );
+nok qw( base admin C dev/alice/foo );
+nok qw( base admin C refs/tags/dev/alice/foo );
+nok qw( base admin D master );
+nok qw( base admin D notmaster );
+nok qw( base admin D refs/tags/boo );
+nok qw( base admin D refs/tags/v1 );
+nok qw( base admin D dev/admin/foo );
+nok qw( base admin D refs/tags/dev/admin/foo );
+nok qw( base admin D dev/alice/foo );
+nok qw( base admin D refs/tags/dev/alice/foo );
+
+ok qw( base u1 R );
+ok qw( base u1 W master );
+ok qw( base u1 W notmaster );
+ok qw( base u1 W refs/tags/boo );
+ok qw( base u1 W refs/tags/v1 );
+ok qw( base u1 W dev/u1/foo );
+ok qw( base u1 W refs/tags/dev/u1/foo );
+ok qw( base u1 W dev/alice/foo );
+ok qw( base u1 W refs/tags/dev/alice/foo );
+ok qw( base u1 + master );
+ok qw( base u1 + notmaster );
+ok qw( base u1 + refs/tags/boo );
+ok qw( base u1 + refs/tags/v1 );
+ok qw( base u1 + dev/u1/foo );
+ok qw( base u1 + refs/tags/dev/u1/foo );
+ok qw( base u1 + dev/alice/foo );
+ok qw( base u1 + refs/tags/dev/alice/foo );
+ok qw( base u1 C master );
+ok qw( base u1 C notmaster );
+ok qw( base u1 C refs/tags/boo );
+ok qw( base u1 C refs/tags/v1 );
+ok qw( base u1 C dev/u1/foo );
+ok qw( base u1 C refs/tags/dev/u1/foo );
+ok qw( base u1 C dev/alice/foo );
+ok qw( base u1 C refs/tags/dev/alice/foo );
+ok qw( base u1 D master );
+ok qw( base u1 D notmaster );
+ok qw( base u1 D refs/tags/boo );
+ok qw( base u1 D refs/tags/v1 );
+ok qw( base u1 D dev/u1/foo );
+ok qw( base u1 D refs/tags/dev/u1/foo );
+ok qw( base u1 D dev/alice/foo );
+ok qw( base u1 D refs/tags/dev/alice/foo );
+
+ok qw( base u2 R );
+ok qw( base u2 W master );
+ok qw( base u2 W notmaster );
+ok qw( base u2 W refs/tags/boo );
+ok qw( base u2 W refs/tags/v1 );
+ok qw( base u2 W dev/u2/foo );
+ok qw( base u2 W refs/tags/dev/u2/foo );
+ok qw( base u2 W dev/alice/foo );
+ok qw( base u2 W refs/tags/dev/alice/foo );
+nok qw( base u2 + master );
+nok qw( base u2 + notmaster );
+nok qw( base u2 + refs/tags/boo );
+nok qw( base u2 + refs/tags/v1 );
+nok qw( base u2 + dev/u2/foo );
+nok qw( base u2 + refs/tags/dev/u2/foo );
+nok qw( base u2 + dev/alice/foo );
+nok qw( base u2 + refs/tags/dev/alice/foo );
+ok qw( base u2 C master );
+ok qw( base u2 C notmaster );
+ok qw( base u2 C refs/tags/boo );
+ok qw( base u2 C refs/tags/v1 );
+ok qw( base u2 C dev/u2/foo );
+ok qw( base u2 C refs/tags/dev/u2/foo );
+ok qw( base u2 C dev/alice/foo );
+ok qw( base u2 C refs/tags/dev/alice/foo );
+nok qw( base u2 D master );
+nok qw( base u2 D notmaster );
+nok qw( base u2 D refs/tags/boo );
+nok qw( base u2 D refs/tags/v1 );
+nok qw( base u2 D dev/u2/foo );
+nok qw( base u2 D refs/tags/dev/u2/foo );
+nok qw( base u2 D dev/alice/foo );
+nok qw( base u2 D refs/tags/dev/alice/foo );
+
+ok qw( base u3 R );
+nok qw( base u3 W master );
+ok qw( base u3 W notmaster );
+ok qw( base u3 W refs/tags/boo );
+ok qw( base u3 W refs/tags/v1 );
+ok qw( base u3 W dev/u3/foo );
+ok qw( base u3 W refs/tags/dev/u3/foo );
+ok qw( base u3 W dev/alice/foo );
+ok qw( base u3 W refs/tags/dev/alice/foo );
+nok qw( base u3 + master );
+nok qw( base u3 + notmaster );
+nok qw( base u3 + refs/tags/boo );
+nok qw( base u3 + refs/tags/v1 );
+nok qw( base u3 + dev/u3/foo );
+nok qw( base u3 + refs/tags/dev/u3/foo );
+nok qw( base u3 + dev/alice/foo );
+nok qw( base u3 + refs/tags/dev/alice/foo );
+nok qw( base u3 C master );
+ok qw( base u3 C notmaster );
+ok qw( base u3 C refs/tags/boo );
+ok qw( base u3 C refs/tags/v1 );
+ok qw( base u3 C dev/u3/foo );
+ok qw( base u3 C refs/tags/dev/u3/foo );
+ok qw( base u3 C dev/alice/foo );
+ok qw( base u3 C refs/tags/dev/alice/foo );
+nok qw( base u3 D master );
+nok qw( base u3 D notmaster );
+nok qw( base u3 D refs/tags/boo );
+nok qw( base u3 D refs/tags/v1 );
+nok qw( base u3 D dev/u3/foo );
+nok qw( base u3 D refs/tags/dev/u3/foo );
+nok qw( base u3 D dev/alice/foo );
+nok qw( base u3 D refs/tags/dev/alice/foo );
+
+ok qw( base u4 R );
+nok qw( base u4 W master );
+nok qw( base u4 W notmaster );
+nok qw( base u4 W refs/tags/boo );
+nok qw( base u4 W refs/tags/v1 );
+nok qw( base u4 W dev/u4/foo );
+nok qw( base u4 W refs/tags/dev/u4/foo );
+nok qw( base u4 W dev/alice/foo );
+nok qw( base u4 W refs/tags/dev/alice/foo );
+nok qw( base u4 + master );
+nok qw( base u4 + notmaster );
+nok qw( base u4 + refs/tags/boo );
+nok qw( base u4 + refs/tags/v1 );
+nok qw( base u4 + dev/u4/foo );
+nok qw( base u4 + refs/tags/dev/u4/foo );
+nok qw( base u4 + dev/alice/foo );
+nok qw( base u4 + refs/tags/dev/alice/foo );
+nok qw( base u4 C master );
+nok qw( base u4 C notmaster );
+nok qw( base u4 C refs/tags/boo );
+nok qw( base u4 C refs/tags/v1 );
+nok qw( base u4 C dev/u4/foo );
+nok qw( base u4 C refs/tags/dev/u4/foo );
+nok qw( base u4 C dev/alice/foo );
+nok qw( base u4 C refs/tags/dev/alice/foo );
+nok qw( base u4 D master );
+nok qw( base u4 D notmaster );
+nok qw( base u4 D refs/tags/boo );
+nok qw( base u4 D refs/tags/v1 );
+nok qw( base u4 D dev/u4/foo );
+nok qw( base u4 D refs/tags/dev/u4/foo );
+nok qw( base u4 D dev/alice/foo );
+nok qw( base u4 D refs/tags/dev/alice/foo );
+
+nok qw( base u5 R );
+nok qw( base u5 W master );
+nok qw( base u5 W notmaster );
+nok qw( base u5 W refs/tags/boo );
+nok qw( base u5 W refs/tags/v1 );
+nok qw( base u5 W dev/u5/foo );
+nok qw( base u5 W refs/tags/dev/u5/foo );
+nok qw( base u5 W dev/alice/foo );
+nok qw( base u5 W refs/tags/dev/alice/foo );
+nok qw( base u5 + master );
+nok qw( base u5 + notmaster );
+nok qw( base u5 + refs/tags/boo );
+nok qw( base u5 + refs/tags/v1 );
+nok qw( base u5 + dev/u5/foo );
+nok qw( base u5 + refs/tags/dev/u5/foo );
+nok qw( base u5 + dev/alice/foo );
+nok qw( base u5 + refs/tags/dev/alice/foo );
+nok qw( base u5 C master );
+nok qw( base u5 C notmaster );
+nok qw( base u5 C refs/tags/boo );
+nok qw( base u5 C refs/tags/v1 );
+nok qw( base u5 C dev/u5/foo );
+nok qw( base u5 C refs/tags/dev/u5/foo );
+nok qw( base u5 C dev/alice/foo );
+nok qw( base u5 C refs/tags/dev/alice/foo );
+nok qw( base u5 D master );
+nok qw( base u5 D notmaster );
+nok qw( base u5 D refs/tags/boo );
+nok qw( base u5 D refs/tags/v1 );
+nok qw( base u5 D dev/u5/foo );
+nok qw( base u5 D refs/tags/dev/u5/foo );
+nok qw( base u5 D dev/alice/foo );
+nok qw( base u5 D refs/tags/dev/alice/foo );
+
+nok qw( base u6 R );
+nok qw( base u6 W master );
+nok qw( base u6 W notmaster );
+nok qw( base u6 W refs/tags/boo );
+nok qw( base u6 W refs/tags/v1 );
+nok qw( base u6 W dev/u6/foo );
+nok qw( base u6 W refs/tags/dev/u6/foo );
+nok qw( base u6 W dev/alice/foo );
+nok qw( base u6 W refs/tags/dev/alice/foo );
+nok qw( base u6 + master );
+nok qw( base u6 + notmaster );
+nok qw( base u6 + refs/tags/boo );
+nok qw( base u6 + refs/tags/v1 );
+nok qw( base u6 + dev/u6/foo );
+nok qw( base u6 + refs/tags/dev/u6/foo );
+nok qw( base u6 + dev/alice/foo );
+nok qw( base u6 + refs/tags/dev/alice/foo );
+nok qw( base u6 C master );
+nok qw( base u6 C notmaster );
+nok qw( base u6 C refs/tags/boo );
+nok qw( base u6 C refs/tags/v1 );
+nok qw( base u6 C dev/u6/foo );
+nok qw( base u6 C refs/tags/dev/u6/foo );
+nok qw( base u6 C dev/alice/foo );
+nok qw( base u6 C refs/tags/dev/alice/foo );
+nok qw( base u6 D master );
+nok qw( base u6 D notmaster );
+nok qw( base u6 D refs/tags/boo );
+nok qw( base u6 D refs/tags/v1 );
+nok qw( base u6 D dev/u6/foo );
+nok qw( base u6 D refs/tags/dev/u6/foo );
+nok qw( base u6 D dev/alice/foo );
+nok qw( base u6 D refs/tags/dev/alice/foo );
+
+ok qw( baseroot admin R );
+ok qw( baseroot admin W master );
+ok qw( baseroot admin W notmaster );
+ok qw( baseroot admin W refs/tags/boo );
+ok qw( baseroot admin W refs/tags/v1 );
+ok qw( baseroot admin W dev/admin/foo );
+ok qw( baseroot admin W refs/tags/dev/admin/foo );
+ok qw( baseroot admin W dev/alice/foo );
+ok qw( baseroot admin W refs/tags/dev/alice/foo );
+ok qw( baseroot admin + master );
+ok qw( baseroot admin + notmaster );
+ok qw( baseroot admin + refs/tags/boo );
+ok qw( baseroot admin + refs/tags/v1 );
+ok qw( baseroot admin + dev/admin/foo );
+ok qw( baseroot admin + refs/tags/dev/admin/foo );
+ok qw( baseroot admin + dev/alice/foo );
+ok qw( baseroot admin + refs/tags/dev/alice/foo );
+ok qw( baseroot admin C master );
+ok qw( baseroot admin C notmaster );
+ok qw( baseroot admin C refs/tags/boo );
+ok qw( baseroot admin C refs/tags/v1 );
+ok qw( baseroot admin C dev/admin/foo );
+ok qw( baseroot admin C refs/tags/dev/admin/foo );
+ok qw( baseroot admin C dev/alice/foo );
+ok qw( baseroot admin C refs/tags/dev/alice/foo );
+ok qw( baseroot admin D master );
+ok qw( baseroot admin D notmaster );
+ok qw( baseroot admin D refs/tags/boo );
+ok qw( baseroot admin D refs/tags/v1 );
+ok qw( baseroot admin D dev/admin/foo );
+ok qw( baseroot admin D refs/tags/dev/admin/foo );
+ok qw( baseroot admin D dev/alice/foo );
+ok qw( baseroot admin D refs/tags/dev/alice/foo );
+
+ok qw( baseroot u1 R );
+ok qw( baseroot u1 W master );
+ok qw( baseroot u1 W notmaster );
+ok qw( baseroot u1 W refs/tags/boo );
+ok qw( baseroot u1 W refs/tags/v1 );
+ok qw( baseroot u1 W dev/u1/foo );
+ok qw( baseroot u1 W refs/tags/dev/u1/foo );
+ok qw( baseroot u1 W dev/alice/foo );
+ok qw( baseroot u1 W refs/tags/dev/alice/foo );
+ok qw( baseroot u1 + master );
+ok qw( baseroot u1 + notmaster );
+ok qw( baseroot u1 + refs/tags/boo );
+ok qw( baseroot u1 + refs/tags/v1 );
+ok qw( baseroot u1 + dev/u1/foo );
+ok qw( baseroot u1 + refs/tags/dev/u1/foo );
+ok qw( baseroot u1 + dev/alice/foo );
+ok qw( baseroot u1 + refs/tags/dev/alice/foo );
+ok qw( baseroot u1 C master );
+ok qw( baseroot u1 C notmaster );
+ok qw( baseroot u1 C refs/tags/boo );
+ok qw( baseroot u1 C refs/tags/v1 );
+ok qw( baseroot u1 C dev/u1/foo );
+ok qw( baseroot u1 C refs/tags/dev/u1/foo );
+ok qw( baseroot u1 C dev/alice/foo );
+ok qw( baseroot u1 C refs/tags/dev/alice/foo );
+ok qw( baseroot u1 D master );
+ok qw( baseroot u1 D notmaster );
+ok qw( baseroot u1 D refs/tags/boo );
+ok qw( baseroot u1 D refs/tags/v1 );
+ok qw( baseroot u1 D dev/u1/foo );
+ok qw( baseroot u1 D refs/tags/dev/u1/foo );
+ok qw( baseroot u1 D dev/alice/foo );
+ok qw( baseroot u1 D refs/tags/dev/alice/foo );
+
+ok qw( baseroot u2 R );
+ok qw( baseroot u2 W master );
+ok qw( baseroot u2 W notmaster );
+ok qw( baseroot u2 W refs/tags/boo );
+ok qw( baseroot u2 W refs/tags/v1 );
+ok qw( baseroot u2 W dev/u2/foo );
+ok qw( baseroot u2 W refs/tags/dev/u2/foo );
+ok qw( baseroot u2 W dev/alice/foo );
+ok qw( baseroot u2 W refs/tags/dev/alice/foo );
+nok qw( baseroot u2 + master );
+nok qw( baseroot u2 + notmaster );
+nok qw( baseroot u2 + refs/tags/boo );
+nok qw( baseroot u2 + refs/tags/v1 );
+nok qw( baseroot u2 + dev/u2/foo );
+nok qw( baseroot u2 + refs/tags/dev/u2/foo );
+nok qw( baseroot u2 + dev/alice/foo );
+nok qw( baseroot u2 + refs/tags/dev/alice/foo );
+ok qw( baseroot u2 C master );
+ok qw( baseroot u2 C notmaster );
+ok qw( baseroot u2 C refs/tags/boo );
+ok qw( baseroot u2 C refs/tags/v1 );
+ok qw( baseroot u2 C dev/u2/foo );
+ok qw( baseroot u2 C refs/tags/dev/u2/foo );
+ok qw( baseroot u2 C dev/alice/foo );
+ok qw( baseroot u2 C refs/tags/dev/alice/foo );
+nok qw( baseroot u2 D master );
+nok qw( baseroot u2 D notmaster );
+nok qw( baseroot u2 D refs/tags/boo );
+nok qw( baseroot u2 D refs/tags/v1 );
+nok qw( baseroot u2 D dev/u2/foo );
+nok qw( baseroot u2 D refs/tags/dev/u2/foo );
+nok qw( baseroot u2 D dev/alice/foo );
+nok qw( baseroot u2 D refs/tags/dev/alice/foo );
+
+ok qw( baseroot u3 R );
+nok qw( baseroot u3 W master );
+ok qw( baseroot u3 W notmaster );
+ok qw( baseroot u3 W refs/tags/boo );
+ok qw( baseroot u3 W refs/tags/v1 );
+ok qw( baseroot u3 W dev/u3/foo );
+ok qw( baseroot u3 W refs/tags/dev/u3/foo );
+ok qw( baseroot u3 W dev/alice/foo );
+ok qw( baseroot u3 W refs/tags/dev/alice/foo );
+nok qw( baseroot u3 + master );
+nok qw( baseroot u3 + notmaster );
+nok qw( baseroot u3 + refs/tags/boo );
+nok qw( baseroot u3 + refs/tags/v1 );
+nok qw( baseroot u3 + dev/u3/foo );
+nok qw( baseroot u3 + refs/tags/dev/u3/foo );
+nok qw( baseroot u3 + dev/alice/foo );
+nok qw( baseroot u3 + refs/tags/dev/alice/foo );
+nok qw( baseroot u3 C master );
+ok qw( baseroot u3 C notmaster );
+ok qw( baseroot u3 C refs/tags/boo );
+ok qw( baseroot u3 C refs/tags/v1 );
+ok qw( baseroot u3 C dev/u3/foo );
+ok qw( baseroot u3 C refs/tags/dev/u3/foo );
+ok qw( baseroot u3 C dev/alice/foo );
+ok qw( baseroot u3 C refs/tags/dev/alice/foo );
+nok qw( baseroot u3 D master );
+nok qw( baseroot u3 D notmaster );
+nok qw( baseroot u3 D refs/tags/boo );
+nok qw( baseroot u3 D refs/tags/v1 );
+nok qw( baseroot u3 D dev/u3/foo );
+nok qw( baseroot u3 D refs/tags/dev/u3/foo );
+nok qw( baseroot u3 D dev/alice/foo );
+nok qw( baseroot u3 D refs/tags/dev/alice/foo );
+
+ok qw( baseroot u4 R );
+nok qw( baseroot u4 W master );
+nok qw( baseroot u4 W notmaster );
+nok qw( baseroot u4 W refs/tags/boo );
+nok qw( baseroot u4 W refs/tags/v1 );
+nok qw( baseroot u4 W dev/u4/foo );
+nok qw( baseroot u4 W refs/tags/dev/u4/foo );
+nok qw( baseroot u4 W dev/alice/foo );
+nok qw( baseroot u4 W refs/tags/dev/alice/foo );
+nok qw( baseroot u4 + master );
+nok qw( baseroot u4 + notmaster );
+nok qw( baseroot u4 + refs/tags/boo );
+nok qw( baseroot u4 + refs/tags/v1 );
+nok qw( baseroot u4 + dev/u4/foo );
+nok qw( baseroot u4 + refs/tags/dev/u4/foo );
+nok qw( baseroot u4 + dev/alice/foo );
+nok qw( baseroot u4 + refs/tags/dev/alice/foo );
+nok qw( baseroot u4 C master );
+nok qw( baseroot u4 C notmaster );
+nok qw( baseroot u4 C refs/tags/boo );
+nok qw( baseroot u4 C refs/tags/v1 );
+nok qw( baseroot u4 C dev/u4/foo );
+nok qw( baseroot u4 C refs/tags/dev/u4/foo );
+nok qw( baseroot u4 C dev/alice/foo );
+nok qw( baseroot u4 C refs/tags/dev/alice/foo );
+nok qw( baseroot u4 D master );
+nok qw( baseroot u4 D notmaster );
+nok qw( baseroot u4 D refs/tags/boo );
+nok qw( baseroot u4 D refs/tags/v1 );
+nok qw( baseroot u4 D dev/u4/foo );
+nok qw( baseroot u4 D refs/tags/dev/u4/foo );
+nok qw( baseroot u4 D dev/alice/foo );
+nok qw( baseroot u4 D refs/tags/dev/alice/foo );
+
+nok qw( baseroot u5 R );
+nok qw( baseroot u5 W master );
+nok qw( baseroot u5 W notmaster );
+nok qw( baseroot u5 W refs/tags/boo );
+nok qw( baseroot u5 W refs/tags/v1 );
+nok qw( baseroot u5 W dev/u5/foo );
+nok qw( baseroot u5 W refs/tags/dev/u5/foo );
+nok qw( baseroot u5 W dev/alice/foo );
+nok qw( baseroot u5 W refs/tags/dev/alice/foo );
+nok qw( baseroot u5 + master );
+nok qw( baseroot u5 + notmaster );
+nok qw( baseroot u5 + refs/tags/boo );
+nok qw( baseroot u5 + refs/tags/v1 );
+nok qw( baseroot u5 + dev/u5/foo );
+nok qw( baseroot u5 + refs/tags/dev/u5/foo );
+nok qw( baseroot u5 + dev/alice/foo );
+nok qw( baseroot u5 + refs/tags/dev/alice/foo );
+nok qw( baseroot u5 C master );
+nok qw( baseroot u5 C notmaster );
+nok qw( baseroot u5 C refs/tags/boo );
+nok qw( baseroot u5 C refs/tags/v1 );
+nok qw( baseroot u5 C dev/u5/foo );
+nok qw( baseroot u5 C refs/tags/dev/u5/foo );
+nok qw( baseroot u5 C dev/alice/foo );
+nok qw( baseroot u5 C refs/tags/dev/alice/foo );
+nok qw( baseroot u5 D master );
+nok qw( baseroot u5 D notmaster );
+nok qw( baseroot u5 D refs/tags/boo );
+nok qw( baseroot u5 D refs/tags/v1 );
+nok qw( baseroot u5 D dev/u5/foo );
+nok qw( baseroot u5 D refs/tags/dev/u5/foo );
+nok qw( baseroot u5 D dev/alice/foo );
+nok qw( baseroot u5 D refs/tags/dev/alice/foo );
+
+nok qw( baseroot u6 R );
+nok qw( baseroot u6 W master );
+nok qw( baseroot u6 W notmaster );
+nok qw( baseroot u6 W refs/tags/boo );
+nok qw( baseroot u6 W refs/tags/v1 );
+nok qw( baseroot u6 W dev/u6/foo );
+nok qw( baseroot u6 W refs/tags/dev/u6/foo );
+nok qw( baseroot u6 W dev/alice/foo );
+nok qw( baseroot u6 W refs/tags/dev/alice/foo );
+nok qw( baseroot u6 + master );
+nok qw( baseroot u6 + notmaster );
+nok qw( baseroot u6 + refs/tags/boo );
+nok qw( baseroot u6 + refs/tags/v1 );
+nok qw( baseroot u6 + dev/u6/foo );
+nok qw( baseroot u6 + refs/tags/dev/u6/foo );
+nok qw( baseroot u6 + dev/alice/foo );
+nok qw( baseroot u6 + refs/tags/dev/alice/foo );
+nok qw( baseroot u6 C master );
+nok qw( baseroot u6 C notmaster );
+nok qw( baseroot u6 C refs/tags/boo );
+nok qw( baseroot u6 C refs/tags/v1 );
+nok qw( baseroot u6 C dev/u6/foo );
+nok qw( baseroot u6 C refs/tags/dev/u6/foo );
+nok qw( baseroot u6 C dev/alice/foo );
+nok qw( baseroot u6 C refs/tags/dev/alice/foo );
+nok qw( baseroot u6 D master );
+nok qw( baseroot u6 D notmaster );
+nok qw( baseroot u6 D refs/tags/boo );
+nok qw( baseroot u6 D refs/tags/v1 );
+nok qw( baseroot u6 D dev/u6/foo );
+nok qw( baseroot u6 D refs/tags/dev/u6/foo );
+nok qw( baseroot u6 D dev/alice/foo );
+nok qw( baseroot u6 D refs/tags/dev/alice/foo );
+
+nok qw( basepers admin R );
+nok qw( basepers admin W master );
+nok qw( basepers admin W notmaster );
+nok qw( basepers admin W refs/tags/boo );
+nok qw( basepers admin W refs/tags/v1 );
+nok qw( basepers admin W dev/admin/foo );
+nok qw( basepers admin W refs/tags/dev/admin/foo );
+nok qw( basepers admin W dev/alice/foo );
+nok qw( basepers admin W refs/tags/dev/alice/foo );
+nok qw( basepers admin + master );
+nok qw( basepers admin + notmaster );
+nok qw( basepers admin + refs/tags/boo );
+nok qw( basepers admin + refs/tags/v1 );
+nok qw( basepers admin + dev/admin/foo );
+nok qw( basepers admin + refs/tags/dev/admin/foo );
+nok qw( basepers admin + dev/alice/foo );
+nok qw( basepers admin + refs/tags/dev/alice/foo );
+nok qw( basepers admin C master );
+nok qw( basepers admin C notmaster );
+nok qw( basepers admin C refs/tags/boo );
+nok qw( basepers admin C refs/tags/v1 );
+nok qw( basepers admin C dev/admin/foo );
+nok qw( basepers admin C refs/tags/dev/admin/foo );
+nok qw( basepers admin C dev/alice/foo );
+nok qw( basepers admin C refs/tags/dev/alice/foo );
+nok qw( basepers admin D master );
+nok qw( basepers admin D notmaster );
+nok qw( basepers admin D refs/tags/boo );
+nok qw( basepers admin D refs/tags/v1 );
+nok qw( basepers admin D dev/admin/foo );
+nok qw( basepers admin D refs/tags/dev/admin/foo );
+nok qw( basepers admin D dev/alice/foo );
+nok qw( basepers admin D refs/tags/dev/alice/foo );
+
+ok qw( basepers u1 R );
+ok qw( basepers u1 W master );
+ok qw( basepers u1 W notmaster );
+ok qw( basepers u1 W refs/tags/boo );
+ok qw( basepers u1 W refs/tags/v1 );
+ok qw( basepers u1 W dev/u1/foo );
+ok qw( basepers u1 W refs/tags/dev/u1/foo );
+nok qw( basepers u1 W dev/alice/foo );
+nok qw( basepers u1 W refs/tags/dev/alice/foo );
+ok qw( basepers u1 + master );
+ok qw( basepers u1 + notmaster );
+ok qw( basepers u1 + refs/tags/boo );
+ok qw( basepers u1 + refs/tags/v1 );
+ok qw( basepers u1 + dev/u1/foo );
+ok qw( basepers u1 + refs/tags/dev/u1/foo );
+nok qw( basepers u1 + dev/alice/foo );
+nok qw( basepers u1 + refs/tags/dev/alice/foo );
+ok qw( basepers u1 C master );
+ok qw( basepers u1 C notmaster );
+ok qw( basepers u1 C refs/tags/boo );
+ok qw( basepers u1 C refs/tags/v1 );
+ok qw( basepers u1 C dev/u1/foo );
+ok qw( basepers u1 C refs/tags/dev/u1/foo );
+nok qw( basepers u1 C dev/alice/foo );
+nok qw( basepers u1 C refs/tags/dev/alice/foo );
+ok qw( basepers u1 D master );
+ok qw( basepers u1 D notmaster );
+ok qw( basepers u1 D refs/tags/boo );
+ok qw( basepers u1 D refs/tags/v1 );
+ok qw( basepers u1 D dev/u1/foo );
+ok qw( basepers u1 D refs/tags/dev/u1/foo );
+nok qw( basepers u1 D dev/alice/foo );
+nok qw( basepers u1 D refs/tags/dev/alice/foo );
+
+ok qw( basepers u2 R );
+ok qw( basepers u2 W master );
+ok qw( basepers u2 W notmaster );
+ok qw( basepers u2 W refs/tags/boo );
+ok qw( basepers u2 W refs/tags/v1 );
+ok qw( basepers u2 W dev/u2/foo );
+ok qw( basepers u2 W refs/tags/dev/u2/foo );
+nok qw( basepers u2 W dev/alice/foo );
+nok qw( basepers u2 W refs/tags/dev/alice/foo );
+nok qw( basepers u2 + master );
+nok qw( basepers u2 + notmaster );
+nok qw( basepers u2 + refs/tags/boo );
+nok qw( basepers u2 + refs/tags/v1 );
+ok qw( basepers u2 + dev/u2/foo );
+ok qw( basepers u2 + refs/tags/dev/u2/foo );
+nok qw( basepers u2 + dev/alice/foo );
+nok qw( basepers u2 + refs/tags/dev/alice/foo );
+ok qw( basepers u2 C master );
+ok qw( basepers u2 C notmaster );
+ok qw( basepers u2 C refs/tags/boo );
+ok qw( basepers u2 C refs/tags/v1 );
+ok qw( basepers u2 C dev/u2/foo );
+ok qw( basepers u2 C refs/tags/dev/u2/foo );
+nok qw( basepers u2 C dev/alice/foo );
+nok qw( basepers u2 C refs/tags/dev/alice/foo );
+nok qw( basepers u2 D master );
+nok qw( basepers u2 D notmaster );
+nok qw( basepers u2 D refs/tags/boo );
+nok qw( basepers u2 D refs/tags/v1 );
+ok qw( basepers u2 D dev/u2/foo );
+ok qw( basepers u2 D refs/tags/dev/u2/foo );
+nok qw( basepers u2 D dev/alice/foo );
+nok qw( basepers u2 D refs/tags/dev/alice/foo );
+
+ok qw( basepers u3 R );
+nok qw( basepers u3 W master );
+ok qw( basepers u3 W notmaster );
+ok qw( basepers u3 W refs/tags/boo );
+ok qw( basepers u3 W refs/tags/v1 );
+ok qw( basepers u3 W dev/u3/foo );
+ok qw( basepers u3 W refs/tags/dev/u3/foo );
+nok qw( basepers u3 W dev/alice/foo );
+nok qw( basepers u3 W refs/tags/dev/alice/foo );
+nok qw( basepers u3 + master );
+nok qw( basepers u3 + notmaster );
+nok qw( basepers u3 + refs/tags/boo );
+nok qw( basepers u3 + refs/tags/v1 );
+ok qw( basepers u3 + dev/u3/foo );
+ok qw( basepers u3 + refs/tags/dev/u3/foo );
+nok qw( basepers u3 + dev/alice/foo );
+nok qw( basepers u3 + refs/tags/dev/alice/foo );
+nok qw( basepers u3 C master );
+ok qw( basepers u3 C notmaster );
+ok qw( basepers u3 C refs/tags/boo );
+ok qw( basepers u3 C refs/tags/v1 );
+ok qw( basepers u3 C dev/u3/foo );
+ok qw( basepers u3 C refs/tags/dev/u3/foo );
+nok qw( basepers u3 C dev/alice/foo );
+nok qw( basepers u3 C refs/tags/dev/alice/foo );
+nok qw( basepers u3 D master );
+nok qw( basepers u3 D notmaster );
+nok qw( basepers u3 D refs/tags/boo );
+nok qw( basepers u3 D refs/tags/v1 );
+ok qw( basepers u3 D dev/u3/foo );
+ok qw( basepers u3 D refs/tags/dev/u3/foo );
+nok qw( basepers u3 D dev/alice/foo );
+nok qw( basepers u3 D refs/tags/dev/alice/foo );
+
+ok qw( basepers u4 R );
+nok qw( basepers u4 W master );
+nok qw( basepers u4 W notmaster );
+nok qw( basepers u4 W refs/tags/boo );
+nok qw( basepers u4 W refs/tags/v1 );
+nok qw( basepers u4 W dev/u4/foo );
+nok qw( basepers u4 W refs/tags/dev/u4/foo );
+nok qw( basepers u4 W dev/alice/foo );
+nok qw( basepers u4 W refs/tags/dev/alice/foo );
+nok qw( basepers u4 + master );
+nok qw( basepers u4 + notmaster );
+nok qw( basepers u4 + refs/tags/boo );
+nok qw( basepers u4 + refs/tags/v1 );
+nok qw( basepers u4 + dev/u4/foo );
+nok qw( basepers u4 + refs/tags/dev/u4/foo );
+nok qw( basepers u4 + dev/alice/foo );
+nok qw( basepers u4 + refs/tags/dev/alice/foo );
+nok qw( basepers u4 C master );
+nok qw( basepers u4 C notmaster );
+nok qw( basepers u4 C refs/tags/boo );
+nok qw( basepers u4 C refs/tags/v1 );
+nok qw( basepers u4 C dev/u4/foo );
+nok qw( basepers u4 C refs/tags/dev/u4/foo );
+nok qw( basepers u4 C dev/alice/foo );
+nok qw( basepers u4 C refs/tags/dev/alice/foo );
+nok qw( basepers u4 D master );
+nok qw( basepers u4 D notmaster );
+nok qw( basepers u4 D refs/tags/boo );
+nok qw( basepers u4 D refs/tags/v1 );
+nok qw( basepers u4 D dev/u4/foo );
+nok qw( basepers u4 D refs/tags/dev/u4/foo );
+nok qw( basepers u4 D dev/alice/foo );
+nok qw( basepers u4 D refs/tags/dev/alice/foo );
+
+ok qw( basepers u5 R );
+nok qw( basepers u5 W master );
+nok qw( basepers u5 W notmaster );
+nok qw( basepers u5 W refs/tags/boo );
+nok qw( basepers u5 W refs/tags/v1 );
+ok qw( basepers u5 W dev/u5/foo );
+ok qw( basepers u5 W refs/tags/dev/u5/foo );
+nok qw( basepers u5 W dev/alice/foo );
+nok qw( basepers u5 W refs/tags/dev/alice/foo );
+nok qw( basepers u5 + master );
+nok qw( basepers u5 + notmaster );
+nok qw( basepers u5 + refs/tags/boo );
+nok qw( basepers u5 + refs/tags/v1 );
+ok qw( basepers u5 + dev/u5/foo );
+ok qw( basepers u5 + refs/tags/dev/u5/foo );
+nok qw( basepers u5 + dev/alice/foo );
+nok qw( basepers u5 + refs/tags/dev/alice/foo );
+nok qw( basepers u5 C master );
+nok qw( basepers u5 C notmaster );
+nok qw( basepers u5 C refs/tags/boo );
+nok qw( basepers u5 C refs/tags/v1 );
+ok qw( basepers u5 C dev/u5/foo );
+ok qw( basepers u5 C refs/tags/dev/u5/foo );
+nok qw( basepers u5 C dev/alice/foo );
+nok qw( basepers u5 C refs/tags/dev/alice/foo );
+nok qw( basepers u5 D master );
+nok qw( basepers u5 D notmaster );
+nok qw( basepers u5 D refs/tags/boo );
+nok qw( basepers u5 D refs/tags/v1 );
+ok qw( basepers u5 D dev/u5/foo );
+ok qw( basepers u5 D refs/tags/dev/u5/foo );
+nok qw( basepers u5 D dev/alice/foo );
+nok qw( basepers u5 D refs/tags/dev/alice/foo );
+
+ok qw( basepers u6 R );
+nok qw( basepers u6 W master );
+nok qw( basepers u6 W notmaster );
+nok qw( basepers u6 W refs/tags/boo );
+nok qw( basepers u6 W refs/tags/v1 );
+ok qw( basepers u6 W dev/u6/foo );
+ok qw( basepers u6 W refs/tags/dev/u6/foo );
+nok qw( basepers u6 W dev/alice/foo );
+nok qw( basepers u6 W refs/tags/dev/alice/foo );
+nok qw( basepers u6 + master );
+nok qw( basepers u6 + notmaster );
+nok qw( basepers u6 + refs/tags/boo );
+nok qw( basepers u6 + refs/tags/v1 );
+ok qw( basepers u6 + dev/u6/foo );
+ok qw( basepers u6 + refs/tags/dev/u6/foo );
+nok qw( basepers u6 + dev/alice/foo );
+nok qw( basepers u6 + refs/tags/dev/alice/foo );
+nok qw( basepers u6 C master );
+nok qw( basepers u6 C notmaster );
+nok qw( basepers u6 C refs/tags/boo );
+nok qw( basepers u6 C refs/tags/v1 );
+ok qw( basepers u6 C dev/u6/foo );
+ok qw( basepers u6 C refs/tags/dev/u6/foo );
+nok qw( basepers u6 C dev/alice/foo );
+nok qw( basepers u6 C refs/tags/dev/alice/foo );
+nok qw( basepers u6 D master );
+nok qw( basepers u6 D notmaster );
+nok qw( basepers u6 D refs/tags/boo );
+nok qw( basepers u6 D refs/tags/v1 );
+ok qw( basepers u6 D dev/u6/foo );
+ok qw( basepers u6 D refs/tags/dev/u6/foo );
+nok qw( basepers u6 D dev/alice/foo );
+nok qw( basepers u6 D refs/tags/dev/alice/foo );
+
+nok qw( baserel admin R );
+nok qw( baserel admin W master );
+nok qw( baserel admin W notmaster );
+nok qw( baserel admin W refs/tags/boo );
+nok qw( baserel admin W refs/tags/v1 );
+nok qw( baserel admin W dev/admin/foo );
+nok qw( baserel admin W refs/tags/dev/admin/foo );
+nok qw( baserel admin W dev/alice/foo );
+nok qw( baserel admin W refs/tags/dev/alice/foo );
+nok qw( baserel admin + master );
+nok qw( baserel admin + notmaster );
+nok qw( baserel admin + refs/tags/boo );
+nok qw( baserel admin + refs/tags/v1 );
+nok qw( baserel admin + dev/admin/foo );
+nok qw( baserel admin + refs/tags/dev/admin/foo );
+nok qw( baserel admin + dev/alice/foo );
+nok qw( baserel admin + refs/tags/dev/alice/foo );
+nok qw( baserel admin C master );
+nok qw( baserel admin C notmaster );
+nok qw( baserel admin C refs/tags/boo );
+nok qw( baserel admin C refs/tags/v1 );
+nok qw( baserel admin C dev/admin/foo );
+nok qw( baserel admin C refs/tags/dev/admin/foo );
+nok qw( baserel admin C dev/alice/foo );
+nok qw( baserel admin C refs/tags/dev/alice/foo );
+nok qw( baserel admin D master );
+nok qw( baserel admin D notmaster );
+nok qw( baserel admin D refs/tags/boo );
+nok qw( baserel admin D refs/tags/v1 );
+nok qw( baserel admin D dev/admin/foo );
+nok qw( baserel admin D refs/tags/dev/admin/foo );
+nok qw( baserel admin D dev/alice/foo );
+nok qw( baserel admin D refs/tags/dev/alice/foo );
+
+ok qw( baserel u1 R );
+ok qw( baserel u1 W master );
+ok qw( baserel u1 W notmaster );
+ok qw( baserel u1 W refs/tags/boo );
+nok qw( baserel u1 W refs/tags/v1 );
+ok qw( baserel u1 W dev/u1/foo );
+ok qw( baserel u1 W refs/tags/dev/u1/foo );
+ok qw( baserel u1 W dev/alice/foo );
+ok qw( baserel u1 W refs/tags/dev/alice/foo );
+ok qw( baserel u1 + master );
+ok qw( baserel u1 + notmaster );
+ok qw( baserel u1 + refs/tags/boo );
+nok qw( baserel u1 + refs/tags/v1 );
+ok qw( baserel u1 + dev/u1/foo );
+ok qw( baserel u1 + refs/tags/dev/u1/foo );
+ok qw( baserel u1 + dev/alice/foo );
+ok qw( baserel u1 + refs/tags/dev/alice/foo );
+ok qw( baserel u1 C master );
+ok qw( baserel u1 C notmaster );
+ok qw( baserel u1 C refs/tags/boo );
+nok qw( baserel u1 C refs/tags/v1 );
+ok qw( baserel u1 C dev/u1/foo );
+ok qw( baserel u1 C refs/tags/dev/u1/foo );
+ok qw( baserel u1 C dev/alice/foo );
+ok qw( baserel u1 C refs/tags/dev/alice/foo );
+ok qw( baserel u1 D master );
+ok qw( baserel u1 D notmaster );
+ok qw( baserel u1 D refs/tags/boo );
+nok qw( baserel u1 D refs/tags/v1 );
+ok qw( baserel u1 D dev/u1/foo );
+ok qw( baserel u1 D refs/tags/dev/u1/foo );
+ok qw( baserel u1 D dev/alice/foo );
+ok qw( baserel u1 D refs/tags/dev/alice/foo );
+
+ok qw( baserel u2 R );
+ok qw( baserel u2 W master );
+ok qw( baserel u2 W notmaster );
+ok qw( baserel u2 W refs/tags/boo );
+nok qw( baserel u2 W refs/tags/v1 );
+ok qw( baserel u2 W dev/u2/foo );
+ok qw( baserel u2 W refs/tags/dev/u2/foo );
+ok qw( baserel u2 W dev/alice/foo );
+ok qw( baserel u2 W refs/tags/dev/alice/foo );
+nok qw( baserel u2 + master );
+nok qw( baserel u2 + notmaster );
+nok qw( baserel u2 + refs/tags/boo );
+nok qw( baserel u2 + refs/tags/v1 );
+nok qw( baserel u2 + dev/u2/foo );
+nok qw( baserel u2 + refs/tags/dev/u2/foo );
+nok qw( baserel u2 + dev/alice/foo );
+nok qw( baserel u2 + refs/tags/dev/alice/foo );
+ok qw( baserel u2 C master );
+ok qw( baserel u2 C notmaster );
+ok qw( baserel u2 C refs/tags/boo );
+nok qw( baserel u2 C refs/tags/v1 );
+ok qw( baserel u2 C dev/u2/foo );
+ok qw( baserel u2 C refs/tags/dev/u2/foo );
+ok qw( baserel u2 C dev/alice/foo );
+ok qw( baserel u2 C refs/tags/dev/alice/foo );
+nok qw( baserel u2 D master );
+nok qw( baserel u2 D notmaster );
+nok qw( baserel u2 D refs/tags/boo );
+nok qw( baserel u2 D refs/tags/v1 );
+nok qw( baserel u2 D dev/u2/foo );
+nok qw( baserel u2 D refs/tags/dev/u2/foo );
+nok qw( baserel u2 D dev/alice/foo );
+nok qw( baserel u2 D refs/tags/dev/alice/foo );
+
+ok qw( baserel u3 R );
+nok qw( baserel u3 W master );
+ok qw( baserel u3 W notmaster );
+ok qw( baserel u3 W refs/tags/boo );
+nok qw( baserel u3 W refs/tags/v1 );
+ok qw( baserel u3 W dev/u3/foo );
+ok qw( baserel u3 W refs/tags/dev/u3/foo );
+ok qw( baserel u3 W dev/alice/foo );
+ok qw( baserel u3 W refs/tags/dev/alice/foo );
+nok qw( baserel u3 + master );
+nok qw( baserel u3 + notmaster );
+nok qw( baserel u3 + refs/tags/boo );
+nok qw( baserel u3 + refs/tags/v1 );
+nok qw( baserel u3 + dev/u3/foo );
+nok qw( baserel u3 + refs/tags/dev/u3/foo );
+nok qw( baserel u3 + dev/alice/foo );
+nok qw( baserel u3 + refs/tags/dev/alice/foo );
+nok qw( baserel u3 C master );
+ok qw( baserel u3 C notmaster );
+ok qw( baserel u3 C refs/tags/boo );
+nok qw( baserel u3 C refs/tags/v1 );
+ok qw( baserel u3 C dev/u3/foo );
+ok qw( baserel u3 C refs/tags/dev/u3/foo );
+ok qw( baserel u3 C dev/alice/foo );
+ok qw( baserel u3 C refs/tags/dev/alice/foo );
+nok qw( baserel u3 D master );
+nok qw( baserel u3 D notmaster );
+nok qw( baserel u3 D refs/tags/boo );
+nok qw( baserel u3 D refs/tags/v1 );
+nok qw( baserel u3 D dev/u3/foo );
+nok qw( baserel u3 D refs/tags/dev/u3/foo );
+nok qw( baserel u3 D dev/alice/foo );
+nok qw( baserel u3 D refs/tags/dev/alice/foo );
+
+ok qw( baserel u4 R );
+nok qw( baserel u4 W master );
+nok qw( baserel u4 W notmaster );
+nok qw( baserel u4 W refs/tags/boo );
+nok qw( baserel u4 W refs/tags/v1 );
+nok qw( baserel u4 W dev/u4/foo );
+nok qw( baserel u4 W refs/tags/dev/u4/foo );
+nok qw( baserel u4 W dev/alice/foo );
+nok qw( baserel u4 W refs/tags/dev/alice/foo );
+nok qw( baserel u4 + master );
+nok qw( baserel u4 + notmaster );
+nok qw( baserel u4 + refs/tags/boo );
+nok qw( baserel u4 + refs/tags/v1 );
+nok qw( baserel u4 + dev/u4/foo );
+nok qw( baserel u4 + refs/tags/dev/u4/foo );
+nok qw( baserel u4 + dev/alice/foo );
+nok qw( baserel u4 + refs/tags/dev/alice/foo );
+nok qw( baserel u4 C master );
+nok qw( baserel u4 C notmaster );
+nok qw( baserel u4 C refs/tags/boo );
+nok qw( baserel u4 C refs/tags/v1 );
+nok qw( baserel u4 C dev/u4/foo );
+nok qw( baserel u4 C refs/tags/dev/u4/foo );
+nok qw( baserel u4 C dev/alice/foo );
+nok qw( baserel u4 C refs/tags/dev/alice/foo );
+nok qw( baserel u4 D master );
+nok qw( baserel u4 D notmaster );
+nok qw( baserel u4 D refs/tags/boo );
+nok qw( baserel u4 D refs/tags/v1 );
+nok qw( baserel u4 D dev/u4/foo );
+nok qw( baserel u4 D refs/tags/dev/u4/foo );
+nok qw( baserel u4 D dev/alice/foo );
+nok qw( baserel u4 D refs/tags/dev/alice/foo );
+
+ok qw( baserel u5 R );
+nok qw( baserel u5 W master );
+nok qw( baserel u5 W notmaster );
+nok qw( baserel u5 W refs/tags/boo );
+nok qw( baserel u5 W refs/tags/v1 );
+nok qw( baserel u5 W dev/u5/foo );
+nok qw( baserel u5 W refs/tags/dev/u5/foo );
+nok qw( baserel u5 W dev/alice/foo );
+nok qw( baserel u5 W refs/tags/dev/alice/foo );
+nok qw( baserel u5 + master );
+nok qw( baserel u5 + notmaster );
+nok qw( baserel u5 + refs/tags/boo );
+nok qw( baserel u5 + refs/tags/v1 );
+nok qw( baserel u5 + dev/u5/foo );
+nok qw( baserel u5 + refs/tags/dev/u5/foo );
+nok qw( baserel u5 + dev/alice/foo );
+nok qw( baserel u5 + refs/tags/dev/alice/foo );
+nok qw( baserel u5 C master );
+nok qw( baserel u5 C notmaster );
+nok qw( baserel u5 C refs/tags/boo );
+nok qw( baserel u5 C refs/tags/v1 );
+nok qw( baserel u5 C dev/u5/foo );
+nok qw( baserel u5 C refs/tags/dev/u5/foo );
+nok qw( baserel u5 C dev/alice/foo );
+nok qw( baserel u5 C refs/tags/dev/alice/foo );
+nok qw( baserel u5 D master );
+nok qw( baserel u5 D notmaster );
+nok qw( baserel u5 D refs/tags/boo );
+nok qw( baserel u5 D refs/tags/v1 );
+nok qw( baserel u5 D dev/u5/foo );
+nok qw( baserel u5 D refs/tags/dev/u5/foo );
+nok qw( baserel u5 D dev/alice/foo );
+nok qw( baserel u5 D refs/tags/dev/alice/foo );
+
+nok qw( baserel u6 R );
+nok qw( baserel u6 W master );
+nok qw( baserel u6 W notmaster );
+nok qw( baserel u6 W refs/tags/boo );
+nok qw( baserel u6 W refs/tags/v1 );
+nok qw( baserel u6 W dev/u6/foo );
+nok qw( baserel u6 W refs/tags/dev/u6/foo );
+nok qw( baserel u6 W dev/alice/foo );
+nok qw( baserel u6 W refs/tags/dev/alice/foo );
+nok qw( baserel u6 + master );
+nok qw( baserel u6 + notmaster );
+nok qw( baserel u6 + refs/tags/boo );
+nok qw( baserel u6 + refs/tags/v1 );
+nok qw( baserel u6 + dev/u6/foo );
+nok qw( baserel u6 + refs/tags/dev/u6/foo );
+nok qw( baserel u6 + dev/alice/foo );
+nok qw( baserel u6 + refs/tags/dev/alice/foo );
+nok qw( baserel u6 C master );
+nok qw( baserel u6 C notmaster );
+nok qw( baserel u6 C refs/tags/boo );
+nok qw( baserel u6 C refs/tags/v1 );
+nok qw( baserel u6 C dev/u6/foo );
+nok qw( baserel u6 C refs/tags/dev/u6/foo );
+nok qw( baserel u6 C dev/alice/foo );
+nok qw( baserel u6 C refs/tags/dev/alice/foo );
+nok qw( baserel u6 D master );
+nok qw( baserel u6 D notmaster );
+nok qw( baserel u6 D refs/tags/boo );
+nok qw( baserel u6 D refs/tags/v1 );
+nok qw( baserel u6 D dev/u6/foo );
+nok qw( baserel u6 D refs/tags/dev/u6/foo );
+nok qw( baserel u6 D dev/alice/foo );
+nok qw( baserel u6 D refs/tags/dev/alice/foo );
+
+ok qw( baseall admin R );
+ok qw( baseall admin W master );
+ok qw( baseall admin W notmaster );
+ok qw( baseall admin W refs/tags/boo );
+ok qw( baseall admin W refs/tags/v1 );
+ok qw( baseall admin W dev/admin/foo );
+ok qw( baseall admin W refs/tags/dev/admin/foo );
+ok qw( baseall admin W dev/alice/foo );
+ok qw( baseall admin W refs/tags/dev/alice/foo );
+ok qw( baseall admin + master );
+ok qw( baseall admin + notmaster );
+ok qw( baseall admin + refs/tags/boo );
+ok qw( baseall admin + refs/tags/v1 );
+ok qw( baseall admin + dev/admin/foo );
+ok qw( baseall admin + refs/tags/dev/admin/foo );
+ok qw( baseall admin + dev/alice/foo );
+ok qw( baseall admin + refs/tags/dev/alice/foo );
+ok qw( baseall admin C master );
+ok qw( baseall admin C notmaster );
+ok qw( baseall admin C refs/tags/boo );
+ok qw( baseall admin C refs/tags/v1 );
+ok qw( baseall admin C dev/admin/foo );
+ok qw( baseall admin C refs/tags/dev/admin/foo );
+ok qw( baseall admin C dev/alice/foo );
+ok qw( baseall admin C refs/tags/dev/alice/foo );
+ok qw( baseall admin D master );
+ok qw( baseall admin D notmaster );
+ok qw( baseall admin D refs/tags/boo );
+ok qw( baseall admin D refs/tags/v1 );
+ok qw( baseall admin D dev/admin/foo );
+ok qw( baseall admin D refs/tags/dev/admin/foo );
+ok qw( baseall admin D dev/alice/foo );
+ok qw( baseall admin D refs/tags/dev/alice/foo );
+
+ok qw( baseall u1 R );
+ok qw( baseall u1 W master );
+ok qw( baseall u1 W notmaster );
+ok qw( baseall u1 W refs/tags/boo );
+nok qw( baseall u1 W refs/tags/v1 );
+ok qw( baseall u1 W dev/u1/foo );
+ok qw( baseall u1 W refs/tags/dev/u1/foo );
+nok qw( baseall u1 W dev/alice/foo );
+nok qw( baseall u1 W refs/tags/dev/alice/foo );
+ok qw( baseall u1 + master );
+ok qw( baseall u1 + notmaster );
+ok qw( baseall u1 + refs/tags/boo );
+nok qw( baseall u1 + refs/tags/v1 );
+ok qw( baseall u1 + dev/u1/foo );
+ok qw( baseall u1 + refs/tags/dev/u1/foo );
+nok qw( baseall u1 + dev/alice/foo );
+nok qw( baseall u1 + refs/tags/dev/alice/foo );
+ok qw( baseall u1 C master );
+ok qw( baseall u1 C notmaster );
+ok qw( baseall u1 C refs/tags/boo );
+nok qw( baseall u1 C refs/tags/v1 );
+ok qw( baseall u1 C dev/u1/foo );
+ok qw( baseall u1 C refs/tags/dev/u1/foo );
+nok qw( baseall u1 C dev/alice/foo );
+nok qw( baseall u1 C refs/tags/dev/alice/foo );
+ok qw( baseall u1 D master );
+ok qw( baseall u1 D notmaster );
+ok qw( baseall u1 D refs/tags/boo );
+nok qw( baseall u1 D refs/tags/v1 );
+ok qw( baseall u1 D dev/u1/foo );
+ok qw( baseall u1 D refs/tags/dev/u1/foo );
+nok qw( baseall u1 D dev/alice/foo );
+nok qw( baseall u1 D refs/tags/dev/alice/foo );
+
+ok qw( baseall u2 R );
+ok qw( baseall u2 W master );
+ok qw( baseall u2 W notmaster );
+ok qw( baseall u2 W refs/tags/boo );
+nok qw( baseall u2 W refs/tags/v1 );
+ok qw( baseall u2 W dev/u2/foo );
+ok qw( baseall u2 W refs/tags/dev/u2/foo );
+nok qw( baseall u2 W dev/alice/foo );
+nok qw( baseall u2 W refs/tags/dev/alice/foo );
+nok qw( baseall u2 + master );
+nok qw( baseall u2 + notmaster );
+nok qw( baseall u2 + refs/tags/boo );
+nok qw( baseall u2 + refs/tags/v1 );
+ok qw( baseall u2 + dev/u2/foo );
+ok qw( baseall u2 + refs/tags/dev/u2/foo );
+nok qw( baseall u2 + dev/alice/foo );
+nok qw( baseall u2 + refs/tags/dev/alice/foo );
+ok qw( baseall u2 C master );
+ok qw( baseall u2 C notmaster );
+ok qw( baseall u2 C refs/tags/boo );
+nok qw( baseall u2 C refs/tags/v1 );
+ok qw( baseall u2 C dev/u2/foo );
+ok qw( baseall u2 C refs/tags/dev/u2/foo );
+nok qw( baseall u2 C dev/alice/foo );
+nok qw( baseall u2 C refs/tags/dev/alice/foo );
+nok qw( baseall u2 D master );
+nok qw( baseall u2 D notmaster );
+nok qw( baseall u2 D refs/tags/boo );
+nok qw( baseall u2 D refs/tags/v1 );
+ok qw( baseall u2 D dev/u2/foo );
+ok qw( baseall u2 D refs/tags/dev/u2/foo );
+nok qw( baseall u2 D dev/alice/foo );
+nok qw( baseall u2 D refs/tags/dev/alice/foo );
+
+ok qw( baseall u3 R );
+nok qw( baseall u3 W master );
+ok qw( baseall u3 W notmaster );
+ok qw( baseall u3 W refs/tags/boo );
+nok qw( baseall u3 W refs/tags/v1 );
+ok qw( baseall u3 W dev/u3/foo );
+ok qw( baseall u3 W refs/tags/dev/u3/foo );
+nok qw( baseall u3 W dev/alice/foo );
+nok qw( baseall u3 W refs/tags/dev/alice/foo );
+nok qw( baseall u3 + master );
+nok qw( baseall u3 + notmaster );
+nok qw( baseall u3 + refs/tags/boo );
+nok qw( baseall u3 + refs/tags/v1 );
+ok qw( baseall u3 + dev/u3/foo );
+ok qw( baseall u3 + refs/tags/dev/u3/foo );
+nok qw( baseall u3 + dev/alice/foo );
+nok qw( baseall u3 + refs/tags/dev/alice/foo );
+nok qw( baseall u3 C master );
+ok qw( baseall u3 C notmaster );
+ok qw( baseall u3 C refs/tags/boo );
+nok qw( baseall u3 C refs/tags/v1 );
+ok qw( baseall u3 C dev/u3/foo );
+ok qw( baseall u3 C refs/tags/dev/u3/foo );
+nok qw( baseall u3 C dev/alice/foo );
+nok qw( baseall u3 C refs/tags/dev/alice/foo );
+nok qw( baseall u3 D master );
+nok qw( baseall u3 D notmaster );
+nok qw( baseall u3 D refs/tags/boo );
+nok qw( baseall u3 D refs/tags/v1 );
+ok qw( baseall u3 D dev/u3/foo );
+ok qw( baseall u3 D refs/tags/dev/u3/foo );
+nok qw( baseall u3 D dev/alice/foo );
+nok qw( baseall u3 D refs/tags/dev/alice/foo );
+
+ok qw( baseall u4 R );
+nok qw( baseall u4 W master );
+nok qw( baseall u4 W notmaster );
+nok qw( baseall u4 W refs/tags/boo );
+nok qw( baseall u4 W refs/tags/v1 );
+nok qw( baseall u4 W dev/u4/foo );
+nok qw( baseall u4 W refs/tags/dev/u4/foo );
+nok qw( baseall u4 W dev/alice/foo );
+nok qw( baseall u4 W refs/tags/dev/alice/foo );
+nok qw( baseall u4 + master );
+nok qw( baseall u4 + notmaster );
+nok qw( baseall u4 + refs/tags/boo );
+nok qw( baseall u4 + refs/tags/v1 );
+nok qw( baseall u4 + dev/u4/foo );
+nok qw( baseall u4 + refs/tags/dev/u4/foo );
+nok qw( baseall u4 + dev/alice/foo );
+nok qw( baseall u4 + refs/tags/dev/alice/foo );
+nok qw( baseall u4 C master );
+nok qw( baseall u4 C notmaster );
+nok qw( baseall u4 C refs/tags/boo );
+nok qw( baseall u4 C refs/tags/v1 );
+nok qw( baseall u4 C dev/u4/foo );
+nok qw( baseall u4 C refs/tags/dev/u4/foo );
+nok qw( baseall u4 C dev/alice/foo );
+nok qw( baseall u4 C refs/tags/dev/alice/foo );
+nok qw( baseall u4 D master );
+nok qw( baseall u4 D notmaster );
+nok qw( baseall u4 D refs/tags/boo );
+nok qw( baseall u4 D refs/tags/v1 );
+nok qw( baseall u4 D dev/u4/foo );
+nok qw( baseall u4 D refs/tags/dev/u4/foo );
+nok qw( baseall u4 D dev/alice/foo );
+nok qw( baseall u4 D refs/tags/dev/alice/foo );
+
+ok qw( baseall u5 R );
+nok qw( baseall u5 W master );
+nok qw( baseall u5 W notmaster );
+nok qw( baseall u5 W refs/tags/boo );
+nok qw( baseall u5 W refs/tags/v1 );
+ok qw( baseall u5 W dev/u5/foo );
+ok qw( baseall u5 W refs/tags/dev/u5/foo );
+nok qw( baseall u5 W dev/alice/foo );
+nok qw( baseall u5 W refs/tags/dev/alice/foo );
+nok qw( baseall u5 + master );
+nok qw( baseall u5 + notmaster );
+nok qw( baseall u5 + refs/tags/boo );
+nok qw( baseall u5 + refs/tags/v1 );
+ok qw( baseall u5 + dev/u5/foo );
+ok qw( baseall u5 + refs/tags/dev/u5/foo );
+nok qw( baseall u5 + dev/alice/foo );
+nok qw( baseall u5 + refs/tags/dev/alice/foo );
+nok qw( baseall u5 C master );
+nok qw( baseall u5 C notmaster );
+nok qw( baseall u5 C refs/tags/boo );
+nok qw( baseall u5 C refs/tags/v1 );
+ok qw( baseall u5 C dev/u5/foo );
+ok qw( baseall u5 C refs/tags/dev/u5/foo );
+nok qw( baseall u5 C dev/alice/foo );
+nok qw( baseall u5 C refs/tags/dev/alice/foo );
+nok qw( baseall u5 D master );
+nok qw( baseall u5 D notmaster );
+nok qw( baseall u5 D refs/tags/boo );
+nok qw( baseall u5 D refs/tags/v1 );
+ok qw( baseall u5 D dev/u5/foo );
+ok qw( baseall u5 D refs/tags/dev/u5/foo );
+nok qw( baseall u5 D dev/alice/foo );
+nok qw( baseall u5 D refs/tags/dev/alice/foo );
+
+ok qw( baseall u6 R );
+nok qw( baseall u6 W master );
+nok qw( baseall u6 W notmaster );
+nok qw( baseall u6 W refs/tags/boo );
+nok qw( baseall u6 W refs/tags/v1 );
+ok qw( baseall u6 W dev/u6/foo );
+ok qw( baseall u6 W refs/tags/dev/u6/foo );
+nok qw( baseall u6 W dev/alice/foo );
+nok qw( baseall u6 W refs/tags/dev/alice/foo );
+nok qw( baseall u6 + master );
+nok qw( baseall u6 + notmaster );
+nok qw( baseall u6 + refs/tags/boo );
+nok qw( baseall u6 + refs/tags/v1 );
+ok qw( baseall u6 + dev/u6/foo );
+ok qw( baseall u6 + refs/tags/dev/u6/foo );
+nok qw( baseall u6 + dev/alice/foo );
+nok qw( baseall u6 + refs/tags/dev/alice/foo );
+nok qw( baseall u6 C master );
+nok qw( baseall u6 C notmaster );
+nok qw( baseall u6 C refs/tags/boo );
+nok qw( baseall u6 C refs/tags/v1 );
+ok qw( baseall u6 C dev/u6/foo );
+ok qw( baseall u6 C refs/tags/dev/u6/foo );
+nok qw( baseall u6 C dev/alice/foo );
+nok qw( baseall u6 C refs/tags/dev/alice/foo );
+nok qw( baseall u6 D master );
+nok qw( baseall u6 D notmaster );
+nok qw( baseall u6 D refs/tags/boo );
+nok qw( baseall u6 D refs/tags/v1 );
+ok qw( baseall u6 D dev/u6/foo );
+ok qw( baseall u6 D refs/tags/dev/u6/foo );
+nok qw( baseall u6 D dev/alice/foo );
+nok qw( baseall u6 D refs/tags/dev/alice/foo );
+