File Coverage

blib/lib/Gears/Config.pm
Criterion Covered Total %
statement 73 76 96.0
branch 24 32 75.0
condition 11 14 78.5
subroutine 10 10 100.0
pod 4 4 100.0
total 122 136 89.7


line stmt bran cond sub pod time code
1             package Gears::Config;
2             $Gears::Config::VERSION = '0.101';
3 2     2   199350 use v5.40;
  2         6  
4 2     2   345 use Mooish::Base -standard;
  2         66216  
  2         19  
5              
6 2     2   275615 use Gears::Config::Reader::PerlScript;
  2         3259  
  2         100  
7 2     2   20 use Gears::X::Config;
  2         3  
  2         56  
8 2     2   1178 use Value::Diff;
  2         1911  
  2         2004  
9              
10             has param 'readers' => (
11             isa => ArrayRef [InstanceOf ['Gears::Config::Reader']],
12             default => sub { [Gears::Config::Reader::PerlScript->new] },
13             );
14              
15             has field 'config' => (
16             isa => HashRef,
17             default => sub { {} },
18             );
19              
20 23         36 my sub _merge ($this_conf, $this_diff)
21 23     23   38 {
  23         31  
  23         86  
22 23         85 foreach my $key (sort keys $this_diff->%*) {
23 33         93 my $value = $this_diff->{$key};
24 33         63 my $ref = ref $value;
25 33         48 my $mode;
26              
27 33 100       124 if ($key =~ /^([+-=])/) {
28 9         28 $mode = $1;
29 9         24 $key = substr $key, 1;
30             }
31              
32             # equal sign allow replacing mismatching types of refs
33 33 100 100     154 if (!exists $this_conf->{$key} || ($mode // '') eq '=') {
    50 100        
    100          
    100          
34 25         107 $this_conf->{$key} = $value;
35             }
36             elsif (ref $this_conf->{$key} ne $ref) {
37 0         0 Gears::X::Config->raise("configuration key type mismatch for $key");
38             }
39              
40             elsif ($ref eq 'HASH') {
41 2 50 66     11 if (!defined $mode || $mode eq '+') {
42 2         10 __SUB__->($this_conf->{$key}, $value);
43             }
44             else {
45 0         0 Gears::X::Config->raise("$mode$key is not supported for this ref type");
46             }
47             }
48              
49             elsif ($ref eq 'ARRAY') {
50 5 100 100     36 if (!defined $mode || $mode eq '+') {
    50 33        
51 3         16 push $this_conf->{$key}->@*, $value->@*;
52             }
53             elsif ($mode eq '-' && diff($this_conf->{$key}, $value, \my $rest)) {
54 2         263 $this_conf->{$key}->@* = $rest->@*;
55             }
56             }
57              
58             else {
59 1 50       4 Gears::X::Config->raise("$mode$key is not supported for this ref type")
60             if defined $mode;
61              
62 1         6 $this_conf->{$key} = $value;
63             }
64             }
65              
66             }
67              
68 21         35 sub merge ($self, $hash)
69 21     21 1 47 {
  21         44  
  21         31  
70 21         95 my $conf = $self->config;
71 21 50       74 if (diff($hash, $conf, \my $diff)) {
72 21         1756 _merge($conf, $diff);
73             }
74             }
75              
76 23         39 sub parse ($self, $source_type, $source)
  23         34  
77 23     23 1 88 {
  23         31  
  23         34  
78 23 100       78 if ($source_type eq 'file') {
    50          
79 4         7 my $config;
80 4         17 foreach my $reader ($self->readers->@*) {
81 4 50       23 next unless $reader->handles($source);
82 4         48 $config = $reader->parse($self, $source);
83 3         7 last;
84             }
85              
86 3 50       9 Gears::X::Config->raise("no reader to handle file: $source")
87             unless defined $config;
88              
89 3         24 return $config;
90             }
91             elsif ($source_type eq 'var') {
92 19         70 return $source;
93             }
94             else {
95 0         0 Gears::X::Config->raise("unknown type of config to add: $source_type");
96             }
97             }
98              
99 22         75 sub add ($self, $source_type, $source)
  22         40  
100 22     22 1 1177 {
  22         66  
  22         38  
101 22         73 $self->merge($self->parse($source_type, $source));
102 21         103 return $self;
103             }
104              
105 9         37 sub get ($self, $path, $default = undef)
  9         17  
106 9     9 1 62 {
  9         16  
  9         15  
107 9         29 my $current = $self->config;
108              
109 9         41 foreach my $part (split /\./, $path) {
110 15 100       60 Gears::X::Config->raise("invalid config path $path at part $part - not a hash")
111             unless ref $current eq 'HASH';
112              
113 13 100       55 return $default unless exists $current->{$part};
114 10         23 $current = $current->{$part};
115             }
116              
117 4         24 return $current;
118             }
119              
120             __END__