{
$Config::Yak::VERSION
=
'0.23'
;
}
BEGIN {
$Config::Yak::AUTHORITY
=
'cpan:TEX'
;
}
use
5.010_000;
subtype
'ArrayRefOfStr'
,
as
'ArrayRef[Str]'
;
coerce
'ArrayRefOfStr'
,
from
'Str'
,
via { [
$_
] };
has
'locations'
=> (
'is'
=>
'rw'
,
'isa'
=>
'ArrayRefOfStr'
,
'coerce'
=> 1,
'required'
=> 1,
);
has
'last_ts'
=> (
'is'
=>
'rw'
,
'isa'
=>
'Num'
,
'default'
=> 0,
);
has
'files_read'
=> (
'is'
=>
'rw'
,
'isa'
=>
'ArrayRef[Str]'
,
'default'
=>
sub
{ [] },
);
sub
config {
my
$self
=
shift
;
my
$arg
=
shift
;
if
(
defined
(
$arg
) ) {
return
$self
->data(
$arg
);
}
else
{
return
$self
->data();
}
}
sub
_init_debug {
my
$self
=
shift
;
if
(
$ENV
{
'CONFIG_YAK_DEBUG'
}) {
return
1;
}
return
0;
}
sub
_init_data {
my
$self
=
shift
;
my
@files
= ();
my
@legacy_files
= ();
foreach
my
$loc
( @{
$self
->locations() } ) {
if
( -d
$loc
) {
foreach
my
$file
(
glob
(
$loc
.
'/*.conf'
) ) {
if
(
$self
->_is_legacy_config(
$file
) ) {
push
(
@legacy_files
,
$file
);
}
else
{
push
(
@files
,
$file
);
}
}
if
( -d
$loc
.
'/conf.d'
) {
foreach
my
$file
(
glob
(
$loc
.
'/conf.d/*.conf'
) ) {
if
(
$self
->_is_legacy_config(
$file
) ) {
push
(
@legacy_files
,
$file
);
}
else
{
push
(
@files
,
$file
);
}
}
}
}
elsif
( -e
$loc
) {
if
(
$self
->_is_legacy_config(
$loc
) ) {
push
(
@legacy_files
,
$loc
);
}
else
{
push
(
@files
,
$loc
);
}
}
}
print
'_init_config - glob()ed these files: '
.
join
(
q{:}
,
@files
) .
"\n"
if
$self
->debug();
print
'_init_config - glob()ed these legacy files: '
.
join
(
q{:}
,
@legacy_files
) .
"\n"
if
$self
->debug();
my
$cfg
= {};
$cfg
=
$self
->_load_legacy_config( [
@legacy_files
],
$cfg
);
foreach
my
$file
(
@files
) {
$cfg
=
$self
->_load_config( [
$file
],
$cfg
);
}
return
$cfg
;
}
sub
_is_legacy_config {
my
$self
=
shift
;
my
$file
=
shift
;
my
$is_legacy
= 0;
if
( -e
$file
&&
open
(
my
$FH
,
'<'
,
$file
) ) {
my
@lines
= <
$FH
>;
close
(
$FH
);
foreach
my
$line
(
@lines
) {
if
(
$line
=~ m/^\[/ ) {
$is_legacy
= 1;
last
;
}
elsif
(
$line
=~ m/^\s*</ ) {
$is_legacy
= 0;
last
;
}
}
}
return
$is_legacy
;
}
sub
_load_legacy_config {
my
$self
=
shift
;
my
$files_ref
=
shift
;
my
$cfg
=
shift
|| {};
Hash::Merge::set_behavior(
'RETAINMENT_PRECEDENT'
);
foreach
my
$file
( @{
$files_ref
} ) {
if
( -e
$file
) {
try
{
my
$Config
= Config::Tiny::->
read
(
$file
);
print
'_load_legacy_config - Loaded '
.
$file
.
"\n"
if
$self
->debug();
Data::Structure::Util::unbless(
$Config
);
$cfg
= Hash::Merge::merge(
$cfg
,
$Config
);
my
$last_ts
= (
stat
(
$file
) )[9];
$self
->last_ts(
$last_ts
)
if
$last_ts
>
$self
->last_ts();
1;
}
catch
{
warn
"Loading $file failed: $_\n"
if
$self
->debug();
};
}
}
return
$cfg
;
}
sub
_load_config {
my
$self
=
shift
;
my
$files_ref
=
shift
;
my
$ccfg
=
shift
|| {};
no
warnings
'once'
;
if
(!
$self
->debug()) {
open
( OLD_STDERR,
'>&STDERR'
)
or
die
(
'Failed to save STDERR'
);
open
( STDERR,
'>'
,
'/dev/null'
)
or
die
(
'Failed to redirect STDERR'
);
}
my
$cfg
= {};
my
$success
=
try
{
$cfg
= Config::Any->load_files(
{
files
=>
$files_ref
,
use_ext
=> 1,
driver_args
=> {
General
=> {
-UseApacheInclude
=> 0,
-IncludeRelative
=> 0,
-IncludeDirectories
=> 0,
-IncludeGlob
=> 0,
-SplitPolicy
=>
'equalsign'
,
-CComments
=> 0,
-AutoTrue
=> 1,
-MergeDuplicateBlocks
=> 1,
-MergeDuplicateOptions
=> 0,
-LowerCaseNames
=> 1,
-UTF8
=> 1,
},
},
flatten_to_hash
=> 1,
},
);
1;
}
catch
{
print
'Loading '
.
join
(
q{:}
, @{
$files_ref
} ) .
" failed: $_\n"
if
$self
->debug();
};
return
$ccfg
unless
$success
;
if
(!
$self
->debug()) {
open
( STDERR,
'>&OLD_STDERR'
);
}
Hash::Merge::set_behavior(
'RETAINMENT_PRECEDENT'
);
if
(
ref
(
$cfg
) eq
'ARRAY'
) {
my
$ncfg
= {};
foreach
my
$c
( @{
$cfg
} ) {
foreach
my
$file
(
keys
%{
$c
} ) {
$ncfg
->{
$file
} =
$c
->{
$file
};
}
}
$cfg
=
$ncfg
;
}
if
(
ref
(
$cfg
) eq
'HASH'
) {
foreach
my
$file
(
keys
%{
$cfg
} ) {
print
"_load_config - Loaded $file\n"
if
$self
->debug();
push
(@{
$self
->files_read()},
$file
);
$ccfg
= Hash::Merge::merge(
$ccfg
,
$cfg
->{
$file
} );
my
$last_ts
= (
stat
(
$file
) )[9];
$self
->last_ts(
$last_ts
)
if
$last_ts
>
$self
->last_ts();
}
}
return
$ccfg
;
}
sub
add_config {
my
$self
=
shift
;
my
$file
=
shift
;
$self
->config( Hash::Merge::merge(
$self
->config(),
$self
->_load_config( [
$file
] ) ) );
return
1;
}
sub
reset_config {
my
$self
=
shift
;
$self
->config( {} );
return
1;
}
sub
dump
{
my
$self
=
shift
;
$Data::Dumper::Sortkeys
= 1;
return
Dumper(
$self
->config() );
}
no
Moose;
__PACKAGE__->meta->make_immutable;
1;