File Coverage

blib/lib/App/Env/_Util.pm
Criterion Covered Total %
statement 84 84 100.0
branch 32 40 80.0
condition 20 22 90.9
subroutine 23 23 100.0
pod 0 14 0.0
total 159 183 86.8


line stmt bran cond sub pod time code
1             package App::Env::_Util;
2              
3             # ABSTRACT: Utilities
4              
5 29     29   165003 use v5.10;
  29         112  
6 29     29   169 use strict;
  29         48  
  29         1162  
7 29     29   182 use warnings;
  29         51  
  29         2278  
8              
9             our $VERSION = '1.05';
10              
11             # need to distinguish between a non-existent module
12             # and one which has compile errors.
13 29     29   14945 use Module::Find qw( );
  29         57526  
  29         1225  
14 29     29   205 use List::Util 1.33 'any';
  29         581  
  29         2455  
15 29     29   1240 use Params::Validate ();
  29         22300  
  29         22297  
16              
17             #-------------------------------------------------------
18              
19             sub croak {
20 9     9 0 1802146 require Carp;
21 9         2783 goto &Carp::croak;
22             }
23              
24             #-------------------------------------------------------
25              
26             # environment cache
27             my %Cache;
28              
29 96     96 0 657 sub getCacheEntry { return $Cache{ $_[0] }; }
30 45     45 0 395 sub setCacheEntry { $Cache{ $_[0] } = $_[1]; }
31 1     1 0 31 sub deleteCacheEntry { delete $Cache{ $_[0] } }
32 93     93 0 555 sub existsCacheEntry { return exists $Cache{ $_[0] }; }
33 1     1 0 10 sub is_CacheEmpty { keys %Cache == 0 }
34              
35             sub uncache {
36 23     23 0 562 my %opt = Params::Validate::validate(
37             @_,
38             {
39             All => { default => undef, type => Params::Validate::SCALAR },
40             App => { default => undef, type => Params::Validate::SCALAR },
41             Site => { optional => 1, type => Params::Validate::SCALAR },
42             CacheID => { default => undef, type => Params::Validate::SCALAR },
43             } );
44              
45 23 100       186 if ( $opt{All} ) {
    100          
46 1         3 delete $opt{All};
47             croak( "can't specify All option with other options\n" )
48 1 50   2   10 if any { defined } values %opt;
  2         7  
49 1         46 %Cache = ();
50             }
51              
52             elsif ( defined $opt{CacheID} ) {
53 1         3 my $cacheid = delete $opt{CacheID};
54             croak( "can't specify CacheID option with other options\n" )
55 1 50   2   13 if any { defined } values %opt;
  2         6  
56              
57 1         17 delete $Cache{$cacheid};
58             }
59             else {
60             croak( "must specify App or CacheID options\n" )
61 21 50       83 unless defined $opt{App};
62              
63             # don't use normal rules for Site specification as we're trying
64             # to delete a specific one.
65 21 100       61 delete $Cache{ modulename( app_env_site( exists $opt{Site} ? ( $opt{Site} ) : () ), $opt{App} ) };
66             }
67              
68 23         88 return;
69             }
70              
71             #-------------------------------------------------------
72              
73             my %existsModule;
74              
75             sub loadModuleList {
76 43     43 0 202 %existsModule = ();
77              
78 43         200 for my $path ( Module::Find::findallmod( 'App::Env' ) ) {
79             # greedy match picks up full part of path
80 514         162102 my ( $base, $app ) = $path =~ /^(.*)::(.*)/;
81              
82             # store lowercased module
83 514         1503 $existsModule{ $base . q{::} . lc $app } = $path;
84             }
85              
86 43         154 return;
87             }
88              
89             sub existsModule {
90 214     214 0 553 my ( $path ) = @_;
91              
92             # reconstruct path with lowercased application name.
93             # greedy match picks up full part of path
94 214         3069 my ( $base, $app ) = $path =~ /^(.*)::(.*)/;
95 214         587 $path = $base . q{::} . lc $app;
96              
97             # (re)load cache if we can't find the module in the list
98             loadModuleList()
99 214 100       763 unless $existsModule{$path};
100              
101             # really check
102 214         832 return $existsModule{$path};
103             }
104              
105              
106             # allow site specific site definition
107 29         67 use constant APP_ENV_SITE => do {
108 29 100 100     249 if ( !exists $ENV{APP_ENV_SITE} && existsModule( 'App::Env::Site' ) ) {
109 22 0 33     72 eval { require App::Env::Site; 1; } // croak( ref $@ ? $@ : "Error loading App::Env::Site: $@\n" );
  22         10565  
  22         759  
110             }
111              
112             # only use the environment variable if defined and not empty.
113             defined $ENV{APP_ENV_SITE}
114 29 100 100     23669 && length $ENV{APP_ENV_SITE} ? $ENV{APP_ENV_SITE} : undef;
115 29     29   287 };
  29         73  
