|
NAMEFile::ShareDir::ProjectDistDir - Simple set-and-forget using of a '/share' directory in your projects rootVERSIONversion 1.000008DETERRENTSTOP!. Before using this distribution, some warnings MUST be considered.The primary use-case for this module is targeted at development projects that are NOT intended for "CPAN". As such, using it for "CPAN" is generally a bad idea, and better solutions generally involve the less fragile "Test::File::ShareDir", constraining any magical behavior exclusively to where it is needed: Tests. Why?
For these reason, it is dangerous to rely on this distribution while striving to produce quality code. If this documentation is not sufficient to dissuade you, I must strongly implore you to choose the "strict" mechanism, because that substantially reduces the possibilities with regards to false-positive of potential "dev" directories. I have in mind to find a better mechanism to deliver the same objective, but no solutions are forthcoming at this time. SYNOPSISpackage An::Example::Package; use File::ShareDir::ProjectDistDir; # during development, $dir will be $projectroot/share # but once installed, it will be wherever File::Sharedir thinks it is. my $dir = dist_dir('An-Example') Project layout requirements: $project/ $project/lib/An/Example/Package.pm $project/share/ # files for package 'An-Example' go here. You can use a directory name other than 'share' ( Assuming you make sure when you install that, you specify the different directory there also ) as follows: use File::ShareDir::ProjectDistDir ':all', defaults => { projectdir => 'templates', }; METHODSimportuse File::ShareDir::ProjectDistDir (@args); This uses "Sub::Exporter" to do the heavy lifting, so most usage of this module can be maximized by understanding that first.
Sub::Exporter tricks of note. Make your own sharedir util package Foo::Util; sub import { my ($caller_class, $caller_file, $caller_line ) = caller(); if ( grep { /share/ } @_ ) { require File::ShareDir::ProjectDistDir; File::ShareDir::ProjectDistDir->import( filename => $caller_file, dist_dir => { distname => 'myproject' , -as => 'share' }, dist_dir => { distname => 'otherproject' , -as => 'other_share' , projectdir => 'share2' }, -into => $caller_class, ); } } .... package Foo; use Foo::Util qw( share ); my $dir = share(); my $other_dir => other_share(); build_dist_diruse File::ShareDir::ProjectDirDir ( : all ); # this calls my $coderef = File::ShareDir::ProjectDistDir->build_dist_dir( 'dist_dir' => {}, { defaults => { filename => 'path/to/yourcallingfile.pm', projectdir => 'share' } } ); use File::ShareDir::ProjectDirDir ( qw( :all ), distname => 'example-dist' ); # this calls my $coderef = File::ShareDir::ProjectDistDir->build_dist_dir( 'dist_dir' => {}, { distname => 'example-dist', defaults => { filename => 'path/to/yourcallingfile.pm', projectdir => 'share' } } ); use File::ShareDir::ProjectDirDir dist_dir => { distname => 'example-dist', -as => 'mydistdir' }, dist_dir => { distname => 'other-dist', -as => 'otherdistdir' }; # This calls my $coderef = File::ShareDir::ProjectDistDir->build_dist_dir( 'dist_dir', { distname => 'example-dist' }, { defaults => { filename => 'path/to/yourcallingfile.pm', projectdir => 'share' } }, ); my $othercoderef = File::ShareDir::ProjectDistDir->build_dist_dir( 'dist_dir', { distname => 'other-dist' }, { defaults => { filename => 'path/to/yourcallingfile.pm', projectdir => 'share' } }, ); # And leverages Sub::Exporter to create 2 subs in your package. Generates the exported 'dist_dir' method. In development environments, the generated method will return a path to the development directories 'share' directory. In non-development environments, this simply returns "File::ShareDir::dist_dir". As a result of this, specifying the Distribution name is not required during development ( unless in "strict" mode ), however, it will start to matter once it is installed. This is a potential avenues for bugs if you happen to name it wrong. In "strict" mode, the distribution name is ALWAYS REQUIRED, either at least at "import" or "dist_dir()" time. build_dist_fileuse File::ShareDir::ProjectDirDir ( : all ); # this calls my $coderef = File::ShareDir::ProjectDistDir->build_dist_file( 'dist_file' => {}, { defaults => { filename => 'path/to/yourcallingfile.pm', projectdir => 'share' } } ); use File::ShareDir::ProjectDirDir ( qw( :all ), distname => 'example-dist' ); # this calls my $coderef = File::ShareDir::ProjectDistDir->build_dist_file( 'dist_file' => {}, { distname => 'example-dist', defaults => { filename => 'path/to/yourcallingfile.pm', projectdir => 'share' } } ); use File::ShareDir::ProjectDirDir dist_file => { distname => 'example-dist', -as => 'mydistfile' }, dist_file => { distname => 'other-dist', -as => 'otherdistfile' }; # This calls my $coderef = File::ShareDir::ProjectDistDir->build_dist_file( 'dist_file', { distname => 'example-dist' }, { defaults => { filename => 'path/to/yourcallingfile.pm', projectdir => 'share' } }, ); my $othercoderef = File::ShareDir::ProjectDistDir->build_dist_file( 'dist_file', { distname => 'other-dist' }, { defaults => { filename => 'path/to/yourcallingfile.pm', projectdir => 'share' } }, ); # And leverages Sub::Exporter to create 2 subs in your package. Generates the 'dist_file' method. In development environments, the generated method will return a path to the development directories 'share' directory. In non-development environments, this simply returns "File::ShareDir::dist_file". Caveats as a result of package-name as stated in "build_dist_dir" also apply to this method. SIGNIFICANT CHANGES1.000000Strict Mode.Using Strict Mode use File::ShareDir::ProjectDistDir ':all', strict => 1; use File::ShareDir::ProjectDistDir 'dist_dir' => { strict => 1 }; Why you should use strict mode Starting with 1.000000, there is a parameter "strict" that changes how "sharedir" resolution performs. Without strict: lib/... share/... With strict lib/... share/dist/Dist-Name-Here/... This technique greatly builds resilience to the long standing problem with "develop" vs "install" heuristic ambiguity. Here at least, dist_dir('Dist-Name') Will instead fall back to @INC/auto/share/dist/Dist-Name When share/dist/Dist-Name Does not exist. This means if you have a layout like this: <DEVROOT>/inc/<a local::lib path here> <DEVROOT>/lib/<development files here> Then when "Foo-Bar-Baz" is installed as: <DEVROOT>/inc/lib/Foo/Bar/Baz.pm <DEVROOT>/inc/lib/auto/share/dist/Foo-Bar-Baz Then "Baz.pm" will not see the "DEVROOT" and assume "Hey, this is development" and then proceed to try finding files in "DEVROOT/share" Instead, "DEVROOT" must have "DEVROOT/share/dist/Foo-Bar-Baz" too, otherwise it reverts to "DEVROOT/inc/lib/auto..." "Path::Class" interfaces deprecated and dependency dropped. If you have any dependence on this function, now is the time to get yourself off it. Minimum Changes to stay with "Path::Class" short term. As the dependency has been dropped on "Path::Class", if you have "CPAN" modules relying on "Path::Class" interface, you should now at a very minimum start declaring { requires => "Path::Class" } This will keep your dist working, but will not be future proof against further changes. Staying with "Path::Class" long term. Recommended approach if you want to stay using the "Path::Class" interface: use File::ShareDir::... etc use Path::Class qw( dir file ); my $dir = dir( dist_dir('Dist-Name') ); This should future-proof you against anything File::ShareDir may do in the future. "Versioning Scheme arbitrary converted to float" This change is a superficial one, and should have no bearing on how significant you think this release is. It is a significant release, but the primary reason for the version change is simply to avoid compatibility issues in versions themselves. However, outside that, "x.y.z" semantics are still intended to be semi-meaningful, just with less "." and more 0 ☺ "dev" path determination now deferred to call time instead of "use" This was essentially a required change to make "strict" mode plausible, because strict mode _requires_ the "distname" to be known, even in the development environment. This should not have any user visible effects, but please, if you have any problems, file a bug. "file" component determination wrested from "File::ShareDir". dist_file('foo','bar') Is now simply sugar syntax for path(dist_dir('foo'))->child('bar') This should have no side effects in your code, but please file any bugs you experience. ( return value is still "undef" if the file does not exist, and still "croak"'s if the file is not a file, or unreadable, but these may both be subject to change ) 0.5.0 - Heuristics and Return type changesNew "devdir" heuristicStarting with 0.5.0, instead of using our simple "lib/../share" pattern heuristic, a more advanced heuristic is used from the new "Path::FindDev" and "Path::IsDev". This relies on a more "concrete" marker somewhere at the top of your development tree, and more importantly, checks for the existence of specific files that are not likely to occur outside a project root. "lib" and "share" based heuristics were a little fragile, for a few reasons:
So instead, as of 0.5.0, the heuristic revolves around certain specific files being in the "dev" directory. Which is hopefully a more fault resilient mechanism. New Return Types Starting with 0.5.0, the internals are now based on "Path::Tiny" instead of "Path::Class", and as a result, there may be a few glitches in transition. Also, previously you could get a "Path::Class::*" object back from "dist_dir" and "dist_file" by importing it as such: use File::ShareDir::ProjectDistDir qw( dist_dir dist_file ), defaults => { pathclass => 1 }; Now you can also get "Path::Tiny" objects back, by passing: use File::ShareDir::ProjectDistDir qw( dist_dir dist_file ), defaults => { pathtiny => 1 }; For the time being, you can still get Path::Class objects back, it is deprecated since 1.000000 ( In fact, I may even make 2 specific sub-classes of "PDD" for people who want objects back, as it will make the "API" and the code much cleaner ) AUTHORKent Fredric <kentnl@cpan.org>COPYRIGHT AND LICENSEThis software is copyright (c) 2015 by Kent Fredric <kentnl@cpan.org>.This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.
Visit the GSP FreeBSD Man Page Interface. |