File Coverage

blib/lib/Dotenv.pm
Criterion Covered Total %
statement 45 45 100.0
branch 22 22 100.0
condition n/a
subroutine 7 7 100.0
pod 2 2 100.0
total 76 76 100.0


line stmt bran cond sub pod time code
1             package Dotenv;
2             $Dotenv::VERSION = '0.002';
3 6     6   372390 use strict;
  6         54  
  6         176  
4 6     6   32 use warnings;
  6         10  
  6         188  
5              
6 6     6   29 use Carp ();
  6         11  
  6         97  
7 6     6   3205 use Path::Tiny ();
  6         51100  
  6         4988  
8              
9             sub import {
10 6     6   59 my ( $package, @args ) = @_;
11 6 100       5657 if (@args) {
12 2         5 my $action = shift @args;
13 2 100       6 if ( $action eq '-load' ) {
14 1         4 $package->load(@args);
15             }
16             else {
17 1         185 Carp::croak "Unknown action $action";
18             }
19             }
20             }
21              
22             my $parse = sub {
23             my ( $string, $env ) = @_;
24             $string =~ s/\A\x{feff}//; # drop BOM
25              
26             my %kv;
27             for my $line ( split /$/m, $string ) {
28             chomp($line);
29             next if $line =~ /\A\s*(?:[#:]|\z)/; # skip blanks and comments
30             if (
31             my ( $k, $v ) =
32             $line =~ m{
33             \A # beginning of line
34             \s* # leading whitespace
35             (?:export\s+)? # optional export
36             ([a-zA-Z_][a-zA-Z0-9_]+) # key
37             (?:\s*=\s*) # separator
38             ( # optional value begin
39             '[^']*(?:\\'|[^']*)*' # single quoted value
40             | # or
41             "[^"]*(?:\\"|[^"]*)*" # double quoted value
42             | # or
43             [^\#\r\n]+ # unquoted value
44             )? # value end
45             \s* # trailing whitespace
46             (?:\#.*)? # optional comment
47             \z # end of line
48             }x
49             )
50             {
51             $v //= '';
52             $v =~ s/\s*\z//;
53              
54             # single and double quotes semantics
55             if ( $v =~ s/\A(['"])(.*)\1\z/$2/ && $1 eq '"' ) {
56             $v =~ s/\\n/\n/g;
57             $v =~ s/\\//g;
58             }
59             $kv{$k} = $v;
60             }
61             else {
62             Carp::croak "Can't parse env line: $line";
63             }
64             }
65             return %kv;
66             };
67              
68             sub parse {
69 24     24 1 27691 my ( $package, @sources ) = @_;
70 24 100       74 @sources = ('.env') if !@sources;
71              
72 24         35 my %env;
73 24         46 for my $source (@sources) {
74 31 100       244 Carp::croak "Can't handle an unitialized value"
75             if !defined $source;
76              
77 30         42 my %kv;
78 30         108 my $ref = ref $source;
79 30 100       124 if ( $ref eq '' ) {
    100          
    100          
    100          
    100          
    100          
80 13         65 %kv = $parse->( Path::Tiny->new($source)->slurp_utf8, \%env );
81             }
82             elsif ( $ref eq 'HASH' ) { # bare hash ref
83 8         91 %kv = %$source;
84             }
85             elsif ( $ref eq 'ARRAY' ) {
86 1         6 %kv = $parse->( join( "\n", @$source ), \%env );
87             }
88             elsif ( $ref eq 'SCALAR' ) {
89 1         11 %kv = $parse->( $$source, \%env );
90             }
91             elsif ( $ref eq 'GLOB' ) {
92 1         4 local $/;
93 1         51 %kv = $parse->( scalar <$source>, \%env );
94 1         29 close $source;
95             }
96 6         60 elsif ( eval { $source->can('getline') } ) {
97 1         4 local $/;
98 1         30 %kv = $parse->( scalar $source->getline, \%env );
99 1         9 $source->close;
100             }
101             else {
102 5         498 Carp::croak "Don't know how to handle '$source'";
103             }
104              
105             # don't overwrite anything that already exists
106 25         393 %env = ( %kv, %env );
107             }
108              
109 18         385 return \%env;
110             }
111              
112             sub load {
113 7     7 1 4466 my ( $package, @sources ) = @_;
114 7 100       22 @sources = ('.env') if !@sources;
115 7         14 %ENV = %{ $package->parse( \%ENV, @sources ) };
  7         19  
116 7         1350 return \%ENV;
117             }
118              
119             '.env';
120              
121             __END__