116              
117             # _App_Env_Site ( [$alt_site] );
118             # if $alt_site is non-empty, return it.
119             # if $alt_site is empty or undefined return ().
120             # otherwise return APP_ENV_SITE
121             sub app_env_site {
122              
123 116 100   116 0 575 @_ || return APP_ENV_SITE;
124              
125 17         30 my $site = shift;
126              
127 17 100 100     93 return () if !defined $site || $site eq q{};
128 14         56 return $site;
129              
130             # App::Env::_Util::croak( "Environment variable APP_ENV_SITE is only obeyed at the time that ${ \__PACKAGE__ } is loaded" )
131             # if ( defined( APP_ENV_SITE ) xor defined $ENV{APP_ENV_SITE} )
132             # || ( defined( APP_ENV_SITE ) && defined $ENV{APP_ENV_SITE} && APP_ENV_SITE ne $ENV{APP_ENV_SITE} );
133             }
134              
135              
136             sub shell_escape {
137 132     132 0 278 my $str = shift;
138              
139             # empty string
140 132 50       217 return q{''} unless length( $str );
141              
142             # otherwise, escape all but the "known" non-magic characters.
143 132         248 $str =~ s{([^\w/.:=\-+%@,])}{\\$1}go;
144              
145 132         455 return $str;
146             }
147              
148             #-------------------------------------------------------
149              
150             sub modulename {
151 208     208 0 444 return join( q{::}, 'App::Env', grep { defined } @_ );
  321         1349  
152             }
153              
154             #-------------------------------------------------------
155              
156             sub exclude_param_check {
157 12 100 100 12 0 313 !ref $_[0]
      100        
158             || 'ARRAY' eq ref $_[0]
159             || 'Regexp' eq ref $_[0]
160             || 'CODE' eq ref $_[0];
161             }
162              
163             #-------------------------------------------------------
164              
165             # construct a module name based upon the current or requested site.
166             # requires the module if found. returns the module name if module is
167             # found, undef if not, die's if require fails
168              
169             sub require_module {
170 95     95 0 6828 my ( $app, %par ) = @_;
171              
172 95   100     654 my $app_opts = $par{app_opts} //= {};
173 95   100     579 my $loop = $par{loop} //= 1;
174              
175 95 50       313 croak( "too many alias loops for $app\n" )
176             if $loop == 10;
177              
178 95 100       419 my @sites = app_env_site( exists $par{site} ? $par{site} : () );
179              
180             # check possible sites, in turn.
181             my ( $module )
182 95         275 = grep { defined } ( map { existsModule( modulename( $_, $app ) ) } @sites ),
  187         481  
  92         300  
183             existsModule( modulename( $app ) );
184              
185 95 100       306 if ( defined $module ) {
186             ## no critic ( ProhibitStringyEval );
187 93 50       9111 eval "require $module"
188             or croak $@;
189              
190             # see if this is an alias
191 93 100       8106 if ( my $alias = $module->can( 'alias' ) ) {
192 6         24 ( $app, my $napp_opts ) = $alias->();
193 6 100       46 @{$app_opts}{ keys %$napp_opts } = @{$napp_opts}{ keys %$napp_opts }
  2         6  
  2         8  
194             if $napp_opts;
195 6         33 return require_module(
196             $app, %par,
197             loop => ++$loop,
198             app_opts => $app_opts,
199             );
200             }
201             }
202              
203             else {
204 2         17 return ( undef );
205             }
206              
207 87         707 return ( $module, $app_opts );
208             }
209              
210             1;
211              
212             #
213             # This file is part of App-Env
214             #
215             # This software is Copyright (c) 2018 by Smithsonian Astrophysical Observatory.
216             #
217             # This is free software, licensed under:
218             #
219             # The GNU General Public License, Version 3, June 2007
220             #
221              
222             __END__