File Coverage

blib/lib/File/ShareDir/ProjectDistDir.pm
Criterion Covered Total %
statement 120 153 78.4
branch 35 62 56.4
condition 4 6 66.6
subroutine 21 24 87.5
pod 2 2 100.0
total 182 247 73.6


line stmt bran cond sub pod time code
1 15     15   848919 use 5.006;
  15         37  
2 15     15   50 use strict;
  15         17  
  15         247  
3 15     15   55 use warnings;
  15         13  
  15         788  
4              
5             package File::ShareDir::ProjectDistDir;
6              
7             our $VERSION = '1.000009';
8              
9             # ABSTRACT: Simple set-and-forget using of a '/share' directory in your projects root
10              
11             our $AUTHORITY = 'cpan:KENTNL'; # AUTHORITY
12              
13              
14              
15              
16              
17              
18              
19              
20              
21              
22              
23 15     15   5690 use Path::IsDev qw();
  15         144435  
  15         372  
24 15     15   6228 use Path::FindDev qw(find_dev);
  15         8257  
  15         51  
25 15     15   2175 use Sub::Exporter qw(build_exporter);
  15         20  
  15         43  
26 15     15   8201 use File::ShareDir qw();
  15         63403  
  15         1196  
27              
28             my ($exporter) = build_exporter(
29             {
30             exports => [ dist_dir => \&build_dist_dir, dist_file => \&build_dist_file ],
31             groups => {
32             all => [qw( dist_dir dist_file )],
33             'default' => [qw( dist_dir dist_file )],
34             },
35             collectors => [ 'defaults', ],
36             },
37             );
38             my $env_key = 'FILE_SHAREDIR_PROJECTDISTDIR_DEBUG';
39              
40             ## no critic (Subroutines::ProhibitSubroutinePrototypes)
41       34     sub _debug($) { }
42             ## use critic
43              
44             if ( $ENV{$env_key} ) {
45             ## no critic (ProtectPrivateVars,TestingAndDebugging::ProhibitNoWarnings)
46 15     15   90 no warnings 'redefine';
  15         19  
  15         16930  
47             *File::ShareDir::ProjectDistDir::_debug = sub ($) {
48             *STDERR->printf( qq{[ProjectDistDir] %s\n}, $_[0] );
49             };
50             $Path::IsDev::DEBUG = 1;
51             $Path::FindDev::DEBUG = 1;
52             }
53              
54             ## no critic (RequireArgUnpacking)
55 0     0   0 sub _croak { require Carp; goto &Carp::croak }
  0         0  
56 2     2   8 sub _carp { require Carp; goto &Carp::carp }
  2         363  
57              
58 34     34   239 sub _path { require Path::Tiny; goto &Path::Tiny::path }
  34         140  
