File Coverage

blib/lib/Config/ENV.pm
Criterion Covered Total %
statement 89 89 100.0
branch 21 22 95.4
condition 9 10 90.0
subroutine 21 21 100.0
pod 8 8 100.0
total 148 150 98.6


line stmt bran cond sub pod time code
1             package Config::ENV;
2              
3 7     7   195522 use strict;
  7         44  
  7         167  
4 7     7   30 use warnings;
  7         10  
  7         144  
5              
6 7     7   23 use Carp;
  7         14  
  7         409  
7 7     7   78 use File::Spec;
  7         16  
  7         443  
8              
9             our $VERSION = '0.19';
10              
11             sub import {
12 14     14   82722 my $class = shift;
13 14         29 my $package = caller(0);
14              
15 7     7   60 no strict 'refs';
  7         22  
  7         746  
16 14 100       40 if (__PACKAGE__ eq $class) {
17 9         16 my $name = shift;
18 9         20 my %opts = @_;
19              
20 9         12 push @{"$package\::ISA"}, __PACKAGE__;
  9         89  
21              
22 9         23 for my $method (qw/common config parent load/) {
23 36         49 *{"$package\::$method"} = \&{__PACKAGE__ . "::" . $method}
  36         105  
  36         71  
24             }
25              
26 7     7   40 no warnings 'once';
  7         10  
  7         1202  
27 9         1532 ${"$package\::data"} = +{
28             common => {},
29             envs => {},
30             name => $name,
31             default => $opts{default} || 'default',
32             export => $opts{export},
33 9   100     66 _local => [],
34             };
35             } else {
36 5         11 my %opts = @_;
37 5         12 my $data = _data($class);
38 5 100 100     126 if (my $export = $opts{export} || $data->{export}) {
39 2     4   16 *{"$package\::$export"} = sub { $class };
  2         1128  
  4         25  
40             }
41             }
42             }
43              
44             sub _data {
45 148   66 148   283 my $package = shift || caller(1);
46 7     7   40 no strict 'refs';
  7         11  
  7         190  
47 7     7   31 no warnings 'once';
  7         19  
  7         4031  
48 148         156 ${"$package\::data"};
  148         356  
49             }
50              
51             sub common ($) { ## no critic
52 8     8 1 3468 my ($hash) = @_;
53 8         23 _data->{common} = $hash;
54             }
55              
56             sub config ($$) { ## no critic
57 13     13 1 40 my ($name, $hash) = @_;
58 13         46 _data->{envs}->{$name} = $hash;
59 13         26 undef _data->{_merged}->{$name};
60             }
61              
62             sub load ($) { ## no critic
63 11     11 1 3630 my $filename = shift;
64              
65             # Workaround: convert implied relative path to explicit path for CVE-2016-1238 (. in @INC removal)
66 11         14 my $explicit_filename = $filename;
67 11 100       117 $explicit_filename = File::Spec->catfile('.', $filename) unless File::Spec->file_name_is_absolute($filename);
68 11         1438 my $hash = do "$explicit_filename";
69              
70 11 100       179 croak $@ if $@;
71 10 100       339 croak "$^E" unless defined $hash;
72 8 100       17 unless (ref($hash) eq 'HASH') {
73 1         81 croak "$filename does not return HashRef.";
74             }
75              
76 7 100       34 wantarray ? %$hash : $hash;
77             }
78              
79             sub parent ($) { ## no critic
80 2     2 1 9 my ($name) = @_;
81 2 50       4 %{ _data->{envs}->{$name} || {} };
  2         4  
82             }
83              
84             sub current {
85 36     36 1 54 my ($package) = @_;
86 36         48 my $data = _data($package);
87              
88             my $vals = $data->{_merged}->{$package->env} ||= +{
89 25         53 %{ $data->{common} },
90 25 100       46 %{ $data->{envs}->{$package->env} || {} },
91 36   100     80 (map { %$_ } @{ $data->{_local} }),
  17         82  
  25         110  
92             };
93             }
94              
95             sub param {
96 32     32 1 112 my ($package, $name) = @_;
97 32         70 $package->current->{$name};
98             }
99              
100             sub local {
101 8     8 1 120 my ($package, %hash) = @_;
102 8 100       130 not defined wantarray and croak "local returns guard object; Can't use in void context.";
103              
104 7         12 my $data = _data($package);
105 7         10 push @{ $data->{_local} }, \%hash;
  7         14  
106 7         14 undef $data->{_merged};
107              
108             bless sub {
109 7     7   8 @{ $data->{_local} } = grep { $_ != \%hash } @{ $data->{_local} };
  7         12  
  12         28  
  7         11  
110 7         36 undef $data->{_merged};
111 7         34 }, 'Config::ENV::Local';
112             }
113              
114             sub env {
115 64     64 1 172 my ($package) = @_;
116 64         85 my $data = _data($package);
117 64 100       321 $ENV{$data->{name}} || $data->{default};
118             }
119              
120             {
121             package
122             Config::ENV::Local;
123              
124             sub DESTROY {
125 7     7   1897 my $self = shift;
126 7         17 $self->();
127             }
128             };
129              
130             1;
131             __END__