git_configs almost done, but

real testing can only happen after wildrepos is finished (specifically,
when memberships() can return regex repo names also)
This commit is contained in:
Sitaram Chamarty 2012-03-16 14:29:45 +05:30
parent 45348a4225
commit f21d17e086
5 changed files with 161 additions and 26 deletions

View file

@ -60,11 +60,11 @@ sub parse {
}
} elsif ( $line =~ /^config (.+) = ?(.*)/ ) {
my ( $key, $value ) = ( $1, $2 );
my @validkeys = split( ' ', ( $rc{GL_GITCONFIG_KEYS} || '' ) );
my @validkeys = split( ' ', ( $rc{GIT_CONFIG_KEYS} || '' ) );
push @validkeys, "gitolite-options\\..*";
my @matched = grep { $key =~ /^$_$/ } @validkeys;
# XXX move this also to add_config: _die "git config $key not allowed\ncheck GL_GITCONFIG_KEYS in the rc file for how to allow it" if (@matched < 1);
# XXX both $key and $value must satisfy a liberal but secure pattern
_die "git config $key not allowed\ncheck GIT_CONFIG_KEYS in the rc file" if (@matched < 1);
_die "bad value '$value'" if $value =~ $UNSAFE_PATT;
add_config( 1, $key, $value );
} elsif ( $line =~ /^subconf (\S+)$/ ) {
trace( 2, $line );

View file

@ -6,6 +6,7 @@ package Gitolite::Conf::Load;
@EXPORT = qw(
load
access
git_config
vrefs
lister_dispatch
);
@ -89,6 +90,44 @@ sub access {
return "$aa $ref $repo $user DENIED by fallthru";
}
sub git_config {
my ( $repo, $key ) = @_;
$key ||= '.';
load($repo);
# read comments bottom up
my %ret =
# and take the second and third elements to make up your new hash
map { $_->[1] => $_->[2] }
# keep only the ones where the second element matches your key
grep { $_->[1] =~ qr($key) }
# sort this list of listrefs by the first element in each list ref'd to
sort { $a->[0] <=> $b->[0] }
# dereference it (into a list of listrefs)
map { @$_ }
# take the value of that entry
map { $configs{$_} }
# if it has an entry in %configs
grep { $configs{$_} }
# for each "repo" that represents us
memberships($repo);
# %configs looks like this (for each 'foo' that is in memberships())
# 'foo' => [ [ 6, 'foo.bar', 'repo' ], [ 7, 'foodbar', 'repoD' ], [ 8, 'foo.czar', 'jule' ] ],
# the first map gets you the value
# [ [ 6, 'foo.bar', 'repo' ], [ 7, 'foodbar', 'repoD' ], [ 8, 'foo.czar', 'jule' ] ],
# the deref gets you
# [ 6, 'foo.bar', 'repo' ], [ 7, 'foodbar', 'repoD' ], [ 8, 'foo.czar', 'jule' ]
# the sort rearranges it (in this case it's already sorted but anyway...)
# the grep gets you this, assuming the key is foo.bar (and "." is regex ".')
# [ 6, 'foo.bar', 'repo' ], [ 7, 'foodbar', 'repoD' ]
# and the final map does this:
# 'foo.bar'=>'repo' , 'foodbar'=>'repoD'
return \%ret;
}
# ----------------------------------------------------------------------
sub load_common {

View file

@ -5,12 +5,14 @@ package Gitolite::Conf::Store;
@EXPORT = qw(
add_to_group
expand_list
set_repolist
parse_refs
parse_users
add_rule
add_config
set_subconf
expand_list
new_repos
new_repo
hook_repos
@ -40,7 +42,7 @@ my %split_conf;
my @repolist; # current repo list; reset on each 'repo ...' line
my $subconf = 'master';
my $ruleseq = 0;
my $nextseq = 0;
my %ignored;
# XXX you still have to "warn" if this has any entries
@ -60,24 +62,6 @@ sub add_to_group {
$groups{$lhs} = {} unless $groups{$lhs};
}
sub expand_list {
my @list = @_;
my @new_list = ();
for my $item (@list) {
if ( $item =~ /^@/ and $item ne '@all' ) # nested group
{
_die "undefined group $item" unless $groups{$item};
# add those names to the list
push @new_list, sort keys %{ $groups{$item} };
} else {
push @new_list, $item;
}
}
return @new_list;
}
sub set_repolist {
@repolist = @_;
@ -119,7 +103,7 @@ sub add_rule {
_die "bad ref '$ref'" unless $ref =~ $REPOPATT_PATT;
_die "bad user '$user'" unless $user =~ $USERNAME_PATT;
$ruleseq++;
$nextseq++;
for my $repo (@repolist) {
if ( check_subconf_repo_disallowed( $subconf, $repo ) ) {
my $repo = $repo;
@ -128,7 +112,7 @@ sub add_rule {
next;
}
push @{ $repos{$repo}{$user} }, [ $ruleseq, $perm, $ref ];
push @{ $repos{$repo}{$user} }, [ $nextseq, $perm, $ref ];
# XXX g2 diff: we're not doing a lint check for usernames versus pubkeys;
# maybe we can add that later
@ -141,11 +125,41 @@ sub add_rule {
}
}
sub add_config {
my($n, $key, $value) = @_;
$nextseq++;
for my $repo (@repolist) {
# XXX should we check_subconf_repo_disallowed here?
push @{ $configs{$repo} }, [ $nextseq, $key, $value ];
}
}
sub set_subconf {
$subconf = shift;
_die "bad subconf '$subconf'" unless $subconf =~ /^[-\w.]+$/;
}
# ----------------------------------------------------------------------
sub expand_list {
my @list = @_;
my @new_list = ();
for my $item (@list) {
if ( $item =~ /^@/ and $item ne '@all' ) # nested group
{
_die "undefined group $item" unless $groups{$item};
# add those names to the list
push @new_list, sort keys %{ $groups{$item} };
} else {
push @new_list, $item;
}
}
return @new_list;
}
sub new_repos {
trace(3);
_chdir( $rc{GL_REPO_BASE} );

View file

@ -14,6 +14,7 @@ package Gitolite::Rc;
$REPONAME_PATT
$REPOPATT_PATT
$USERNAME_PATT
$UNSAFE_PATT
);
use Exporter 'import';
@ -42,6 +43,7 @@ $REF_OR_FILENAME_PATT = qr(^[0-9a-zA-Z][0-9a-zA-Z._\@/+ :,-]*$);
$REPONAME_PATT = qr(^\@?[0-9a-zA-Z][0-9a-zA-Z._\@/+-]*$);
$REPOPATT_PATT = qr(^\@?[0-9a-zA-Z[][\\^.$|()[\]*+?{}0-9a-zA-Z._\@/,-]*$);
$USERNAME_PATT = qr(^\@?[0-9a-zA-Z][0-9a-zA-Z._\@+-]*$);
$UNSAFE_PATT = qr([`~#\$\&()|;<>]);
# ----------------------------------------------------------------------
@ -183,7 +185,7 @@ __DATA__
%RC = (
UMASK => 0077,
GL_GITCONFIG_KEYS => "",
GIT_CONFIG_KEYS => "",
# comment out or uncomment as needed
# these will run in sequence during the conf file parse

80
src/commands/git-config Executable file
View file

@ -0,0 +1,80 @@
#!/usr/bin/perl
use strict;
use warnings;
use Getopt::Long;
use lib $ENV{GL_BINDIR};
use Gitolite::Rc;
use Gitolite::Common;
use Gitolite::Conf::Load;
=for usage
Usage: gitolite git-config [-n] [-q] [-r] <repo> <key|pattern>
Print git config keys and values for the given repo. The key is either a full
key, or, if '-r' is supplied, a regex that is applied to all available keys.
-q exit code only (shell truth; 0 is success)
-n suppress trailing newline when used as key (not pattern)
-r treat key as regex pattern (unanchored)
Examples:
gitolite git-config repo gitweb.owner
gitolite git-config -q repo gitweb.owner
gitolite git-config -r repo gitweb
When the key is treated as a pattern, prints one key+value per line, tab
separated:
reponame<tab>key<tab>value<newline>
Otherwise the output is just the value.
Finally, see the advanced use section of 'gitolite access -h' -- you can do
something similar here also:
gitolite list-phy-repos | gitolite git-config -r % gitweb\\. | cut -f1 > ~/projects.list
=cut
usage() if not @ARGV;
my ( $help, $nonl, $quiet, $regex ) = (0) x 4;
GetOptions(
'n' => \$nonl,
'q' => \$quiet,
'r' => \$regex,
'h' => \$help,
) or usage();
my ( $repo, $key ) = @ARGV;
usage() unless $key;
my $ret = '';
if ( $repo ne '%' and $key ne '%' ) {
# single repo, single key; no STDIN
$key = "^\Q$key\E\$" unless $regex;
$ret = git_config( $repo, $key );
# unlike access, there's nothing to print if we don't find any matching keys
exit 1 unless %$ret;
map { print "$repo\t$_\t" . $ret->{$_} . "\n" } sort keys %$ret unless $quiet;
exit 0;
}
$repo = '' if $repo eq '%';
$key = '' if $key eq '%';
_die "'-q' doesn't go with using a pipe" if $quiet;
@ARGV = ();
while (<>) {
my @in = split;
my $r = $repo || shift @in;
my $k = $key || shift @in;
$k = "^\Q$k\E\$" unless $regex;
$ret = git_config( $r, $k );
next unless %$ret;
map { print "$r\t$_\t" . $ret->{$_} . "\n" } sort keys %$ret;
}