2009-10-25 03:59:52 +01:00
|
|
|
# this file is commonly used using "require". It is not required to use "use"
|
|
|
|
# (because it doesn't live in a different package)
|
|
|
|
|
|
|
|
# warning: preceding para requires 4th attribute of a programmer after
|
|
|
|
# laziness, impatience, and hubris: sense of humour :-)
|
|
|
|
|
|
|
|
# WARNING
|
|
|
|
# -------
|
|
|
|
# the name of this file will change as soon as its function/feature set
|
|
|
|
# stabilises enough ;-)
|
|
|
|
|
2009-11-26 17:00:59 +01:00
|
|
|
# right now all it does is
|
|
|
|
# - define a function that tells you where to find the rc file
|
|
|
|
# - define a function that creates a new repo and give it our update hook
|
2009-10-25 03:59:52 +01:00
|
|
|
|
2009-12-04 05:21:22 +01:00
|
|
|
# ----------------------------------------------------------------------------
|
|
|
|
# common definitions
|
|
|
|
# ----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
$ABRT = "\n\t\t***** ABORTING *****\n ";
|
|
|
|
$WARN = "\n\t\t***** WARNING *****\n ";
|
|
|
|
|
|
|
|
# commands we're expecting
|
|
|
|
$R_COMMANDS=qr/^(git[ -]upload-pack|git[ -]upload-archive)$/;
|
|
|
|
$W_COMMANDS=qr/^git[ -]receive-pack$/;
|
|
|
|
|
2009-12-08 10:33:38 +01:00
|
|
|
# note that REPONAME_PATT allows "/", while USERNAME_PATT allows "@"
|
2009-12-18 05:45:35 +01:00
|
|
|
$REPONAME_PATT=qr(^\@?[0-9a-zA-Z][0-9a-zA-Z._/+-]*$); # very simple pattern
|
|
|
|
$USERNAME_PATT=qr(^\@?[0-9a-zA-Z][0-9a-zA-Z._\@+-]*$); # very simple pattern
|
2009-12-04 05:21:22 +01:00
|
|
|
|
|
|
|
# ----------------------------------------------------------------------------
|
|
|
|
# convenience subs
|
|
|
|
# ----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
sub wrap_chdir {
|
|
|
|
chdir($_[0]) or die "$ABRT chdir $_[0] failed: $! at ", (caller)[1], " line ", (caller)[2], "\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
sub wrap_open {
|
|
|
|
open (my $fh, $_[0], $_[1]) or die "$ABRT open $_[1] failed: $! at ", (caller)[1], " line ", (caller)[2], "\n" .
|
|
|
|
( $_[2] || '' ); # suffix custom error message if given
|
|
|
|
return $fh;
|
|
|
|
}
|
|
|
|
|
2010-01-31 18:40:12 +01:00
|
|
|
sub log_it {
|
|
|
|
open my $log_fh, ">>", $ENV{GL_LOG} or die "open log failed: $!\n";
|
|
|
|
print $log_fh @_;
|
|
|
|
close $log_fh or die "close log failed: $!\n";
|
|
|
|
}
|
|
|
|
|
2010-01-31 19:26:58 +01:00
|
|
|
# check one ref
|
|
|
|
sub check_ref {
|
|
|
|
|
|
|
|
# normally, the $ref will be whatever ref the commit is trying to update
|
|
|
|
# (like refs/heads/master or whatever). At least one of the refexes that
|
|
|
|
# pertain to this user must match this ref **and** the corresponding
|
|
|
|
# permission must also match the action (W or +) being attempted. If none
|
|
|
|
# of them match, the access is denied.
|
|
|
|
|
|
|
|
# Notice that the function DIES!!! Any future changes that require more
|
|
|
|
# work to be done *after* this, even on failure, can start using return
|
|
|
|
# codes etc., but for now we're happy to just die.
|
|
|
|
|
|
|
|
my ($allowed_refs, $repo, $ref, $perm) = @_;
|
|
|
|
for my $ar (@{$allowed_refs}) {
|
|
|
|
my $refex = (keys %$ar)[0];
|
|
|
|
# refex? sure -- a regex to match a ref against :)
|
|
|
|
next unless $ref =~ /^$refex/;
|
|
|
|
die "$perm $ref $ENV{GL_USER} DENIED by $refex\n" if $ar->{$refex} eq '-';
|
|
|
|
|
|
|
|
# as far as *this* ref is concerned we're ok
|
|
|
|
return $refex if ($ar->{$refex} =~ /\Q$perm/);
|
|
|
|
}
|
|
|
|
die "$perm $ref $repo $ENV{GL_USER} DENIED by fallthru\n";
|
|
|
|
}
|
|
|
|
|
2009-10-25 03:59:52 +01:00
|
|
|
# ----------------------------------------------------------------------------
|
|
|
|
# where is the rc file hiding?
|
|
|
|
# ----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
sub where_is_rc
|
|
|
|
{
|
|
|
|
# till now, the rc file was in one fixed place: .gitolite.rc in $HOME of
|
|
|
|
# the user hosting the gitolite repos. This was fine, because gitolite is
|
|
|
|
# all about empowering non-root users :-)
|
|
|
|
|
|
|
|
# then we wanted to make a debian package out of it (thank you, Rhonda!)
|
|
|
|
# which means (a) it's going to be installed by root anyway and (b) any
|
|
|
|
# config files have to be in /etc/<something>
|
|
|
|
|
|
|
|
# the only way to resolve this in a backward compat way is to look for the
|
|
|
|
# $HOME one, and if you don't find it look for the /etc one
|
|
|
|
|
|
|
|
# this common routine does that, setting an env var for the first one it
|
|
|
|
# finds
|
|
|
|
|
|
|
|
return if $ENV{GL_RC};
|
|
|
|
|
|
|
|
for my $glrc ( $ENV{HOME} . "/.gitolite.rc", "/etc/gitolite/gitolite.rc" ) {
|
|
|
|
if (-f $glrc) {
|
|
|
|
$ENV{GL_RC} = $glrc;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-12-04 05:21:22 +01:00
|
|
|
# ----------------------------------------------------------------------------
|
|
|
|
# create a new repository
|
|
|
|
# ----------------------------------------------------------------------------
|
2009-11-26 17:00:59 +01:00
|
|
|
|
|
|
|
# NOTE: this sub will change your cwd; caller beware!
|
|
|
|
sub new_repo
|
|
|
|
{
|
|
|
|
my ($repo, $hooks_dir) = @_;
|
|
|
|
|
|
|
|
umask($REPO_UMASK);
|
|
|
|
|
|
|
|
system("mkdir", "-p", "$repo.git") and die "$ABRT mkdir $repo.git failed: $!\n";
|
|
|
|
# erm, note that's "and die" not "or die" as is normal in perl
|
|
|
|
wrap_chdir("$repo.git");
|
|
|
|
system("git --bare init >&2");
|
|
|
|
# propagate our own, plus any local admin-defined, hooks
|
|
|
|
system("cp $hooks_dir/* hooks/");
|
|
|
|
chmod 0755, "hooks/update";
|
|
|
|
}
|
|
|
|
|
2009-12-04 05:21:22 +01:00
|
|
|
# ----------------------------------------------------------------------------
|
|
|
|
# parse the compiled acl
|
|
|
|
# ----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
sub parse_acl
|
|
|
|
{
|
|
|
|
my $GL_CONF_COMPILED = shift;
|
|
|
|
die "parse $GL_CONF_COMPILED failed: " . ($! or $@) unless do $GL_CONF_COMPILED;
|
|
|
|
}
|
|
|
|
|
|
|
|
# ----------------------------------------------------------------------------
|
|
|
|
# print a report of $user's basic permissions
|
|
|
|
# ----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
# basic means wildcards will be shown as wildcards; this is pretty much what
|
|
|
|
# got parsed by the compile script
|
|
|
|
sub report_basic
|
|
|
|
{
|
|
|
|
my($GL_ADMINDIR, $GL_CONF_COMPILED, $user) = @_;
|
|
|
|
|
|
|
|
&parse_acl($GL_CONF_COMPILED);
|
|
|
|
|
|
|
|
# send back some useful info if no command was given
|
|
|
|
print "hello $user, the gitolite version here is ";
|
|
|
|
system("cat", "$GL_ADMINDIR/src/VERSION");
|
|
|
|
print "\ryou have the following permissions:\n\r";
|
|
|
|
for my $r (sort keys %repos) {
|
|
|
|
my $perm .= ( $repos{$r}{R}{'@all'} ? ' @' : ( $repos{$r}{R}{$user} ? ' R' : '' ) );
|
|
|
|
$perm .= ( $repos{$r}{W}{'@all'} ? ' @' : ( $repos{$r}{W}{$user} ? ' W' : '' ) );
|
|
|
|
print "$perm\t$r\n\r" if $perm;
|
|
|
|
}
|
|
|
|
}
|
2009-10-25 03:59:52 +01:00
|
|
|
1;
|