refactored and lifted out the line parse part from inside parse_conf_file

adapted from code by kpfleming@digium.com.  I basically cherry-picked
the top commit on "pu-work" (30068d1) on his fork at github, and made
some minor fixups to it
This commit is contained in:
Sitaram Chamarty 2010-09-04 15:03:06 +05:30
parent 5f342c0444
commit 7b633049be

View file

@ -163,35 +163,12 @@ sub check_fragment_repo_disallowed
return 1; return 1;
} }
sub parse_conf_file sub parse_conf_line
{ {
my ($conffile, $fragment) = @_; my ($line, $fragment, $repos_p, $ignored_p) = @_;
# the second arg, $fragment, is passed in as "master" when parsing the
# main config, and the fragment name when parsing a fragment. In the
# latter case, the parser uses that information to ignore (and warn about)
# any repos in the fragment that are not members of the "repo group" of
# the same name.
my %ignored = ();
my $conf_fh = wrap_open( "<", $conffile );
# the syntax is fairly simple, so we parse it inline
my @repos;
while (<$conf_fh>)
{
# kill comments, but take care of "#" inside *simple* strings
s/^((".*?"|[^#"])*)#.*/$1/;
# normalise whitespace; keeps later regexes very simple
s/=/ = /;
s/\s+/ /g;
s/^ //;
s/ $//;
# and blank lines
next unless /\S/;
# user or repo groups # user or repo groups
if (/^(@\S+) = (.*)/) if ($line =~ /^(@\S+) = (.*)/)
{ {
die "$ABRT defining groups is not allowed inside fragments\n" die "$ABRT defining groups is not allowed inside fragments\n"
if $GL_BIG_CONFIG and $fragment ne 'master'; if $GL_BIG_CONFIG and $fragment ne 'master';
@ -201,25 +178,25 @@ sub parse_conf_file
die "$ABRT bad group $1\n" unless $1 =~ $REPONAME_PATT; die "$ABRT bad group $1\n" unless $1 =~ $REPONAME_PATT;
} }
# repo(s) # repo(s)
elsif (/^repo (.*)/) elsif ($line =~ /^repo (.*)/)
{ {
# grab the list... # grab the list...
@repos = split ' ', $1; @{ $repos_p } = split ' ', $1;
unless (@repos == 1 and $repos[0] eq '@all') { unless (@{ $repos_p } == 1 and $repos_p->[0] eq '@all') {
# ...expand groups in the default case # ...expand groups in the default case
@repos = expand_list ( @repos ) unless $GL_BIG_CONFIG; @{ $repos_p } = expand_list ( @{ $repos_p } ) unless $GL_BIG_CONFIG;
# ...sanity check # ...sanity check
for (@repos) { for (@{ $repos_p }) {
die "$ABRT bad reponame $_\n" die "$ABRT bad reponame $_\n"
if ($GL_WILDREPOS and $_ !~ $REPOPATT_PATT); if ($GL_WILDREPOS and $_ !~ $REPOPATT_PATT);
die "$ABRT bad reponame $_ or you forgot to set \$GL_WILDREPOS\n" die "$ABRT bad reponame $_ or you forgot to set \$GL_WILDREPOS\n"
if (not $GL_WILDREPOS and $_ !~ $REPONAME_PATT); if (not $GL_WILDREPOS and $_ !~ $REPONAME_PATT);
} }
} }
s/\bCREAT[EO]R\b/\$creator/g for @repos; s/\bCREAT[EO]R\b/\$creator/g for @{ $repos_p };
} }
# actual permission line # actual permission line
elsif (/^(-|C|R|RW\+?(?:C?D?|D?C?)) (.* )?= (.+)/) elsif ($line =~ /^(-|C|R|RW\+?(?:C?D?|D?C?)) (.* )?= (.+)/)
{ {
my $perms = $1; my $perms = $1;
my @refs; @refs = split( ' ', $2 ) if $2; my @refs; @refs = split( ' ', $2 ) if $2;
@ -246,7 +223,7 @@ sub parse_conf_file
s/\bWRITERS\b/\$writers/g for @users; s/\bWRITERS\b/\$writers/g for @users;
# ok, we can finally populate the %repos hash # ok, we can finally populate the %repos hash
for my $repo (@repos) # each repo in the current stanza for my $repo (@{ $repos_p }) # each repo in the current stanza
{ {
# if we're processing a delegated config file (not the master # if we're processing a delegated config file (not the master
# config), we need to prevent attempts by that admin to obtain # config), we need to prevent attempts by that admin to obtain
@ -255,7 +232,7 @@ sub parse_conf_file
# trying to set access for $repo (='foo')... # trying to set access for $repo (='foo')...
if (check_fragment_repo_disallowed( $fragment, $repo )) if (check_fragment_repo_disallowed( $fragment, $repo ))
{ {
$ignored{$fragment}{$repo} = 1; $ignored_p->{$fragment}{$repo} = 1;
next; next;
} }
for my $user (@users) for my $user (@users)
@ -299,13 +276,13 @@ sub parse_conf_file
} }
} }
# configuration # configuration
elsif (/^config (.+) = ?(.*)/) elsif ($line =~ /^config (.+) = ?(.*)/)
{ {
my ($key, $value) = ($1, $2); my ($key, $value) = ($1, $2);
my @validkeys = split(' ', ($GL_GITCONFIG_KEYS || '') ); my @validkeys = split(' ', ($GL_GITCONFIG_KEYS || '') );
my @matched = grep { $key =~ /^$_$/ } @validkeys; my @matched = grep { $key =~ /^$_$/ } @validkeys;
die "$ABRT git config $key not allowed\n" if (@matched < 1); die "$ABRT git config $key not allowed\n" if (@matched < 1);
for my $repo (@repos) # each repo in the current stanza for my $repo (@{ $repos_p }) # each repo in the current stanza
{ {
$repo_config{$repo}{$key} = $value; $repo_config{$repo}{$key} = $value;
# no problem if it's a plain repo (non-pattern, non-groupname) # no problem if it's a plain repo (non-pattern, non-groupname)
@ -320,7 +297,7 @@ sub parse_conf_file
} }
} }
# include # include
elsif (/^include "(.+)"/) elsif ($line =~ /^include "(.+)"/)
{ {
my $file = $1; my $file = $1;
$file = "$GL_ADMINDIR/conf/$file" unless $file =~ /^\//; $file = "$GL_ADMINDIR/conf/$file" unless $file =~ /^\//;
@ -332,7 +309,7 @@ sub parse_conf_file
# very simple syntax for the gitweb description of repo; one of: # very simple syntax for the gitweb description of repo; one of:
# reponame = "some description string" # reponame = "some description string"
# reponame "owner name" = "some description string" # reponame "owner name" = "some description string"
elsif (/^(\S+)(?: "(.*?)")? = "(.*)"$/) elsif ($line =~ /^(\S+)(?: "(.*?)")? = "(.*)"$/)
{ {
my ($repo, $owner, $desc) = ($1, $2, $3); my ($repo, $owner, $desc) = ($1, $2, $3);
die "$ABRT bad repo name $repo\n" unless $repo =~ $REPONAME_PATT; die "$ABRT bad repo name $repo\n" unless $repo =~ $REPONAME_PATT;
@ -342,9 +319,48 @@ sub parse_conf_file
} }
else else
{ {
die "$ABRT can't make head or tail of '$_'\n"; die "$ABRT can't make head or tail of '$line'\n";
} }
} }
sub cleanup_conf_line
{
my ($line) = @_;
# kill comments, but take care of "#" inside *simple* strings
$line =~ s/^((".*?"|[^#"])*)#.*/$1/;
# normalise whitespace; keeps later regexes very simple
$line =~ s/=/ = /;
$line =~ s/\s+/ /g;
$line =~ s/^ //;
$line =~ s/ $//;
return $line;
}
sub parse_conf_file
{
my ($conffile, $fragment) = @_;
# the second arg, $fragment, is passed in as "master" when parsing the
# main config, and the fragment name when parsing a fragment. In the
# latter case, the parser uses that information to ignore (and warn about)
# any repos in the fragment that are not members of the "repo group" of
# the same name.
my %ignored = ();
my $conf_fh = wrap_open( "<", $conffile );
# the syntax is fairly simple, so we parse it inline
my @repos;
my $line;
while (<$conf_fh>)
{
$line = cleanup_conf_line($_);
# skip blank lines
next unless $line =~ /\S/;
parse_conf_line( $line, $fragment, \@repos, \%ignored );
}
for my $ig (sort keys %ignored) for my $ig (sort keys %ignored)
{ {
warn "\n\t\t***** WARNING *****\n" . warn "\n\t\t***** WARNING *****\n" .