diff --git a/src/gitolite.pm b/src/gitolite.pm index 3bc513f..e3e7578 100644 --- a/src/gitolite.pm +++ b/src/gitolite.pm @@ -34,7 +34,7 @@ our $USERNAME_PATT=qr(^\@?[0-9a-zA-Z][0-9a-zA-Z._\@+-]*$); # very simple patter our $REPOPATT_PATT=qr(^\@?[0-9a-zA-Z][\\^.$|()[\]*+?{}0-9a-zA-Z._\@/-]*$); # these come from the RC file -our ($REPO_UMASK, $GL_WILDREPOS, $GL_PACKAGE_CONF, $GL_PACKAGE_HOOKS); +our ($REPO_UMASK, $GL_WILDREPOS, $GL_PACKAGE_CONF, $GL_PACKAGE_HOOKS, $REPO_BASE, $GL_CONF_COMPILED); our %repos; # ---------------------------------------------------------------------------- @@ -159,7 +159,7 @@ sub new_repo # ---------------------------------------------------------------------------- # "who created this repo", "am I on the R list", and "am I on the RW list"? -sub repo_rights +sub wild_repo_rights { my ($repo_base_abs, $repo, $user) = @_; # creater @@ -189,7 +189,7 @@ sub repo_rights sub get_set_perms { my($repo_base_abs, $repo, $verb, $user) = @_; - my ($creater, $dummy, $dummy2) = &repo_rights($repo_base_abs, $repo, ""); + my ($creater, $dummy, $dummy2) = &wild_repo_rights($repo_base_abs, $repo, ""); die "$repo doesnt exist or is not yours\n" unless $user eq $creater; wrap_chdir("$repo_base_abs"); wrap_chdir("$repo.git"); @@ -209,7 +209,7 @@ sub get_set_perms sub get_set_desc { my($repo_base_abs, $repo, $verb, $user) = @_; - my ($creater, $dummy, $dummy2) = &repo_rights($repo_base_abs, $repo, ""); + my ($creater, $dummy, $dummy2) = &wild_repo_rights($repo_base_abs, $repo, ""); die "$repo doesnt exist or is not yours\n" unless $user eq $creater; wrap_chdir("$repo_base_abs"); wrap_chdir("$repo.git"); @@ -344,7 +344,7 @@ sub expand_wild } else { # find the creater and subsitute in repos my ($read, $write); - ($creater, $read, $write) = &repo_rights($repo_base_abs, $actual_repo, $user); + ($creater, $read, $write) = &wild_repo_rights($repo_base_abs, $actual_repo, $user); # get access list with this &parse_acl($GL_CONF_COMPILED, $actual_repo, $creater, $read || "NOBODY", $write || "NOBODY"); $creater = "($creater)"; @@ -358,6 +358,66 @@ sub expand_wild } } +# there will be multiple calls to repo_rights; better to use a closure. We +# might even be called from outside (see the admin-defined-commands docs for +# how/why). Regardless of how we're called, we assume $ENV{GL_USER} is +# already defined +{ + my %normal_repos; + + sub repo_rights { + my $repo = shift; + $repo =~ s/^\.\///; + $repo =~ s/\.git$//; + + # we get passed an actual repo name. It may be a normal + # (non-wildcard) repo, in which case it is assumed to exist. If it's + # a wildrepo, it may or may not exist. If it doesn't exist, the "C" + # perms are also filled in, else that column is left blank + + unless (%normal_repos) { + unless ($REPO_BASE) { + # means we've been called from outside + &where_is_rc(); + die "parse $ENV{GL_RC} failed: " . ($! or $@) unless do $ENV{GL_RC}; + } + + &parse_acl($GL_CONF_COMPILED, "", "NOBODY", "NOBODY", "NOBODY"); + %normal_repos = %repos; + } + + my $creater; + my $perm = ' '; + + # if repo is present "as is" in the config, those permissions will + # override anything inherited from a wildcard that may have matched + if ($normal_repos{$repo}) { + %repos = %normal_repos; + $creater = ''; + } elsif ( -d "$ENV{GL_REPO_BASE_ABS}/$repo.git" ) { + # must be a wildrepo, and it has already been created; find the + # creater and subsitute in repos + my ($read, $write); + ($creater, $read, $write) = &wild_repo_rights($ENV{GL_REPO_BASE_ABS}, $repo, $ENV{GL_USER}); + # get access list with these substitutions + &parse_acl($GL_CONF_COMPILED, $repo, $creater || "NOBODY", $read || "NOBODY", $write || "NOBODY"); + $creater = "($creater)"; + } else { + # repo didn't exist; C perms also need to be filled in after + # getting access list with only creater filled in + &parse_acl($GL_CONF_COMPILED, $repo, $ENV{GL_USER}, "NOBODY", "NOBODY"); + $perm = ( $repos{$repo}{C}{'@all'} ? ' @C' : ( $repos{$repo}{C}{$ENV{GL_USER}} ? ' =C' : ' ' )) if $GL_WILDREPOS; + # if you didn't have perms to create it, delete the "convenience" + # copy of the ACL that parse_acl makes + delete $repos{$repo} unless $perm =~ /C/; + $creater = ""; + } + $perm .= ( $repos{$repo}{R}{'@all'} ? ' @R' : ( $repos{'@all'}{R}{$ENV{GL_USER}} ? ' #R' : ( $repos{$repo}{R}{$ENV{GL_USER}} ? ' R' : ' ' ))); + $perm .= ( $repos{$repo}{W}{'@all'} ? ' @W' : ( $repos{'@all'}{W}{$ENV{GL_USER}} ? ' #W' : ( $repos{$repo}{W}{$ENV{GL_USER}} ? ' W' : ' ' ))); + return($perm, $creater); + } +} + # ---------------------------------------------------------------------------- # S P E C I A L C O M M A N D S # ---------------------------------------------------------------------------- diff --git a/src/gl-auth-command b/src/gl-auth-command index 24fc5b9..0621a43 100755 --- a/src/gl-auth-command +++ b/src/gl-auth-command @@ -49,7 +49,7 @@ $ENV{PATH} .= ":$GIT_PATH" if $GIT_PATH; # set the umask before creating any files umask($REPO_UMASK); -my $repo_base_abs = ( $REPO_BASE =~ m(^/) ? $REPO_BASE : "$ENV{HOME}/$REPO_BASE" ); +my $repo_base_abs = $ENV{GL_REPO_BASE_ABS} = ( $REPO_BASE =~ m(^/) ? $REPO_BASE : "$ENV{HOME}/$REPO_BASE" ); # ---------------------------------------------------------------------------- # start... @@ -170,7 +170,7 @@ $ENV{GL_REPO}=$repo; if ( -d "$repo_base_abs/$repo.git" ) { # existing repo - my ($creater, $user_R, $user_W) = &repo_rights($repo_base_abs, $repo, $user); + my ($creater, $user_R, $user_W) = &wild_repo_rights($repo_base_abs, $repo, $user); &parse_acl($GL_CONF_COMPILED, $repo, $creater, $user_R, $user_W); } else { &parse_acl($GL_CONF_COMPILED, $repo, $user, "NOBODY", "NOBODY");