fix rt.cpan.org#115326, added IFDefine support, fix POD indentation

git-svn-id: http://dev.catalyst.perl.org/repos/Config-General/trunk@111 be1acefe-a474-0410-9a34-9b3221f2030f
This commit is contained in:
Thomas von Dein
2016-07-08 08:46:02 +00:00
parent 7a48e048cf
commit a49de35c81
7 changed files with 990 additions and 883 deletions

View File

@@ -1,3 +1,19 @@
2.62 - fix rt.cpan.org#115326: Callback on 'pre_open' not called
when glob expands to one include file
- added patch by Niels van Dijke, which adds apache IFDefine
support. Use -UseApacheIfDefine=>1 to enable, add defines
with -Define and add <IFDefine ...> to your config, see
pod for details.
- added test case for the code.
- fixed unindented half of the pod, which was largely no
readable because of this. However, I wonder why this hasn't
reported, seems nobody reads the docs :)
- fixed tab/space issues here and there
2.61 - fix rt.cpan.org#113671: ignore utf BOM, if any and turn on 2.61 - fix rt.cpan.org#113671: ignore utf BOM, if any and turn on
UTF8 support if not yet enabled. UTF8 support if not yet enabled.
@@ -990,7 +1006,6 @@ older history logs (stripped from CVS):
revision 1.16 revision 1.16
date: 2000/08/03 16:54:58; author: jens; state: Exp; lines: +4 -1 date: 2000/08/03 16:54:58; author: jens; state: Exp; lines: +4 -1
An jedes File eine Sektion
# Local Variables: *** # Local Variables: ***
# perl-master-file: ../../webmin/index.pl *** # perl-master-file: ../../webmin/index.pl ***
# End: *** # End: ***

View File

