File Coverage

lib/File/ShareDir/ProjectDistDir.pm
Criterion Covered Total %
statement 122 155 78.7
branch 35 62 56.4
condition 4 6 66.6
subroutine 21 24 87.5
pod 2 2 100.0
total 184 249 73.9


line stmt bran cond sub pod time code
1 15     15   428360 use 5.006;
  15         40  
  15         446  
2 15     15   53 use strict;
  15         16  
  15         330  
3 15     15   75 use warnings;
  15         17  
  15         877  
4              
5             package File::ShareDir::ProjectDistDir;
6              
7             our $VERSION = '1.000007';
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   6323 use Path::IsDev qw();
  15         138854  
  15         307  
24 15     15   6170 use Path::FindDev qw(find_dev);
  15         8189  
  15         64  
25 15     15   2404 use Sub::Exporter qw(build_exporter);
  15         19  
  15         43  
26 15     15   8361 use File::ShareDir qw();
  15         61058  
  15         1102  
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     34   2101 sub _debug($) { }
42             ## use critic
43              
44             if ( $ENV{$env_key} ) {
45             ## no critic (ProtectPrivateVars,TestingAndDebugging::ProhibitNoWarnings)
46 15     15   87 no warnings 'redefine';
  15         19  
  15         15690  
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   5 sub _carp { require Carp; goto &Carp::carp }
  2         293  
57              
58 34     34   240 sub _path { require Path::Tiny; goto &Path::Tiny::path }
  34         138  
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       54 next if eval $code;
67 1         2 my $err = $@;
68 1         13 _carp('Path::Class is not installed.');
69             ## no critic (RequireCarping, ErrorHandling::RequireUseOfExceptions)
70 1         7 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   2743 my ( $class, @args ) = @_;
204              
205 18         47 my ( undef, $xfilename, undef ) = caller;
206              
207 18         49 my $defaults = {
208             filename => $xfilename,
209             projectdir => 'share',
210             pathclass => undef,
211             strict => undef,
212             };
213              
214 18 100       45 if ( not @args ) {
215 6         12 @_ = ( $class, ':all', defaults => $defaults );
216 6         16 goto $exporter;
217             }
218              
219 12         37 for ( 0 .. $#args - 1 ) {
220 29         19 my ( $key, $value );
221 29 100 66     127 next unless $key = $args[$_] and $value = $args[ $_ + 1 ];
222              
223 26 50       52 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         29 for my $setting (qw( projectdir filename distname pathclass pathtiny strict )) {
230 132 100 66     246 if ( $key eq $setting and not ref $value ) {
231 14         18 $defaults->{$setting} = $value;
232 14         23 undef $args[$_];
233 14         13 undef $args[ $_ + 1 ];
234 14         32 last;
235             }
236             }
237             }
238              
239 12 50       27 $defaults->{filename} = $xfilename if not defined $defaults->{filename};
240 12 50       25 $defaults->{projectdir} = 'share' if not defined $defaults->{projectdir};
241              
242 12 100       24 if ( defined $defaults->{pathclass} ) {
243 1         2 _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         12 @_ = ( $class, ( grep { defined } @args ), 'defaults' => $defaults );
  38         56  
248              
249 11         38 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   168 my ( $field, $arg, $col ) = @_;
301 204         126 my $result;
302 204 100       331 $result = $col->{defaults}->{$field} if $col->{defaults}->{$field};
303 204 50       241 $result = $arg->{$field} if $arg->{$field};
304 204         205 return $result;
305             }
306              
307             sub _wrap_return {
308 16     16   23 my ( $type, $value ) = @_;
309 16 50       41 if ( not $type ) {
310 16 50       58 return $value unless ref $value;
311 16         30 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   50 my ( undef, $filename, $projectdir, $distname, $strict ) = @_;
334 17 50       76 if ( defined $DIST_DIR_CACHE{$distname} ) {
335 0         0 return $DIST_DIR_CACHE{$distname};
336             }
337 17         69 _debug( 'Working on: ' . $filename );
338 17         51 my $dev = find_dev( _path($filename)->parent );
339              
340 17 50       743553 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         59 my $devel_share_dir = $dev->child($projectdir);
347              
348 17 100       398 if ($strict) {
349 7         19 $devel_share_dir = $devel_share_dir->child( 'dist', $distname );
350             }
351 17 100       170 if ( -d $devel_share_dir ) {
352 11         248 _debug( 'ISDEV : exists : /' . $devel_share_dir->relative($dev) );
353 11         62 return ( $DIST_DIR_CACHE{$distname} = $devel_share_dir );
354             }
355 6         95 _debug( 'ISPROD: does not exist : /' . $devel_share_dir->relative($dev) );
356             ## no critic (Variables::ProhibitPackageVars)
357 6         19 local $Carp::CarpLevel = $Carp::CarpLevel + 1;
358 6         26 return File::ShareDir::dist_dir($distname);
359             }
360              
361             sub build_dist_dir {
362 17     17 1 2666 my ( $class, undef, $arg, $col ) = @_;
363              
364 17         30 my $projectdir = _get_defaults( projectdir => $arg, $col );
365 17         38 my $pathclass = _get_defaults( pathclass => $arg, $col );
366 17         34 my $pathtiny = _get_defaults( pathtiny => $arg, $col );
367 17         34 my $strict = _get_defaults( strict => $arg, $col );
368 17         24 my $filename = _get_defaults( filename => $arg, $col );
369              
370 17         17 my $wrap_return_type;
371              
372 17 50       38 if ($pathclass) { $wrap_return_type = 'pathclassdir' }
  0         0  
373 17 50       32 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         62 };
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         17 };
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 232 my ( $class, undef, $arg, $col ) = @_;
439              
440 17         29 my $projectdir = _get_defaults( projectdir => $arg, $col );
441 17         29 my $pathclass = _get_defaults( pathclass => $arg, $col );
442 17         28 my $pathtiny = _get_defaults( pathtiny => $arg, $col );
443              
444 17         26 my $strict = _get_defaults( strict => $arg, $col );
445 17         22 my $filename = _get_defaults( filename => $arg, $col );
446              
447 17         27 my $distname = _get_defaults( distname => $arg, $col );
448              
449 17         19 my $wrap_return_type;
450              
451 17 50       30 if ($pathclass) { $wrap_return_type = 'pathclassfile' }
  0         0  
452 17 50       32 if ($pathtiny) { $wrap_return_type = 'pathtiny' }
  0         0  
453              
454             my $check_file = sub {
455 17     17   26 my ( $distdir, $wanted_file ) = @_;
456 17         48 my $child = _path($distdir)->child($wanted_file);
457 17 100       485 return unless -e $child;
458 16 50       319 if ( -d $child ) {
459 0         0 return _croak("Found dist_file '$child', but is a dir");
460             }
461 16 50       233 if ( not -r $child ) {
462 0         0 return _croak("File '$child', no read permissions");
463             }
464 16         251 return _wrap_return( $wrap_return_type, $child );
465 17         55 };
466 17 100       37 if ( not $distname ) {
467             return sub {
468 13     13   1641 my ( $udistname, $wanted_file ) = @_;
469 13         114 my $distdir = $class->_get_cached_dist_dir_result( $filename, $projectdir, $udistname, $strict );
470 13         351 return $check_file->( $distdir, $wanted_file );
471 13         49 };
472             }
473             return sub {
474 4     4   1289 my ($wanted_file) = @_;
475 4         38 my $distdir = $class->_get_cached_dist_dir_result( $filename, $projectdir, $distname, $strict );
476 4         165 return $check_file->( $distdir, $wanted_file );
477 4         18 };
478             }
479              
480             1;
481              
482             __END__