File Coverage

lib/File/ShareDir/ProjectDistDir.pm
Criterion Covered Total %
statement 120 153 78.4
branch 37 62 59.6
condition 4 6 66.6
subroutine 21 24 87.5
pod 2 2 100.0
total 184 247 74.4


line stmt bran cond sub pod time code
1 15     15   1226000 use 5.006;
  15         48  
2 15     15   70 use strict;
  15         24  
  15         378  
3 15     15   63 use warnings;
  15         45  
  15         1041  
4              
5             package File::ShareDir::ProjectDistDir;
6              
7             our $VERSION = '1.000008';
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   12057 use Path::IsDev qw();
  15         207632  
  15         482  
24 15     15   10560 use Path::FindDev qw(find_dev);
  15         10496  
  15         66  
25 15     15   3059 use Sub::Exporter qw(build_exporter);
  15         29  
  15         65  
26 15     15   13670 use File::ShareDir qw();
  15         90817  
  15         1695  
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   127 no warnings 'redefine';
  15         21  
  15         24191  
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 1     1   7 sub _carp { require Carp; goto &Carp::carp }
  1         399  
57              
58 34     34   261 sub _path { require Path::Tiny; goto &Path::Tiny::path }
  34         165  
59              
60             sub _need_pathclass {
61 1     1   4 for my $package ( q[], q[::File], q[::Dir] ) {
62             ## no critic (Variables::RequireInitializationForLocalVars)
63 3         7 local $@ = undef;
64 3         13 my $code = sprintf 'require %s%s;1', 'Path::Class', $package;
65             ## no critic (BuiltinFunctions::ProhibitStringyEval,Lax::ProhibitStringyEval::ExceptForRequire)
66 3 50       242 next if eval $code;
67 0         0 my $err = $@;
68 0         0 _carp('Path::Class is not installed.');
69             ## no critic (RequireCarping, ErrorHandling::RequireUseOfExceptions)
70 0         0 die $err;
71             }
72 1         2 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   3769 my ( $class, @args ) = @_;
204              
205 18         56 my ( undef, $xfilename, undef ) = caller;
206              
207 18         66 my $defaults = {
208             filename => $xfilename,
209             projectdir => 'share',
210             pathclass => undef,
211             strict => undef,
212             };
213              
214 18 100       56 if ( not @args ) {
215 6         14 @_ = ( $class, ':all', defaults => $defaults );
216 6         25 goto $exporter;
217             }
218              
219 12         45 for ( 0 .. $#args - 1 ) {
220 29         34 my ( $key, $value );
221 29 100 66     164 next unless $key = $args[$_] and $value = $args[ $_ + 1 ];
222              
223 26 50       55 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         41 for my $setting (qw( projectdir filename distname pathclass pathtiny strict )) {
230 132 100 66     310 if ( $key eq $setting and not ref $value ) {
231 14         26 $defaults->{$setting} = $value;
232 14         22 undef $args[$_];
233 14         20 undef $args[ $_ + 1 ];
234 14         34 last;
235             }
236             }
237             }
238              
239 12 50       36 $defaults->{filename} = $xfilename if not defined $defaults->{filename};
240 12 50       34 $defaults->{projectdir} = 'share' if not defined $defaults->{projectdir};
241              
242 12 100       31 if ( defined $defaults->{pathclass} ) {
243 1         4 _carp( 'Path::Class support depecated and will be removed from a future release.' . ' see Documentation for details' );
244 1         4 _need_pathclass();
245             }
246              
247 12         20 @_ = ( $class, ( grep { defined } @args ), 'defaults' => $defaults );
  41         87  
248              
249 12         57 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 216     216   230 my ( $field, $arg, $col ) = @_;
301 216         172 my $result;
302 216 100       441 $result = $col->{defaults}->{$field} if $col->{defaults}->{$field};
303 216 50       344 $result = $arg->{$field} if $arg->{$field};
304 216         288 return $result;
305             }
306              
307             sub _wrap_return {
308 16     16   35 my ( $type, $value ) = @_;
309 16 50       51 if ( not $type ) {
310 16 50       70 return $value unless ref $value;
311 16         42 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   64 my ( undef, $filename, $projectdir, $distname, $strict ) = @_;
334 17 50       102 if ( defined $DIST_DIR_CACHE{$distname} ) {
335 0         0 return $DIST_DIR_CACHE{$distname};
336             }
337 17         87 _debug( 'Working on: ' . $filename );
338 17         66 my $dev = find_dev( _path($filename)->parent );
339              
340 17 50       3812432 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         72 my $devel_share_dir = $dev->child($projectdir);
347              
348 17 100       485 if ($strict) {
349 7         23 $devel_share_dir = $devel_share_dir->child( 'dist', $distname );
350             }
351 17 100       197 if ( -d $devel_share_dir ) {
352 11         365 _debug( 'ISDEV : exists : <devroot>/' . $devel_share_dir->relative($dev) );
353 11         88 return ( $DIST_DIR_CACHE{$distname} = $devel_share_dir );
354             }
355 6         142 _debug( 'ISPROD: does not exist : <devroot>/' . $devel_share_dir->relative($dev) );
356             ## no critic (Variables::ProhibitPackageVars)
357 6         26 local $Carp::CarpLevel = $Carp::CarpLevel + 1;
358 6         39 return File::ShareDir::dist_dir($distname);
359             }
360              
361             sub build_dist_dir {
362 18     18 1 5608 my ( $class, undef, $arg, $col ) = @_;
363              
364 18         48 my $projectdir = _get_defaults( projectdir => $arg, $col );
365 18         58 my $pathclass = _get_defaults( pathclass => $arg, $col );
366 18         42 my $pathtiny = _get_defaults( pathtiny => $arg, $col );
367 18         32 my $strict = _get_defaults( strict => $arg, $col );
368 18         34 my $filename = _get_defaults( filename => $arg, $col );
369              
370 18         38 my $wrap_return_type;
371              
372 18 100       40 if ($pathclass) { $wrap_return_type = 'pathclassdir' }
  1         2  
373 18 50       42 if ($pathtiny) { $wrap_return_type = 'pathtiny' }
  0         0  
374              
375 18         37 my $distname = _get_defaults( distname => $arg, $col );
376              
377 18 100       49 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 14         197 };
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         33 };
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 18     18 1 378 my ( $class, undef, $arg, $col ) = @_;
439              
440 18         37 my $projectdir = _get_defaults( projectdir => $arg, $col );
441 18         42 my $pathclass = _get_defaults( pathclass => $arg, $col );
442 18         43 my $pathtiny = _get_defaults( pathtiny => $arg, $col );
443              
444 18         43 my $strict = _get_defaults( strict => $arg, $col );
445 18         42 my $filename = _get_defaults( filename => $arg, $col );
446              
447 18         43 my $distname = _get_defaults( distname => $arg, $col );
448              
449 18         82 my $wrap_return_type;
450              
451 18 100       46 if ($pathclass) { $wrap_return_type = 'pathclassfile' }
  1         2  