@@ -32,7 +32,7 @@ use Carp::Heavy;
use Carp; use Carp;
use Exporter; use Exporter;
$Config::General::VERSION = "2.61"; $Config::General::VERSION = "2.62";
use vars qw(@ISA @EXPORT_OK); use vars qw(@ISA @EXPORT_OK);
use base qw(Exporter); use base qw(Exporter);
@@ -95,7 +95,9 @@ sub new {
NormalizeBlock => 0, NormalizeBlock => 0,
NormalizeOption => 0, NormalizeOption => 0,
NormalizeValue => 0, NormalizeValue => 0,
Plug => {} Plug => {},
UseApacheIfDefine => 0,
Define => {}
}; };
# create the class instance # create the class instance
@@ -234,7 +236,6 @@ sub _blessvars {
# pre-compile the variable regexp # pre-compile the variable regexp
$self->{regex} = $self->_set_regex(); $self->{regex} = $self->_set_regex();
} }
# return $self;
} }
@@ -304,7 +305,6 @@ sub _prepare {
# handle options which contains values we need (strings, hashrefs or the like) # handle options which contains values we need (strings, hashrefs or the like)
if (exists $conf{-String} ) { if (exists $conf{-String} ) {
#if (ref(\$conf{-String}) eq 'SCALAR') {
if (not ref $conf{-String}) { if (not ref $conf{-String}) {
if ( $conf{-String}) { if ( $conf{-String}) {
$self->{StringContent} = $conf{-String}; $self->{StringContent} = $conf{-String};
@@ -386,6 +386,33 @@ sub _prepare {
$self->{SlashIsDirectory} = 1; $self->{SlashIsDirectory} = 1;
$self->{SplitPolicy} = 'whitespace'; $self->{SplitPolicy} = 'whitespace';
$self->{CComments} = 0; $self->{CComments} = 0;
$self->{UseApacheIfDefine} = 1;
}
if ($self->{UseApacheIfDefine}) {
if (exists $conf{-Define}) {
my $ref = ref($conf{-Define});
if ($ref eq '') {
$self->{Define} = {$conf{-Define} => 1};
}
elsif ($ref eq 'SCALAR') {
$self->{Define} = {${$conf{-Define}} = 1};
}
elsif ($ref eq 'ARRAY') {
my %h = map { $_ => 1 } @{$conf{-Define}};
$self->{Define} = \%h;
}
elsif ($ref eq 'HASH') {
$self->{Define} = $conf{-Define};
}
else {
croak qq{Config::General: Unsupported ref '$ref' for 'Define'};
}
delete $conf{-Define};
}
} }
} }
@@ -443,10 +470,6 @@ sub _open {
} }
} }
if (@include == 1) {
$configfile = $include[0];
}
else {
# Multiple results or no expansion results (which is fine, # Multiple results or no expansion results (which is fine,
# include foo/* shouldn't fail if there isn't anything matching) # include foo/* shouldn't fail if there isn't anything matching)
# rt.cpan.org#79869: local $this->{IncludeGlob}; # rt.cpan.org#79869: local $this->{IncludeGlob};
@@ -455,7 +478,6 @@ sub _open {
} }
return; return;
} }
}
if (!-e $configfile) { if (!-e $configfile) {
my $found; my $found;
@@ -576,6 +598,10 @@ sub _read {
($cont, $fh, @stuff) = $this->_hook('pre_read', $fh, @stuff); ($cont, $fh, @stuff) = $this->_hook('pre_read', $fh, @stuff);
return if(!$cont); return if(!$cont);
if ($this->{UseApacheIfDefine}) {
$this->_process_apache_ifdefine(\@stuff);
}
foreach (@stuff) { foreach (@stuff) {
if ($this->{AutoLaunder}) { if ($this->{AutoLaunder}) {
if (m/^(.*)$/) { if (m/^(.*)$/) {
@@ -642,8 +668,6 @@ sub _read {
# Remove comments and empty lines # Remove comments and empty lines
s/(?<!\\)#.*$//; # .+ => .* bugfix rt.cpan.org#44600 s/(?<!\\)#.*$//; # .+ => .* bugfix rt.cpan.org#44600
next if /^\s*#/; next if /^\s*#/;
#next if /^\s*$/;
# look for multiline option, indicated by a trailing backslash # look for multiline option, indicated by a trailing backslash
if (/(?<!\\)\\$/) { if (/(?<!\\)\\$/) {
@@ -789,7 +813,44 @@ sub _read {
} }
sub _process_apache_ifdefine {
#
# Loop trough config lines and exclude all those entries
# for which there's no IFDEF but which reside inside an IFDEF.
#
# Called from _read(), if UseApacheIfDefine is enabled, returns
# the modified array.
my($this, $rawlines) = @_;
my @filtered;
my $includeFlag = 1;
my $blockLevel = 0;
foreach (@{$rawlines}) {
if (/^<\s*IfDefine\s+([!]*)("[^"]+"|\S+)\s*>/i) {
# new IFDEF block, mark following content to be included if
# the DEF is known, otherwise skip it til end of IFDEF
my ($negate, $define) = ($1 eq '!',$2);
$blockLevel++;
$includeFlag &= ((not $negate) & (exists $this->{Define}{$define}));
} elsif (/^<\s*\/IfDefine\s*>/i) {
$blockLevel--;
$includeFlag = $blockLevel == 0;
} elsif ($includeFlag && /\s*Define\s+("[^"]+"|\S+)/i) {
# inline Define, add it to our list
$this->{Define}{$1} = 1;
} elsif ($includeFlag) {
push @filtered, $_;
}
}
if ($blockLevel) {
croak qq(Config::General: Block <IfDefine> has no EndBlock statement!\n);
}
@$rawlines = @filtered; # replace caller array
}
sub _parse { sub _parse {
@@ -805,7 +866,6 @@ sub _parse {
$chunk++; $chunk++;
$_ =~ s/^\s+//; # strip spaces @ end and begin $_ =~ s/^\s+//; # strip spaces @ end and begin
$_ =~ s/\s+$//; $_ =~ s/\s+$//;
###### bad $_ =~ s/^\x{ef}\x{bb}\x{bf}//; # strip utf BOM, if any, fix rt.cpan.org#113671
# #
# build option value assignment, split current input # build option value assignment, split current input
@@ -1168,21 +1228,6 @@ sub _hook {
sub NoMultiOptions {
#
# turn AllowMultiOptions off, still exists for backward compatibility.
# Since we do parsing from within new(), we must
# call it again if one turns NoMultiOptions on!
#
croak q(Config::General: The NoMultiOptions() method is deprecated. Set 'AllowMultiOptions' to 'no' instead!);
}
sub save { sub save {
# #
# this is the old version of save() whose API interface # this is the old version of save() whose API interface
@@ -1432,7 +1477,6 @@ sub _hashref {
} }
# #
# Procedural interface # Procedural interface
# #
@@ -1493,7 +1537,6 @@ __END__
=head1 NAME =head1 NAME
Config::General - Generic Config Module Config::General - Generic Config Module
@@ -1965,6 +2008,35 @@ Please note that this is a new option (incorporated in version 2.30),
it may lead to various unexpected side effects or other failures. it may lead to various unexpected side effects or other failures.
You've been warned. You've been warned.
=item B<-UseApacheIfDefine>
Enables support for Apache <IfDefine> ... </IfDefine>. See -Define.
=item B<-Define>
Defines the symbols to be used for conditional configuration files.
Allowed arguments: scalar, scalar ref, array ref or hash ref.
Examples:
-Define => 'TEST'
-Define => \$testOrProduction
-Define => [qw(TEST VERBOSE)]
-Define => {TEST => 1, VERBOSE => 1}
Sample configuration:
<Logging>
<IfDefine TEST>
Level Debug
include test/*.cfg
</IfDef>
<IfDefine !TEST>
Level Notice
include production/*.cfg
</IfDefine>
</Logging>
=item B<-ApacheCompatible> =item B<-ApacheCompatible>
Over the past years a lot of options has been incorporated Over the past years a lot of options has been incorporated
@@ -1986,6 +2058,7 @@ The following options will be set:
SlashIsDirectory = 1 SlashIsDirectory = 1
SplitPolicy = 'whitespace' SplitPolicy = 'whitespace'
CComments = 0 CComments = 0
UseApacheIfDefine = 1
Take a look into the particular documentation sections what Take a look into the particular documentation sections what
those options are doing. those options are doing.
@@ -2199,7 +2272,7 @@ would produce the following hash structure:
$VAR1 = { $VAR1 = {
'dir' => { 'dir' => {
'attributes' => { 'attributes' => {
'owner => "root", 'owner' => "root",
} }
} }
}; };
@@ -2235,6 +2308,7 @@ Options None
</Directory> </Directory>
# you will get: # you will get:
$VAR1 = { $VAR1 = {
'Directory' => { 'Directory' => {
'/usr/frik' => { '/usr/frik' => {
@@ -2312,8 +2386,8 @@ for named blocks.
=head1 IDENTICAL OPTIONS (ARRAYS) =head1 IDENTICAL OPTIONS (ARRAYS)
You may have more than one line of the same option with different values. You may have more than one line of the same option with different values.
Example: Example:
log log1 log log1
log log2 log log2
log log2 log log2
@@ -2328,6 +2402,7 @@ if(ref($allowed) eq "ARRAY") {
else { else {
@ALLOWED = ($allowed); @ALLOWED = ($allowed);
} }
}
The same applies to blocks and named blocks too (they are described in more detail The same applies to blocks and named blocks too (they are described in more detail
below). For example, if you have the following config: below). For example, if you have the following config:
@@ -2363,6 +2438,7 @@ both identical blocks, then you need to turn the B<new()> parameter B<-MergeDupl
on (see above). The parsed structure of the example above would then look like on (see above). The parsed structure of the example above would then look like
this: this:
$VAR1 = { $VAR1 = {
'dir' => { 'dir' => {
'blah' => { 'blah' => {
@@ -2484,6 +2560,7 @@ my $conf = Config::General(
); );
/etc/crypt.d/server.cfg: /etc/crypt.d/server.cfg:
<<include acl.cfg>> <<include acl.cfg>>
In this example Config::General will try to include I<acl.cfg> from I</etc/crypt.d>: In this example Config::General will try to include I<acl.cfg> from I</etc/crypt.d>:
@@ -2578,8 +2655,7 @@ print "_open() tries $file ... ";
if ($file =~ /blah/) { if ($file =~ /blah/) {
print "ignored\n"; print "ignored\n";
return (0); return (0);
} } else {
else {
print "allowed\n"; print "allowed\n";
return (1, @_); return (1, @_);
} }
@@ -2789,7 +2865,7 @@ Thomas Linden <tlinden |AT| cpan.org>
=head1 VERSION =head1 VERSION
2.61 2.62
=cut =cut

View File

@@ -53,3 +53,4 @@ t/Tie/README
t/cfg.51 t/cfg.51
t/utf8_bom/bar.cfg t/utf8_bom/bar.cfg
t/utf8_bom/foo.cfg t/utf8_bom/foo.cfg
t/cfg.58

2
README
View File

@@ -104,4 +104,4 @@ AUTHOR
VERSION VERSION
2.59 2.62

5
TODO
View File

@@ -1,5 +0,0 @@
o need separate methods like ::String or ::File to fill
module parameters, and ::Parse and/or ::Read for manually
invocation of the parser

3
t/cfg.58 Normal file
View File

@@ -0,0 +1,3 @@
<IFDefine TEST>
level debug
</IFDefine>

19
t/run.t
View File

@@ -8,7 +8,7 @@
use Data::Dumper; use Data::Dumper;
use Test::More tests => 75; use Test::More tests => 78;
#use Test::More qw(no_plan); #use Test::More qw(no_plan);
# ahem, we deliver the test code with a local copy of # ahem, we deliver the test code with a local copy of
@@ -774,3 +774,20 @@ for my $bool (0, 1) {
my %hash = $conf->getall; my %hash = $conf->getall;
is_deeply \%hash, $expected57, "-UTF8 => $bool"; is_deeply \%hash, $expected57, "-UTF8 => $bool";
} }
# IFDEF tests
my $cfg58 = "t/cfg.58";
my $expected58 = { level => "debug" };
my %defs = (
scalar => 'TEST',
array => ['TEST'],
hash => {'TEST' => 1}
);
foreach my $def (keys %defs) {
my $conf = Config::General->new(-ConfigFile => $cfg58,
-UseApacheIfDefine => 1,
-Define => $defs{$def});
my %hash = $conf->getall();
is_deeply \%hash, $expected58, "UseApacheIfDefine, -Define => $def";
}