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   196501 use strict;
  7         47  
  7         162  
4 7     7   29 use warnings;
  7         9  
  7         139  
5              
6 7     7   26 use Carp;
  7         18  
  7         432  
7 7     7   39 use File::Spec;
  7         11  
  7         364  
8              
9             our $VERSION = '0.18';
10              
11             sub import {
12 14     14   86768 my $class = shift;
13 14         27 my $package = caller(0);
14              
15 7     7   35 no strict 'refs';
  7         17  
  7         758  
16 14 100       40 if (__PACKAGE__ eq $class) {
17 9         12 my $name = shift;
18 9         20 my %opts = @_;
19              
20 9         12 push @{"$package\::ISA"}, __PACKAGE__;
  9         77  
21              
22 9         18 for my $method (qw/common config parent load/) {
23 36         43 *{"$package\::$method"} = \&{__PACKAGE__ . "::" . $method}
  36         108  
  36         63  
24             }
25              
26 7     7   47 no warnings 'once';
  7         17  
  7         1121  
27 9         1715 ${"$package\::data"} = +{
28             common => {},
29             envs => {},
30             name => $name,
31             default => $opts{default} || 'default',
32             export => $opts{export},
33 9   100     85 _local => [],
34             };
35             } else {
36 5         13 my %opts = @_;
37 5         11 my $data = _data($class);
38 5 100 100     123 if (my $export = $opts{export} || $data->{export}) {
39 2     4   13 *{"$package\::$export"} = sub { $class };
  2         1228  
  4         31  
40             }
41             }
42             }
43              
44             sub _data {
45 148   66 148   338 my $package = shift || caller(1);
46 7     7   40 no strict 'refs';
  7         17  
  7         218  
47 7     7   39 no warnings 'once';
  7         12  
  7         3989  
48 148         149 ${"$package\::data"};
  148         353  
49             }
50              
51             sub common ($) { ## no critic
52 8     8 1 3577 my ($hash) = @_;
53 8         27 _data->{common} = $hash;
54             }
55              
56             sub config ($$) { ## no critic
57 13     13 1 41 my ($name, $hash) = @_;
58 13         22 _data->{envs}->{$name} = $hash;
59 13         22 undef _data->{_merged}->{$name};
60             }
61              
62             sub load ($) { ## no critic
63 11     11 1 3725 my $filename = shift;
64              
65             # Workaround: convert implied relative path to explicit path for CVE-2016-1238 (. in @INC removal)
66 11         18 my $explicit_filename = $filename;
67 11 100       117 $explicit_filename = File::Spec->catfile('.', $filename) unless File::Spec->file_name_is_absolute($filename);
68 11         1307 my $hash = do "$explicit_filename";
69              
70 11 100       181 croak $@ if $@;
71 10 100       364 croak "$^E" unless defined $hash;
72 8 100       17 unless (ref($hash) eq 'HASH') {
73 1         79 croak "$filename does not return HashRef.";
74             }
75              
76 7 100       35 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         2  
82             }
83              
84             sub current {
85 36     36 1 52 my ($package) = @_;
86 36         61 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     86 (map { %$_ } @{ $data->{_local} }),
  17         90  
  25         111  
92             };
93             }
94              
95             sub param {
96 32     32 1 135 my ($package, $name) = @_;
97 32         67 $package->current->{$name};
98             }
99              
100             sub local {
101 8     8 1 132 my ($package, %hash) = @_;
102 8 100       177 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         8 push @{ $data->{_local} }, \%hash;
  7         14  
106 7         15 undef $data->{_merged};
107              
108             bless sub {
109 7     7   11 @{ $data->{_local} } = grep { $_ != \%hash } @{ $data->{_local} };
  7         14  
  12         26  
  7         14  
110 7         35 undef $data->{_merged};
111 7         41 }, 'Config::ENV::Local';
112             }
113              
114             sub env {
115 64     64 1 179 my ($package) = @_;
116 64         85 my $data = _data($package);
117 64 100       328 $ENV{$data->{name}} || $data->{default};
118             }
119              
120             {
121             package
122             Config::ENV::Local;
123              
124             sub DESTROY {
125 7     7   1908 my $self = shift;
126 7         15 $self->();
127             }
128             };
129              
130             1;
131             __END__