452 18 50       37 if ($pathtiny) { $wrap_return_type = 'pathtiny' }
  0         0  
453              
454             my $check_file = sub {
455 17     17   38 my ( $distdir, $wanted_file ) = @_;
456 17         70 my $child = _path($distdir)->child($wanted_file);
457 17 100       682 return unless -e $child;
458 16 50       550 if ( -d $child ) {
459 0         0 return _croak("Found dist_file '$child', but is a dir");
460             }
461 16 50       364 if ( not -r $child ) {
462 0         0 return _croak("File '$child', no read permissions");
463             }
464 16         347 return _wrap_return( $wrap_return_type, $child );
465 18         94 };
466 18 100       57 if ( not $distname ) {
467             return sub {
468 13     13   2801 my ( $udistname, $wanted_file ) = @_;
469 13         152 my $distdir = $class->_get_cached_dist_dir_result( $filename, $projectdir, $udistname, $strict );
470 13         531 return $check_file->( $distdir, $wanted_file );
471 14         73 };
472             }
473             return sub {
474 4     4   1954 my ($wanted_file) = @_;
475 4         40 my $distdir = $class->_get_cached_dist_dir_result( $filename, $projectdir, $distname, $strict );
476 4         237 return $check_file->( $distdir, $wanted_file );
477 4         24 };
478             }
479              
480             1;
481              
482             __END__
483              
484             =pod
485              
486             =encoding UTF-8
487              
488             =head1 NAME
489              
490             File::ShareDir::ProjectDistDir - Simple set-and-forget using of a '/share' directory in your projects root
491              
492             =head1 VERSION
493              
494             version 1.000008
495              
496             =head1 DETERRENT
497              
498             B<STOP!>. Before using this distribution, some warnings B<MUST> be considered.
499              
500             The primary use-case for this module is targeted at development projects that are I<NOT> intended for C<CPAN>.
501              
502             As such, using it for C<CPAN> is generally a bad idea, and better solutions generally involve the less fragile L<< C<Test::File::ShareDir>|Test::File::ShareDir >>, constraining any magical
503             behavior exclusively to where it is needed: Tests.
504              
505             Why?
506              
507             =over 4
508              
509             =item * Determining whether or not we are C<dev> during C<runtime> is a perilous heuristic that routinely fails with even slightly unusual file system layouts.
510              
511             =item * Auto-magical changing of behavior at C<runtime> based on the above leads to many surprising and hard to debug problems.
512              
513             =back
514              
515             For these reason, it is dangerous to rely on this distribution while striving to produce quality code.
516              
517             If this documentation is not sufficient to dissuade you, I must B<strongly implore you> to choose the L<< "strict"|/Strict Mode. >> mechanism,
518             because that substantially reduces the possibilities with regards to false-positive of potential C<dev> directories.
519              
520             I have in mind to find a better mechanism to deliver the same objective, but no solutions are forthcoming at this time.
521              
522             =head1 SYNOPSIS
523              
524             package An::Example::Package;
525              
526             use File::ShareDir::ProjectDistDir;
527              
528             # during development, $dir will be $projectroot/share
529             # but once installed, it will be wherever File::Sharedir thinks it is.
530             my $dir = dist_dir('An-Example')
531              
532             Project layout requirements:
533              
534             $project/
535             $project/lib/An/Example/Package.pm
536             $project/share/ # files for package 'An-Example' go here.
537              
538             You can use a directory name other than 'share' ( Assuming you make sure when
539             you install that, you specify the different directory there also ) as follows:
540              
541             use File::ShareDir::ProjectDistDir ':all', defaults => {
542             projectdir => 'templates',
543             };
544              
545             =head1 METHODS
546              
547             =head2 import
548              
549             use File::ShareDir::ProjectDistDir (@args);
550              
551             This uses L<< C<Sub::Exporter>|Sub::Exporter >> to do the heavy lifting, so most usage of this module can be maximized by
552             understanding that first.
553              
554             =over 4
555              
556             =item * B<C<:all>>
557              
558             ->import( ':all' , .... )
559              
560             Import both C<dist_dir> and C<dist_file>
561              
562             =item * B<C<dist_dir>>
563              
564             ->import('dist_dir' , .... )
565              
566             Import the dist_dir method
567              
568             =item * B<C<dist_file>>
569              
570             ->import('dist_file' , .... )
571              
572             Import the dist_file method
573              
574             =item * B<C<projectdir>>
575              
576             ->import( .... , projectdir => 'share' )
577              
578             Specify what the project directory is as a path relative to the base of your distributions source,
579             and this directory will be used as a C<ShareDir> simulation path for the exported methods I<During development>.
580              
581             If not specified, the default value 'share' is used.
582              
583             =item * B<C<filename>>
584              
585             ->import( .... , filename => 'some/path/to/foo.pm' );
586              
587             Generally you don't want to set this, as its worked out by caller() to work out the name of
588             the file its being called from. This file's path is walked up to find the 'lib' element with a sibling
589             of the name of your C<projectdir>.
590              
591             =item * B<C<distname>>
592              
593             ->import( .... , distname => 'somedistname' );
594              
595             Specifying this argument changes the way the functions are emitted at I<installed C<runtime>>, so that instead of
596             taking the standard arguments File::ShareDir does, the specification of the C<distname> in those functions is eliminated.
597              
598             i.e:
599              
600             # without this flag
601             use File::ShareDir::ProjectDistDir qw( :all );
602              
603             my $dir = dist_dir('example');
604             my $file = dist_file('example', 'path/to/file.pm' );
605              
606             # with this flag
607             use File::ShareDir::ProjectDistDir ( qw( :all ), distname => 'example' );
608              
609             my $dir = dist_dir();
610             my $file = dist_file('path/to/file.pm' );
611              
612             =item * B<C<strict>>
613              
614             ->import( ... , strict => 1 );
615              
616             This parameter specifies that all C<dist> C<sharedirs> will occur within the C<projectdir> directory using the following layout:
617              
618             <root>/<projectdir>/dist/<DISTNAME>/
619              
620             As opposed to
621              
622             <root>/<projectdir>
623              
624             This means if Heuristics misfire and accidentally find another distributions C<share> directory, it will not pick up on it
625             unless that C<share> directory also has that layout, and will instead revert to the C<installdir> path in C<@INC>
626              
627             B<This parameter may become the default option in the future>
628              
629             Specifying this parameter also mandates you B<MUST> declare the C<DISTNAME> value in your file somewhere. Doing otherwise is
630             considered insanity anyway.
631              
632             =item * B<C<defaults>>
633              
634             ->import( ... , defaults => {
635             filename => ....,
636             projectdir => ....,
637             });
638              
639             This is mostly an alternative syntax for specifying C<filename> and C<projectdir>,
640             which is mostly used internally, and their corresponding other values are packed into this one.
641              
642             =back
643              
644             =head3 Sub::Exporter tricks of note.
645              
646             =head4 Make your own sharedir util
647              
648             package Foo::Util;
649              
650             sub import {
651             my ($caller_class, $caller_file, $caller_line ) = caller();
652             if ( grep { /share/ } @_ ) {
653             require File::ShareDir::ProjectDistDir;
654             File::ShareDir::ProjectDistDir->import(
655             filename => $caller_file,
656             dist_dir => { distname => 'myproject' , -as => 'share' },
657             dist_dir => { distname => 'otherproject' , -as => 'other_share' , projectdir => 'share2' },
658             -into => $caller_class,
659             );
660             }
661             }
662              
663             ....
664              
665             package Foo;
666             use Foo::Util qw( share );
667              
668             my $dir = share();
669             my $other_dir => other_share();
670              
671             =head2 build_dist_dir
672              
673             use File::ShareDir::ProjectDirDir ( : all );
674              
675             # this calls
676             my $coderef = File::ShareDir::ProjectDistDir->build_dist_dir(
677             'dist_dir' => {},
678             { defaults => { filename => 'path/to/yourcallingfile.pm', projectdir => 'share' } }
679             );
680              
681             use File::ShareDir::ProjectDirDir ( qw( :all ), distname => 'example-dist' );
682              
683             # this calls
684             my $coderef = File::ShareDir::ProjectDistDir->build_dist_dir(
685             'dist_dir' => {},
686             { distname => 'example-dist', defaults => { filename => 'path/to/yourcallingfile.pm', projectdir => 'share' } }
687             );
688              
689             use File::ShareDir::ProjectDirDir
690             dist_dir => { distname => 'example-dist', -as => 'mydistdir' },
691             dist_dir => { distname => 'other-dist', -as => 'otherdistdir' };
692              
693             # This calls
694             my $coderef = File::ShareDir::ProjectDistDir->build_dist_dir(
695             'dist_dir',
696             { distname => 'example-dist' },
697             { defaults => { filename => 'path/to/yourcallingfile.pm', projectdir => 'share' } },
698             );
699             my $othercoderef = File::ShareDir::ProjectDistDir->build_dist_dir(
700             'dist_dir',
701             { distname => 'other-dist' },
702             { defaults => { filename => 'path/to/yourcallingfile.pm', projectdir => 'share' } },
703             );
704              
705             # And leverages Sub::Exporter to create 2 subs in your package.
706              
707             Generates the exported 'dist_dir' method. In development environments, the generated method will return a path to the
708             development directories 'share' directory. In non-development environments, this simply returns C<File::ShareDir::dist_dir>.
709              
710             As a result of this, specifying the Distribution name is not required during development ( unless in C<strict> mode ), however,
711             it will start to matter once it is installed. This is a potential avenues for bugs if you happen to name it wrong.
712              
713             In C<strict> mode, the distribution name is B<ALWAYS REQUIRED>, either at least at C<import> or C<dist_dir()> time.
714              
715             =head2 build_dist_file
716              
717             use File::ShareDir::ProjectDirDir ( : all );
718              
719             # this calls
720             my $coderef = File::ShareDir::ProjectDistDir->build_dist_file(
721             'dist_file' => {},
722             { defaults => { filename => 'path/to/yourcallingfile.pm', projectdir => 'share' } }
723             );
724              
725             use File::ShareDir::ProjectDirDir ( qw( :all ), distname => 'example-dist' );
726              
727             # this calls
728             my $coderef = File::ShareDir::ProjectDistDir->build_dist_file(
729             'dist_file' => {},
730             { distname => 'example-dist', defaults => { filename => 'path/to/yourcallingfile.pm', projectdir => 'share' } }
731             );
732              
733             use File::ShareDir::ProjectDirDir
734             dist_file => { distname => 'example-dist', -as => 'mydistfile' },
735             dist_file => { distname => 'other-dist', -as => 'otherdistfile' };
736              
737             # This calls
738             my $coderef = File::ShareDir::ProjectDistDir->build_dist_file(
739             'dist_file',
740             { distname => 'example-dist' },
741             { defaults => { filename => 'path/to/yourcallingfile.pm', projectdir => 'share' } },
742             );
743             my $othercoderef = File::ShareDir::ProjectDistDir->build_dist_file(
744             'dist_file',
745             { distname => 'other-dist' },
746             { defaults => { filename => 'path/to/yourcallingfile.pm', projectdir => 'share' } },
747             );
748              
749             # And leverages Sub::Exporter to create 2 subs in your package.
750              
751             Generates the 'dist_file' method.
752              
753             In development environments, the generated method will return
754             a path to the development directories 'share' directory. In non-development environments, this simply returns
755             C<File::ShareDir::dist_file>.
756              
757             Caveats as a result of package-name as stated in L</build_dist_dir> also apply to this method.
758              
759             =begin MetaPOD::JSON v1.0.0
760              
761             {
762             "namespace":"File::ShareDir::ProjectDistDir"
763             }
764              
765              
766             =end MetaPOD::JSON
767              
768             =head1 SIGNIFICANT CHANGES
769              
770             =head2 1.000000
771              
772             =head3 Strict Mode.
773              
774             =head4 Using Strict Mode
775              
776             use File::ShareDir::ProjectDistDir ':all', strict => 1;
777             use File::ShareDir::ProjectDistDir 'dist_dir' => { strict => 1 };
778              
779             =head4 Why you should use strict mode
780              
781             Starting with C<1.000000>, there is a parameter C<strict> that changes
782             how C<sharedir> resolution performs.
783              
784             Without strict:
785              
786             lib/...
787             share/...
788              
789             With strict
790              
791             lib/...
792             share/dist/Dist-Name-Here/...
793              
794             This technique greatly builds resilience to the long standing problem
795             with "develop" vs "install" heuristic ambiguity.
796              
797             Here at least,
798              
799             dist_dir('Dist-Name')
800              
801             Will instead fall back to
802              
803             @INC/auto/share/dist/Dist-Name
804              
805             When
806              
807             share/dist/Dist-Name
808              
809             Does not exist.
810              
811             This means if you have a layout like this:
812              
813             <DEVROOT>/inc/<a local::lib path here>
814             <DEVROOT>/lib/<development files here>
815              
816             Then when C<Foo-Bar-Baz> is installed as:
817              
818             <DEVROOT>/inc/lib/Foo/Bar/Baz.pm
819             <DEVROOT>/inc/lib/auto/share/dist/Foo-Bar-Baz
820              
821             Then C<Baz.pm> will not see the C<DEVROOT> and assume "Hey, this is development" and then proceed to try finding files in
822             C<DEVROOT/share>
823              
824             Instead, C<DEVROOT> must have C<DEVROOT/share/dist/Foo-Bar-Baz> too, otherwise it reverts
825             to C<DEVROOT/inc/lib/auto...>
826              
827             =head3 C<Path::Class> interfaces deprecated and dependency dropped.
828              
829             If you have any dependence on this function, now is the time to get yourself off it.
830              
831             =head4 Minimum Changes to stay with C<Path::Class> short term.
832              
833             As the dependency has been dropped on C<Path::Class>, if you have C<CPAN>
834             modules relying on C<Path::Class> interface, you should now at a very minimum
835             start declaring
836              
837             { requires => "Path::Class" }
838              
839             This will keep your dist working, but will not be future proof against further changes.
840              
841             =head4 Staying with C<Path::Class> long term.
842              
843             Recommended approach if you want to stay using the C<Path::Class> interface:
844              
845             use File::ShareDir::... etc
846             use Path::Class qw( dir file );
847              
848             my $dir = dir( dist_dir('Dist-Name') );
849              
850             This should future-proof you against anything File::ShareDir may do in the future.
851              
852             =head3 C<Versioning Scheme arbitrary converted to float>
853              
854             This change is a superficial one, and should have no bearing on how significant you think this release is.
855              
856             It is a significant release, but the primary reason for the version change is simply to avoid compatibility issues in
857             I<versions themselves>.
858              
859             However, outside that, C<x.y.z> semantics are still intended to be semi-meaningful, just with less C<.> and more C<0> ☺
860              
861             =head3 C<dev> path determination now deferred to call time instead of C<use>
862              
863             This was essentially a required change to make C<strict> mode plausible, because strict mode _requires_ the C<distname> to be
864             known, even in the development environment.
865              
866             This should not have any user visible effects, but please, if you have any problems, file a bug.
867              
868             =head3 C<file> component determination wrested from C<File::ShareDir>.
869              
870             dist_file('foo','bar')
871              
872             Is now simply sugar syntax for
873              
874             path(dist_dir('foo'))->child('bar')
875              
876             This should have no side effects in your code, but please file any bugs you experience.
877              
878             ( return value is still C<undef> if the file does not exist, and still C<croak>'s if the file is not a file, or unreadable, but
879             these may both be subject to change )
880              
881             =head2 0.5.0 - Heuristics and Return type changes
882              
883             =head3 New C<devdir> heuristic
884              
885             Starting with 0.5.0, instead of using our simple C<lib/../share> pattern heuristic, a more
886             advanced heuristic is used from the new L<< C<Path::FindDev>|Path::FindDev >> and L<< C<Path::IsDev>|Path::IsDev >>.
887              
888             This relies on a more "concrete" marker somewhere at the top of your development tree, and more importantly, checks for the
889             existence of specific files that are not likely to occur outside a project root.
890              
891             C<lib> and C<share> based heuristics were a little fragile, for a few reasons:
892              
893             =over 4
894              
895             =item * C<lib> can, and does appear all over UNIX file systems, for purposes B<other> than development project roots.
896              
897             For instance, have a look in C</usr/>
898              
899             /usr/bin
900             /usr/lib
901             /usr/share ## UHOH.
902              
903             This would have the very bad side effect of anything installed in C</usr/lib> thinking its "in development".
904              
905             Fortunately, nobody seems to have hit this specific bug, which I suspect is due only to C</usr/lib> being a symbolic link on most
906             x86_64 systems.
907              
908             =item * C<lib> is also reasonably common within C<CPAN> package names.
909              
910             For instance:
911              
912             lib::abs
913              
914             Which means you'll have a hierarchy like:
915              
916             $PREFIX/lib/lib/abs
917              
918             All you need for something to go horribly wrong would be for somebody to install a C<CPAN> module named:
919              
920             share::mystuff
921              
922             Or similar, and instantly, you have:
923              
924             $PREFIX/lib/lib/
925             $PREFIX/lib/share/
926              
927             Which would mean any module calling itself C<lib::*> would be unable to use this module.
928              
929             =back
930              
931             So instead, as of C<0.5.0>, the heuristic revolves around certain specific files being in the C<dev> directory.
932              
933             Which is hopefully a more fault resilient mechanism.
934              
935             =head3 New Return Types
936              
937             Starting with 0.5.0, the internals are now based on L<< C<Path::Tiny>|Path::Tiny >> instead of L<< C<Path::Class>|Path::Class >>,
938             and as a result, there may be a few glitches in transition.
939              
940             Also, previously you could get a C<Path::Class::*> object back from C<dist_dir> and C<dist_file> by importing it as such:
941              
942             use File::ShareDir::ProjectDistDir
943             qw( dist_dir dist_file ),
944             defaults => { pathclass => 1 };
945              
946             Now you can also get C<Path::Tiny> objects back, by passing:
947              
948             use File::ShareDir::ProjectDistDir
949             qw( dist_dir dist_file ),
950             defaults => { pathtiny => 1 };
951              
952             B<< For the time being, you can still get Path::Class objects back, it is deprecated since 1.000000 >>
953              
954             ( In fact, I may even make 2 specific sub-classes of C<PDD> for people who want objects back, as it will make the C<API> and the
955             code much cleaner )
956              
957             =head1 AUTHOR
958              
959             Kent Fredric <kentnl@cpan.org>
960              
961             =head1 COPYRIGHT AND LICENSE
962              
963             This software is copyright (c) 2015 by Kent Fredric <kentnl@cpan.org>.
964              
965             This is free software; you can redistribute it and/or modify it under
966             the same terms as the Perl 5 programming language system itself.
967              
968             =cut