59              
60             sub _need_pathclass {
61 1     1   2 for my $package ( q[], q[::File], q[::Dir] ) {
62             ## no critic (Variables::RequireInitializationForLocalVars)
63 1         1 local $@ = undef;
64 1         4 my $code = sprintf 'require %s%s;1', 'Path::Class', $package;
65             ## no critic (BuiltinFunctions::ProhibitStringyEval,Lax::ProhibitStringyEval::ExceptForRequire)
66 1 50       67 next if eval $code;
67 1         3 my $err = $@;
68 1         15 _carp('Path::Class is not installed.');
69             ## no critic (RequireCarping, ErrorHandling::RequireUseOfExceptions)
70 1         11 die $err;
71             }
72 0         0 return 1;
73             }
74              
75              
76              
77              
78              
79              
80              
81              
82              
83              
84              
85              
86              
87              
88              
89              
90              
91              
92              
93              
94              
95              
96              
97              
98              
99              
100              
101              
102              
103              
104              
105              
106              
107              
108              
109              
110              
111              
112              
113              
114              
115              
116              
117              
118              
119              
120              
121              
122              
123              
124              
125              
126              
127              
128              
129              
130              
131              
132              
133              
134              
135              
136              
137              
138              
139              
140              
141              
142              
143              
144              
145              
146              
147              
148              
149              
150              
151              
152              
153              
154              
155              
156              
157              
158              
159              
160              
161              
162              
163              
164              
165              
166              
167              
168              
169              
170              
171              
172              
173              
174              
175              
176              
177              
178              
179              
180              
181              
182              
183              
184              
185              
186              
187              
188              
189              
190              
191              
192              
193              
194              
195              
196              
197              
198              
199              
200              
201              
202             sub import {
203 18     18   2579 my ( $class, @args ) = @_;
204              
205 18         51 my ( undef, $xfilename, undef ) = caller;
206              
207 18         52 my $defaults = {
208             filename => $xfilename,
209             projectdir => 'share',
210             pathclass => undef,
211             strict => undef,
212             };
213              
214 18 100       47 if ( not @args ) {
215 6         14 @_ = ( $class, ':all', defaults => $defaults );
216 6         20 goto $exporter;
217             }
218              
219 12         41 for ( 0 .. $#args - 1 ) {
220 29         24 my ( $key, $value );
221 29 100 66     137 next unless $key = $args[$_] and $value = $args[ $_ + 1 ];
222              
223 26 50       45 if ( 'defaults' eq $key ) {
224 0         0 $defaults = $value;
225 0         0 undef $args[$_];
226 0         0 undef $args[ $_ + 1 ];
227 0         0 next;
228             }
229 26         26 for my $setting (qw( projectdir filename distname pathclass pathtiny strict )) {
230 132 100 66     231 if ( $key eq $setting and not ref $value ) {
231 14         19 $defaults->{$setting} = $value;
232 14         18 undef $args[$_];
233 14         18 undef $args[ $_ + 1 ];
234 14         19 last;
235             }
236             }
237             }
238              
239 12 50       34 $defaults->{filename} = $xfilename if not defined $defaults->{filename};
240 12 50       29 $defaults->{projectdir} = 'share' if not defined $defaults->{projectdir};
241              
242 12 100       24 if ( defined $defaults->{pathclass} ) {
243 1         3 _carp( 'Path::Class support depecated and will be removed from a future release.' . ' see Documentation for details' );
244 1         3 _need_pathclass();
245             }
246              
247 11         14 @_ = ( $class, ( grep { defined } @args ), 'defaults' => $defaults );
  38         57  
248              
249 11         39 goto $exporter;
250             }
251              
252              
253              
254              
255              
256              
257              
258              
259              
260              
261              
262              
263              
264              
265              
266              
267              
268              
269              
270              
271              
272              
273              
274              
275              
276              
277              
278              
279              
280              
281              
282              
283              
284              
285              
286              
287              
288              
289              
290              
291              
292              
293              
294              
295              
296              
297              
298              
299             sub _get_defaults {
300 204     204   175 my ( $field, $arg, $col ) = @_;
301 204         128 my $result;
302 204 100       331 $result = $col->{defaults}->{$field} if $col->{defaults}->{$field};
303 204 50       249 $result = $arg->{$field} if $arg->{$field};
304 204         208 return $result;
305             }
306              
307             sub _wrap_return {
308 16     16   35 my ( $type, $value ) = @_;
309 16 50       52 if ( not $type ) {
310 16 50       68 return $value unless ref $value;
311 16         36 return "$value";
312             }
313 0 0       0 if ( 'pathtiny' eq $type ) {
314 0 0       0 return $value if 'Path::Tiny' eq ref $value;
315 0         0 return _path($value);
316             }
317 0 0       0 if ( 'pathclassdir' eq $type ) {
318 0 0       0 return $value if 'Path::Class::Dir' eq ref $value;
319 0         0 _need_pathclass;
320 0         0 return Path::Class::Dir->new("$value");
321             }
322 0 0       0 if ( 'pathclassfile' eq $type ) {
323 0 0       0 return $value if 'Path::Class::File' eq ref $value;
324 0         0 _need_pathclass;
325 0         0 return Path::Class::File->new("$value");
326             }
327 0         0 return _croak("Unknown return type $type");
328             }
329              
330             our %DIST_DIR_CACHE;
331              
332             sub _get_cached_dist_dir_result {
333 17     17   58 my ( undef, $filename, $projectdir, $distname, $strict ) = @_;
334 17 50       82 if ( defined $DIST_DIR_CACHE{$distname} ) {
335 0         0 return $DIST_DIR_CACHE{$distname};
336             }
337 17         83 _debug( 'Working on: ' . $filename );
338 17         55 my $dev = find_dev( _path($filename)->parent );
339              
340 17 50       748580 if ( not defined $dev ) {
341             ## no critic (Variables::ProhibitPackageVars)
342 0         0 local $Carp::CarpLevel = $Carp::CarpLevel + 1;
343 0         0 return File::ShareDir::dist_dir($distname);
344             }
345              
346 17         60 my $devel_share_dir = $dev->child($projectdir);
347              
348 17 100       413 if ($strict) {
349 7         19 $devel_share_dir = $devel_share_dir->child( 'dist', $distname );
350             }
351 17 100       171 if ( -d $devel_share_dir ) {
352 11         265 _debug( 'ISDEV : exists : /' . $devel_share_dir->relative($dev) );
353 11         66 return ( $DIST_DIR_CACHE{$distname} = $devel_share_dir );
354             }
355 6         122 _debug( 'ISPROD: does not exist : /' . $devel_share_dir->relative($dev) );
356             ## no critic (Variables::ProhibitPackageVars)
357 6         21 local $Carp::CarpLevel = $Carp::CarpLevel + 1;
358 6         33 return File::ShareDir::dist_dir($distname);
359             }
360              
361             sub build_dist_dir {
362 17     17 1 2612 my ( $class, undef, $arg, $col ) = @_;
363              
364 17         31 my $projectdir = _get_defaults( projectdir => $arg, $col );
365 17         40 my $pathclass = _get_defaults( pathclass => $arg, $col );
366 17         32 my $pathtiny = _get_defaults( pathtiny => $arg, $col );
367 17         25 my $strict = _get_defaults( strict => $arg, $col );
368 17         28 my $filename = _get_defaults( filename => $arg, $col );
369              
370 17         18 my $wrap_return_type;
371              
372 17 50       32 if ($pathclass) { $wrap_return_type = 'pathclassdir' }
  0         0  
373 17 50       50 if ($pathtiny) { $wrap_return_type = 'pathtiny' }
  0         0  
374              
375 17         23 my $distname = _get_defaults( distname => $arg, $col );
376              
377 17 100       36 if ( not $distname ) {
378             return sub {
379 0     0   0 my ($udistname) = @_;
380 0         0 my $distdir = $class->_get_cached_dist_dir_result( $filename, $projectdir, $udistname, $strict );
381 0         0 return _wrap_return( $wrap_return_type, $distdir );
382 13         72 };
383             }
384             return sub {
385 0     0   0 my $distdir = $class->_get_cached_dist_dir_result( $filename, $projectdir, $distname, $strict );
386 0         0 return _wrap_return( $wrap_return_type, $distdir );
387 4         19 };
388             }
389              
390              
391              
392              
393              
394              
395              
396              
397              
398              
399              
400              
401              
402              
403              
404              
405              
406              
407              
408              
409              
410              
411              
412              
413              
414              
415              
416              
417              
418              
419              
420              
421              
422              
423              
424              
425              
426              
427              
428              
429              
430              
431              
432              
433              
434              
435              
436              
437             sub build_dist_file {
438 17     17 1 271 my ( $class, undef, $arg, $col ) = @_;
439              
440 17         25 my $projectdir = _get_defaults( projectdir => $arg, $col );
441 17         29 my $pathclass = _get_defaults( pathclass => $arg, $col );
442 17         25 my $pathtiny = _get_defaults( pathtiny => $arg, $col );
443              
444 17         33 my $strict = _get_defaults( strict => $arg, $col );
445 17         24 my $filename = _get_defaults( filename => $arg, $col );
446              
447 17         33 my $distname = _get_defaults( distname => $arg, $col );
448              
449 17         17 my $wrap_return_type;
450              
451 17 50       35 if ($pathclass) { $wrap_return_type = 'pathclassfile' }
  0         0  
452 17 50       43 if ($pathtiny) { $wrap_return_type = 'pathtiny' }
  0         0  
453              
454             my $check_file = sub {
455 17     17   35 my ( $distdir, $wanted_file ) = @_;
456 17         61 my $child = _path($distdir)->child($wanted_file);
457 17 100       492 return unless -e $child;
458 16 50       387 if ( -d $child ) {
459 0         0 return _croak("Found dist_file '$child', but is a dir");
460             }
461 16 50       273 if ( not -r $child ) {
462 0         0 return _croak("File '$child', no read permissions");
463             }
464 16         284 return _wrap_return( $wrap_return_type, $child );
465 17         71 };
466 17 100       34 if ( not $distname ) {
467             return sub {
468 13     13   2266 my ( $udistname, $wanted_file ) = @_;
469 13         142 my $distdir = $class->_get_cached_dist_dir_result( $filename, $projectdir, $udistname, $strict );
470 13         414 return $check_file->( $distdir, $wanted_file );
471 13         54 };
472             }
473             return sub {
474 4     4   1459 my ($wanted_file) = @_;
475 4         37 my $distdir = $class->_get_cached_dist_dir_result( $filename, $projectdir, $distname, $strict );
476 4         172 return $check_file->( $distdir, $wanted_file );
477 4         15 };
478             }
479              
480             1;
481              
482             __END__