fix up gitweb, daemon, for wild + big-config

Implementation notes:

  - %repo_config is now "our", not "my"
  - collect_repo_patts now uses repo_rights to get the name of the wild
    card repo (if any) that pertains to the physical $repo, instead of
    all that new code (duh!)
  - new "can_read(repo, user)" sub (to help daemon and gitweb use)
  - the "convenience copy on steroids" thing now copies %repo_config
    also, not just %repos.  This makes setup_repo_configs simpler
  - $creator gets substituted into %groups also; we need that now that
    we (%repos and %groups) are working closer together :)
This commit is contained in:
Sitaram Chamarty 2010-07-19 16:47:38 +05:30
parent 8deee9b6bd
commit f21e7780a1
3 changed files with 58 additions and 52 deletions

View file

@ -40,6 +40,7 @@ our $REPOPATT_PATT=qr(^\@?[0-9a-zA-Z[][\\^.$|()[\]*+?{}0-9a-zA-Z._\@/-]*$);
our ($REPO_UMASK, $GL_WILDREPOS, $GL_PACKAGE_CONF, $GL_PACKAGE_HOOKS, $REPO_BASE, $GL_CONF_COMPILED, $GL_BIG_CONFIG); our ($REPO_UMASK, $GL_WILDREPOS, $GL_PACKAGE_CONF, $GL_PACKAGE_HOOKS, $REPO_BASE, $GL_CONF_COMPILED, $GL_BIG_CONFIG);
our %repos; our %repos;
our %groups; our %groups;
our %repo_config;
our $data_version; our $data_version;
our $current_data_version = '1.5'; our $current_data_version = '1.5';
@ -129,24 +130,9 @@ sub collect_repo_patts
for my $repo (`find . -type d -name "*.git"`) { for my $repo (`find . -type d -name "*.git"`) {
chomp ($repo); chomp ($repo);
$repo =~ s(\./(.*)\.git$)($1); $repo =~ s(\./(.*)\.git$)($1);
# if its non-wild that's all you need # the key has to be in the list, since the repo physically exists
if ($repos_p->{$repo}) { my($perm, $creator, $wild) = &repo_rights($repo);
$repo_patts{$repo} = $repo; $repo_patts{$repo} = $wild || $repo;
} else {
# otherwise it gets a wee bit complicated ;-)
chomp (my $creator = `cat $repo.git/gl-creater`);
for my $key (keys %$repos_p) {
my $key2 = $key;
# subst $creator in the copy with the creator name
$key2 =~ s/\$creator/$creator/g;
# match the new key against $repo
if ($repo =~ /^$key2$/) {
# and if it matched you're done for this $repo
$repo_patts{$repo} = $key;
last;
}
}
}
} }
return %repo_patts; return %repo_patts;
@ -290,9 +276,9 @@ sub get_set_desc
sub setup_repo_configs sub setup_repo_configs
{ {
my ($repo, $repo_patt, $repo_config_p) = @_; my ($repo, $repo_config_p) = @_;
while ( my ($key, $value) = each(%{ $repo_config_p->{$repo_patt} }) ) { while ( my ($key, $value) = each(%{ $repo_config_p->{$repo} }) ) {
if ($value) { if ($value) {
$value =~ s/^"(.*)"$/$1/; $value =~ s/^"(.*)"$/$1/;
system("git", "config", $key, $value); system("git", "config", $key, $value);
@ -306,12 +292,13 @@ sub setup_repo_configs
# set/unset daemon access # set/unset daemon access
# ---------------------------------------------------------------------------- # ----------------------------------------------------------------------------
# does not return anything; just touch/unlink the appropriate file
my $export_ok = "git-daemon-export-ok"; my $export_ok = "git-daemon-export-ok";
sub setup_daemon_access sub setup_daemon_access
{ {
my ($repo, $allowed) = @_; my $repo = shift;
if ($allowed) { if (&can_read($repo, 'daemon')) {
system("touch $export_ok"); system("touch $export_ok");
} else { } else {
unlink($export_ok); unlink($export_ok);
@ -322,13 +309,18 @@ sub setup_daemon_access
# set/unset gitweb access # set/unset gitweb access
# ---------------------------------------------------------------------------- # ----------------------------------------------------------------------------
# returns 1 if gitweb access has happened; this is to allow the caller to add
# an entry to the projects.list file
my $desc_file = "description"; my $desc_file = "description";
sub setup_gitweb_access sub setup_gitweb_access
# this also sets "owner" for gitweb, by the way # this also sets "owner" for gitweb, by the way
{ {
my ($repo, $allowed, $desc, $owner) = @_; my ($repo, $desc, $owner) = @_;
my $ret = 0;
if ($allowed) { # passing in a descr implies 'R = gitweb'
if ($desc or &can_read($repo, 'gitweb')) {
$ret = 1;
if ($desc) { if ($desc) {
open(DESC, ">", $desc_file); open(DESC, ">", $desc_file);
print DESC $desc . "\n"; print DESC $desc . "\n";
@ -351,6 +343,8 @@ sub setup_gitweb_access
if (length($keys) == 0) { if (length($keys) == 0) {
system("git config --remove-section gitweb 2>/dev/null"); system("git config --remove-section gitweb 2>/dev/null");
} }
return $ret;
} }
# ---------------------------------------------------------------------------- # ----------------------------------------------------------------------------
@ -409,6 +403,7 @@ sub parse_acl
$repos{$dr}{DELETE_IS_D} = 1 if $repos{$r}{DELETE_IS_D}; $repos{$dr}{DELETE_IS_D} = 1 if $repos{$r}{DELETE_IS_D};
$repos{$dr}{CREATE_IS_C} = 1 if $repos{$r}{CREATE_IS_C}; $repos{$dr}{CREATE_IS_C} = 1 if $repos{$r}{CREATE_IS_C};
$repos{$dr}{NAME_LIMITS} = 1 if $repos{$r}{NAME_LIMITS}; $repos{$dr}{NAME_LIMITS} = 1 if $repos{$r}{NAME_LIMITS};
$repo_config{$dr} = $repo_config{$r} if $repo_config{$r};
for my $u ('@all', "$gl_user - wild", @user_plus) { for my $u ('@all', "$gl_user - wild", @user_plus) {
my $du = $gl_user; $du = '@all' if $u eq '@all'; my $du = $gl_user; $du = '@all' if $u eq '@all';
@ -522,8 +517,6 @@ sub expand_wild
$repo =~ s/^\.\///; $repo =~ s/^\.\///;
$repo =~ s/\.git$//; $repo =~ s/\.git$//;
return if $last_repo eq $repo; # a wee bit o' caching, though not yet needed
# we get passed an actual repo name. It may be a normal # 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 # (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" # a wildrepo, it may or may not exist. If it doesn't exist, the "C"
@ -582,6 +575,14 @@ sub cli_repo_rights {
print "$perm $creator\n"; print "$perm $creator\n";
} }
sub can_read {
my $repo = shift;
my $user = shift || $ENV{GL_USER};
local $ENV{GL_USER} = $user;
my ($perm, $creator, $wild) = &repo_rights($repo);
return $perm =~ /R/;
}
# ---------------------------------------------------------------------------- # ----------------------------------------------------------------------------
# setup the ~/.ssh/authorized_keys file # setup the ~/.ssh/authorized_keys file
# ---------------------------------------------------------------------------- # ----------------------------------------------------------------------------

View file

@ -207,10 +207,9 @@ if ($perm =~ /C/) {
# it was missing, and you have create perms # it was missing, and you have create perms
wrap_chdir("$ENV{GL_REPO_BASE_ABS}"); wrap_chdir("$ENV{GL_REPO_BASE_ABS}");
new_repo($repo, "$GL_ADMINDIR/hooks/common", $user); new_repo($repo, "$GL_ADMINDIR/hooks/common", $user);
&setup_repo_configs($repo, $ENV{GL_REPOPATT}, \%repo_config); &setup_repo_configs($repo, \%repo_config);
&setup_daemon_access($repo, $repos{$ENV{GL_REPOPATT}}{'R'}{'daemon'} || ''); &setup_daemon_access($repo);
&setup_gitweb_access($repo, $repos{$ENV{GL_REPOPATT}}{'R'}{'gitweb'} || '', '', ''); system("echo $repo.git >> $PROJECTS_LIST") if &setup_gitweb_access($repo, '', '');
system("echo $repo.git >> $PROJECTS_LIST");
wrap_chdir($ENV{HOME}); wrap_chdir($ENV{HOME});
} }

View file

@ -105,7 +105,7 @@ our $current_data_version; # this comes from gitolite.pm
my %user_list = (); my %user_list = ();
# repo configurations # repo configurations
my %repo_config = (); our %repo_config = ();
# gitweb descriptions and owners; plain text, keyed by "$repo.git" # gitweb descriptions and owners; plain text, keyed by "$repo.git"
my %desc = (); my %desc = ();
@ -311,7 +311,15 @@ sub parse_conf_file
for my $repo (@repos) # each repo in the current stanza for my $repo (@repos) # each repo in the current stanza
{ {
$repo_config{$repo}{$key} = $value; $repo_config{$repo}{$key} = $value;
print STDERR "$WARN git config set for $repo but \$GL_GITCONFIG_WILD not set\n" unless $repo =~ $REPONAME_PATT or $GL_GITCONFIG_WILD; # no problem if it's a plain repo (non-pattern, non-groupname)
# OR wild configs are allowed
unless ( ($repo =~ $REPONAME_PATT and $repo !~ /^@/) or $GL_GITCONFIG_WILD) {
my @r = ($repo); # single wildpatt
@r = sort keys %{ $groups{$repo} } if $groups{$repo}; # or a group; get its members
do {
print STDERR "$WARN git config set for $_ but \$GL_GITCONFIG_WILD not set\n" unless $_ =~ $REPONAME_PATT
} for @r;
}
} }
} }
# include # include
@ -389,7 +397,12 @@ $dumped_data .= Data::Dumper->Dump([\%repo_config], [qw(*repo_config)]) if %repo
# much... # much...
$dumped_data =~ s/'(?=[^']*\$(?:creator|readers|writers|gl_user))~?(.*?)'/"$1"/g; $dumped_data =~ s/'(?=[^']*\$(?:creator|readers|writers|gl_user))~?(.*?)'/"$1"/g;
print $compiled_fh $dumped_data; print $compiled_fh $dumped_data;
print $compiled_fh Data::Dumper->Dump([\%groups], [qw(*groups)]) if $GL_BIG_CONFIG and %groups; if ($GL_BIG_CONFIG and %groups) {
$dumped_data = Data::Dumper->Dump([\%groups], [qw(*groups)]);
$dumped_data =~ s/\bCREAT[EO]R\b/\$creator/g;
$dumped_data =~ s/'(?=[^']*\$(?:creator|readers|writers|gl_user))~?(.*?)'/"$1"/g;
print $compiled_fh $dumped_data;
}
close $compiled_fh or die "$ABRT close compiled-conf failed: $!\n"; close $compiled_fh or die "$ABRT close compiled-conf failed: $!\n";
rename "$GL_CONF_COMPILED.new", "$GL_CONF_COMPILED"; rename "$GL_CONF_COMPILED.new", "$GL_CONF_COMPILED";
@ -504,23 +517,12 @@ my %projlist = ();
# for each real repo (and remember this will be empty, thus skipping all this, # for each real repo (and remember this will be empty, thus skipping all this,
# if $GL_NO_DAEMON_NO_GITWEB is on!) # if $GL_NO_DAEMON_NO_GITWEB is on!)
for my $repo (keys %repo_patts) { for my $repo (keys %repo_patts) {
my $repo_patt = $repo_patts{$repo}; # if non-wild, $repo_patt will be eq $repo anyway my $repo_patt = $repo_patts{$repo};
wrap_chdir("$ENV{GL_REPO_BASE_ABS}/$repo.git"); wrap_chdir("$ENV{GL_REPO_BASE_ABS}/$repo.git");
# git config
if ($repo_patt eq $repo or $GL_GITCONFIG_WILD) {
# erm, what that means is that it's either a non-wild repo being
# config'd or a wild one but gitconfig is allowed on wilds.
# XXX do we really need GL_GITCONFIG_WILD now? It was meant to be
# only an efficiency thing, but that was before this whole revamp;
# we already trawl through $REPO_BASE exactly once now anyway!
# ...need to think about this
&setup_repo_configs($repo, $repo_patt, \%repo_config) if $repo_config{$repo_patt};
}
# daemon is easy # daemon is easy
&setup_daemon_access($repo, $repos{$repo_patt}{'R'}{'daemon'} || ''); &setup_daemon_access($repo);
# gitweb is a little more complicated. Here're some notes: # gitweb is a little more complicated. Here're some notes:
# - "setup_gitweb_access" also sets "owner", despite the name # - "setup_gitweb_access" also sets "owner", despite the name
@ -532,12 +534,16 @@ for my $repo (keys %repo_patts) {
# into the "repo foo" section; they're essentialy independent. # into the "repo foo" section; they're essentialy independent.
# Anyway, I believe it doesn't make sense to have all wild repos # Anyway, I believe it doesn't make sense to have all wild repos
# (for some pattern) to have the same description and owner. # (for some pattern) to have the same description and owner.
if ($repos{$repo_patt}{'R'}{'gitweb'} or $desc{"$repo.git"}) { $projlist{"$repo.git"} = 1 if &setup_gitweb_access($repo, $desc{"$repo.git"} || '', $owner{"$repo.git"} || '');
$projlist{"$repo.git"} = 1;
&setup_gitweb_access($repo, 1, $desc{"$repo.git"} || '', $owner{"$repo.git"} || ''); # git config
} else { # implementation note: this must happen *after* one of the previous 2
&setup_gitweb_access($repo, 0, '', ''); # calls (setup daemon or gitweb). The reason is that they call
} # "can_read", which eventually calls parse_acl with the right "creator"
# set for the *current* repo, which in turn stores translated values fr
# $creator in the repo_config hash, which, (phew!) is needed for a match
# that eventually gets you a valid $repo_config{} below
&setup_repo_configs($repo, \%repo_config) if $repo_config{$repo};
} }
# write out the project list # write out the project list