Filename | /Users/ether/.perlbrew/libs/36.0@std/lib/perl5/File/ShareDir.pm |
Statements | Executed 294 statements in 4.84ms |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
1 | 1 | 1 | 2.95ms | 3.06ms | BEGIN@131 | File::ShareDir::
28 | 1 | 1 | 889µs | 889µs | CORE:ftdir (opcode) | File::ShareDir::
14 | 1 | 1 | 263µs | 1.63ms | _search_inc_path | File::ShareDir::
14 | 1 | 1 | 188µs | 1.95ms | _dist_dir_new | File::ShareDir::
14 | 2 | 2 | 124µs | 2.22ms | dist_dir | File::ShareDir::
14 | 1 | 1 | 120µs | 120µs | CORE:fteread (opcode) | File::ShareDir::
14 | 1 | 1 | 76µs | 142µs | _DIST | File::ShareDir::
14 | 1 | 1 | 42µs | 42µs | CORE:match (opcode) | File::ShareDir::
1 | 1 | 1 | 29µs | 29µs | BEGIN@120 | File::ShareDir::
1 | 1 | 1 | 14µs | 21µs | BEGIN@411 | File::ShareDir::
1 | 1 | 1 | 7µs | 45µs | BEGIN@125 | File::ShareDir::
1 | 1 | 1 | 6µs | 8µs | BEGIN@121 | File::ShareDir::
1 | 1 | 1 | 6µs | 59µs | BEGIN@124 | File::ShareDir::
1 | 1 | 1 | 6µs | 37µs | BEGIN@126 | File::ShareDir::
1 | 1 | 1 | 4µs | 34µs | BEGIN@122 | File::ShareDir::
1 | 1 | 1 | 3µs | 3µs | BEGIN@128 | File::ShareDir::
1 | 1 | 1 | 2µs | 2µs | BEGIN@129 | File::ShareDir::
1 | 1 | 1 | 1µs | 1µs | BEGIN@130 | File::ShareDir::
0 | 0 | 0 | 0s | 0s | _FILE | File::ShareDir::
0 | 0 | 0 | 0s | 0s | _MODULE | File::ShareDir::
0 | 0 | 0 | 0s | 0s | __ANON__[:464] | File::ShareDir::
0 | 0 | 0 | 0s | 0s | _dist_dir_old | File::ShareDir::
0 | 0 | 0 | 0s | 0s | _dist_file_new | File::ShareDir::
0 | 0 | 0 | 0s | 0s | _dist_file_old | File::ShareDir::
0 | 0 | 0 | 0s | 0s | _module_dir_new | File::ShareDir::
0 | 0 | 0 | 0s | 0s | _module_dir_old | File::ShareDir::
0 | 0 | 0 | 0s | 0s | _module_subdir | File::ShareDir::
0 | 0 | 0 | 0s | 0s | class_file | File::ShareDir::
0 | 0 | 0 | 0s | 0s | dist_file | File::ShareDir::
0 | 0 | 0 | 0s | 0s | module_dir | File::ShareDir::
0 | 0 | 0 | 0s | 0s | module_file | File::ShareDir::
Line | State ments |
Time on line |
Calls | Time in subs |
Code |
---|---|---|---|---|---|
1 | package File::ShareDir; | ||||
2 | |||||
3 | =pod | ||||
4 | |||||
5 | =head1 NAME | ||||
6 | |||||
7 | File::ShareDir - Locate per-dist and per-module shared files | ||||
8 | |||||
9 | =begin html | ||||
10 | |||||
11 | <a href="https://travis-ci.org/perl5-utils/File-ShareDir"><img src="https://travis-ci.org/perl5-utils/File-ShareDir.svg?branch=master" alt="Travis CI"/></a> | ||||
12 | <a href='https://coveralls.io/github/perl5-utils/File-ShareDir?branch=master'><img src='https://coveralls.io/repos/github/perl5-utils/File-ShareDir/badge.svg?branch=master' alt='Coverage Status' /></a> | ||||
13 | <a href="https://saythanks.io/to/rehsack"><img src="https://img.shields.io/badge/Say%20Thanks-!-1EAEDB.svg" alt="Say Thanks" /></a> | ||||
14 | |||||
15 | =end html | ||||
16 | |||||
17 | =head1 SYNOPSIS | ||||
18 | |||||
19 | use File::ShareDir ':ALL'; | ||||
20 | |||||
21 | # Where are distribution-level shared data files kept | ||||
22 | $dir = dist_dir('File-ShareDir'); | ||||
23 | |||||
24 | # Where are module-level shared data files kept | ||||
25 | $dir = module_dir('File::ShareDir'); | ||||
26 | |||||
27 | # Find a specific file in our dist/module shared dir | ||||
28 | $file = dist_file( 'File-ShareDir', 'file/name.txt'); | ||||
29 | $file = module_file('File::ShareDir', 'file/name.txt'); | ||||
30 | |||||
31 | # Like module_file, but search up the inheritance tree | ||||
32 | $file = class_file( 'Foo::Bar', 'file/name.txt' ); | ||||
33 | |||||
34 | =head1 DESCRIPTION | ||||
35 | |||||
36 | The intent of L<File::ShareDir> is to provide a companion to | ||||
37 | L<Class::Inspector> and L<File::HomeDir>, modules that take a | ||||
38 | process that is well-known by advanced Perl developers but gets a | ||||
39 | little tricky, and make it more available to the larger Perl community. | ||||
40 | |||||
41 | Quite often you want or need your Perl module (CPAN or otherwise) | ||||
42 | to have access to a large amount of read-only data that is stored | ||||
43 | on the file-system at run-time. | ||||
44 | |||||
45 | On a linux-like system, this would be in a place such as /usr/share, | ||||
46 | however Perl runs on a wide variety of different systems, and so | ||||
47 | the use of any one location is unreliable. | ||||
48 | |||||
49 | Perl provides a little-known method for doing this, but almost | ||||
50 | nobody is aware that it exists. As a result, module authors often | ||||
51 | go through some very strange ways to make the data available to | ||||
52 | their code. | ||||
53 | |||||
54 | The most common of these is to dump the data out to an enormous | ||||
55 | Perl data structure and save it into the module itself. The | ||||
56 | result are enormous multi-megabyte .pm files that chew up a | ||||
57 | lot of memory needlessly. | ||||
58 | |||||
59 | Another method is to put the data "file" after the __DATA__ compiler | ||||
60 | tag and limit yourself to access as a filehandle. | ||||
61 | |||||
62 | The problem to solve is really quite simple. | ||||
63 | |||||
64 | 1. Write the data files to the system at install time. | ||||
65 | |||||
66 | 2. Know where you put them at run-time. | ||||
67 | |||||
68 | Perl's install system creates an "auto" directory for both | ||||
69 | every distribution and for every module file. | ||||
70 | |||||
71 | These are used by a couple of different auto-loading systems | ||||
72 | to store code fragments generated at install time, and various | ||||
73 | other modules written by the Perl "ancient masters". | ||||
74 | |||||
75 | But the same mechanism is available to any dist or module to | ||||
76 | store any sort of data. | ||||
77 | |||||
78 | =head2 Using Data in your Module | ||||
79 | |||||
80 | C<File::ShareDir> forms one half of a two part solution. | ||||
81 | |||||
82 | Once the files have been installed to the correct directory, | ||||
83 | you can use C<File::ShareDir> to find your files again after | ||||
84 | the installation. | ||||
85 | |||||
86 | For the installation half of the solution, see L<File::ShareDir::Install> | ||||
87 | and its C<install_share> directive. | ||||
88 | |||||
89 | Using L<File::ShareDir::Install> together with L<File::ShareDir> | ||||
90 | allows one to rely on the files in appropriate C<dist_dir()> | ||||
91 | or C<module_dir()> in development phase, too. | ||||
92 | |||||
93 | =head1 FUNCTIONS | ||||
94 | |||||
95 | C<File::ShareDir> provides four functions for locating files and | ||||
96 | directories. | ||||
97 | |||||
98 | For greater maintainability, none of these are exported by default | ||||
99 | and you are expected to name the ones you want at use-time, or provide | ||||
100 | the C<':ALL'> tag. All of the following are equivalent. | ||||
101 | |||||
102 | # Load but don't import, and then call directly | ||||
103 | use File::ShareDir; | ||||
104 | $dir = File::ShareDir::dist_dir('My-Dist'); | ||||
105 | |||||
106 | # Import a single function | ||||
107 | use File::ShareDir 'dist_dir'; | ||||
108 | dist_dir('My-Dist'); | ||||
109 | |||||
110 | # Import all the functions | ||||
111 | use File::ShareDir ':ALL'; | ||||
112 | dist_dir('My-Dist'); | ||||
113 | |||||
114 | All of the functions will check for you that the dir/file actually | ||||
115 | exists, and that you have read permissions, or they will throw an | ||||
116 | exception. | ||||
117 | |||||
118 | =cut | ||||
119 | |||||
120 | 2 | 34µs | 1 | 29µs | # spent 29µs within File::ShareDir::BEGIN@120 which was called:
# once (29µs+0s) by JSON::Schema::Modern::BEGIN@27 at line 120 # spent 29µs making 1 call to File::ShareDir::BEGIN@120 |
121 | 2 | 21µs | 2 | 10µs | # spent 8µs (6+2) within File::ShareDir::BEGIN@121 which was called:
# once (6µs+2µs) by JSON::Schema::Modern::BEGIN@27 at line 121 # spent 8µs making 1 call to File::ShareDir::BEGIN@121
# spent 2µs making 1 call to strict::import |
122 | 2 | 18µs | 2 | 64µs | # spent 34µs (4+30) within File::ShareDir::BEGIN@122 which was called:
# once (4µs+30µs) by JSON::Schema::Modern::BEGIN@27 at line 122 # spent 34µs making 1 call to File::ShareDir::BEGIN@122
# spent 30µs making 1 call to warnings::import |
123 | |||||
124 | 2 | 25µs | 2 | 112µs | # spent 59µs (6+53) within File::ShareDir::BEGIN@124 which was called:
# once (6µs+53µs) by JSON::Schema::Modern::BEGIN@27 at line 124 # spent 59µs making 1 call to File::ShareDir::BEGIN@124
# spent 53µs making 1 call to base::import |
125 | 2 | 34µs | 2 | 83µs | # spent 45µs (7+38) within File::ShareDir::BEGIN@125 which was called:
# once (7µs+38µs) by JSON::Schema::Modern::BEGIN@27 at line 125 # spent 45µs making 1 call to File::ShareDir::BEGIN@125
# spent 38µs making 1 call to constant::import |
126 | 2 | 16µs | 2 | 68µs | # spent 37µs (6+31) within File::ShareDir::BEGIN@126 which was called:
# once (6µs+31µs) by JSON::Schema::Modern::BEGIN@27 at line 126 # spent 37µs making 1 call to File::ShareDir::BEGIN@126
# spent 31µs making 1 call to constant::import |
127 | |||||
128 | 2 | 8µs | 1 | 3µs | # spent 3µs within File::ShareDir::BEGIN@128 which was called:
# once (3µs+0s) by JSON::Schema::Modern::BEGIN@27 at line 128 # spent 3µs making 1 call to File::ShareDir::BEGIN@128 |
129 | 2 | 9µs | 1 | 2µs | # spent 2µs within File::ShareDir::BEGIN@129 which was called:
# once (2µs+0s) by JSON::Schema::Modern::BEGIN@27 at line 129 # spent 2µs making 1 call to File::ShareDir::BEGIN@129 |
130 | 2 | 8µs | 1 | 1µs | # spent 1µs within File::ShareDir::BEGIN@130 which was called:
# once (1µs+0s) by JSON::Schema::Modern::BEGIN@27 at line 130 # spent 1µs making 1 call to File::ShareDir::BEGIN@130 |
131 | 2 | 1.73ms | 1 | 3.06ms | # spent 3.06ms (2.95+112µs) within File::ShareDir::BEGIN@131 which was called:
# once (2.95ms+112µs) by JSON::Schema::Modern::BEGIN@27 at line 131 # spent 3.06ms making 1 call to File::ShareDir::BEGIN@131 |
132 | |||||
133 | our %DIST_SHARE; | ||||
134 | our %MODULE_SHARE; | ||||
135 | |||||
136 | our @CARP_NOT; | ||||
137 | 1 | 1µs | our @EXPORT_OK = qw{ | ||
138 | dist_dir | ||||
139 | dist_file | ||||
140 | module_dir | ||||
141 | module_file | ||||
142 | class_dir | ||||
143 | class_file | ||||
144 | }; | ||||
145 | 1 | 2µs | our %EXPORT_TAGS = ( | ||
146 | ALL => [@EXPORT_OK], | ||||
147 | ); | ||||
148 | 1 | 0s | our $VERSION = '1.118'; | ||
149 | |||||
150 | ##################################################################### | ||||
151 | # Interface Functions | ||||
152 | |||||
153 | =pod | ||||
154 | |||||
155 | =head2 dist_dir | ||||
156 | |||||
157 | # Get a distribution's shared files directory | ||||
158 | my $dir = dist_dir('My-Distribution'); | ||||
159 | |||||
160 | The C<dist_dir> function takes a single parameter of the name of an | ||||
161 | installed (CPAN or otherwise) distribution, and locates the shared | ||||
162 | data directory created at install time for it. | ||||
163 | |||||
164 | Returns the directory path as a string, or dies if it cannot be | ||||
165 | located or is not readable. | ||||
166 | |||||
167 | =cut | ||||
168 | |||||
169 | sub dist_dir | ||||
170 | # spent 2.22ms (124µs+2.09) within File::ShareDir::dist_dir which was called 14 times, avg 158µs/call:
# 8 times (80µs+1.19ms) by JSON::Schema::Modern::_get_or_load_resource at line 811 of JSON/Schema/Modern.pm, avg 158µs/call
# 6 times (44µs+908µs) by JSON::Schema::Modern::Document::OpenAPI::_add_vocab_and_default_schemas at line 204 of JSON/Schema/Modern/Document/OpenAPI.pm, avg 159µs/call | ||||
171 | 14 | 29µs | 14 | 142µs | my $dist = _DIST(shift); # spent 142µs making 14 calls to File::ShareDir::_DIST, avg 10µs/call |
172 | 14 | 2µs | my $dir; | ||
173 | |||||
174 | # Try the new version, then fall back to the legacy version | ||||
175 | 14 | 52µs | 14 | 1.95ms | $dir = _dist_dir_new($dist) || _dist_dir_old($dist); # spent 1.95ms making 14 calls to File::ShareDir::_dist_dir_new, avg 139µs/call |
176 | |||||
177 | 14 | 32µs | return $dir if defined $dir; | ||
178 | |||||
179 | # Ran out of options | ||||
180 | Carp::croak("Failed to find share dir for dist '$dist'"); | ||||
181 | } | ||||
182 | |||||
183 | sub _dist_dir_new | ||||
184 | # spent 1.95ms (188µs+1.76) within File::ShareDir::_dist_dir_new which was called 14 times, avg 139µs/call:
# 14 times (188µs+1.76ms) by File::ShareDir::dist_dir at line 175, avg 139µs/call | ||||
185 | 14 | 4µs | my $dist = shift; | ||
186 | |||||
187 | 14 | 9µs | return $DIST_SHARE{$dist} if exists $DIST_SHARE{$dist}; | ||
188 | |||||
189 | # Create the subpath | ||||
190 | 14 | 225µs | 28 | 149µs | my $path = File::Spec->catdir('auto', 'share', 'dist', $dist); # spent 134µs making 14 calls to File::Spec::Unix::catdir, avg 10µs/call
# spent 15µs making 14 calls to File::Spec::Unix::canonpath, avg 1µs/call |
191 | |||||
192 | # Find the full dir within @INC | ||||
193 | 14 | 46µs | 14 | 1.63ms | return _search_inc_path($path); # spent 1.63ms making 14 calls to File::ShareDir::_search_inc_path, avg 116µs/call |
194 | } | ||||
195 | |||||
196 | sub _dist_dir_old | ||||
197 | { | ||||
198 | my $dist = shift; | ||||
199 | |||||
200 | # Create the subpath | ||||
201 | my $path = File::Spec->catdir('auto', split(/-/, $dist),); | ||||
202 | |||||
203 | # Find the full dir within @INC | ||||
204 | return _search_inc_path($path); | ||||
205 | } | ||||
206 | |||||
207 | =pod | ||||
208 | |||||
209 | =head2 module_dir | ||||
210 | |||||
211 | # Get a module's shared files directory | ||||
212 | my $dir = module_dir('My::Module'); | ||||
213 | |||||
214 | The C<module_dir> function takes a single parameter of the name of an | ||||
215 | installed (CPAN or otherwise) module, and locates the shared data | ||||
216 | directory created at install time for it. | ||||
217 | |||||
218 | In order to find the directory, the module B<must> be loaded when | ||||
219 | calling this function. | ||||
220 | |||||
221 | Returns the directory path as a string, or dies if it cannot be | ||||
222 | located or is not readable. | ||||
223 | |||||
224 | =cut | ||||
225 | |||||
226 | sub module_dir | ||||
227 | { | ||||
228 | my $module = _MODULE(shift); | ||||
229 | |||||
230 | return $MODULE_SHARE{$module} if exists $MODULE_SHARE{$module}; | ||||
231 | |||||
232 | # Try the new version first, then fall back to the legacy version | ||||
233 | return _module_dir_new($module) || _module_dir_old($module); | ||||
234 | } | ||||
235 | |||||
236 | sub _module_dir_new | ||||
237 | { | ||||
238 | my $module = shift; | ||||
239 | |||||
240 | # Create the subpath | ||||
241 | my $path = File::Spec->catdir('auto', 'share', 'module', _module_subdir($module),); | ||||
242 | |||||
243 | # Find the full dir within @INC | ||||
244 | return _search_inc_path($path); | ||||
245 | } | ||||
246 | |||||
247 | sub _module_dir_old | ||||
248 | { | ||||
249 | my $module = shift; | ||||
250 | my $short = Class::Inspector->filename($module); | ||||
251 | my $long = Class::Inspector->loaded_filename($module); | ||||
252 | $short =~ tr{/}{:} if IS_MACOS; | ||||
253 | $short =~ tr{\\} {/} if IS_WIN32; | ||||
254 | $long =~ tr{\\} {/} if IS_WIN32; | ||||
255 | substr($short, -3, 3, ''); | ||||
256 | $long =~ m/^(.*)\Q$short\E\.pm\z/s or Carp::croak("Failed to find base dir"); | ||||
257 | my $dir = File::Spec->catdir("$1", 'auto', $short); | ||||
258 | |||||
259 | -d $dir or Carp::croak("Directory '$dir': No such directory"); | ||||
260 | -r $dir or Carp::croak("Directory '$dir': No read permission"); | ||||
261 | |||||
262 | return $dir; | ||||
263 | } | ||||
264 | |||||
265 | =pod | ||||
266 | |||||
267 | =head2 dist_file | ||||
268 | |||||
269 | # Find a file in our distribution shared dir | ||||
270 | my $dir = dist_file('My-Distribution', 'file/name.txt'); | ||||
271 | |||||
272 | The C<dist_file> function takes two parameters of the distribution name | ||||
273 | and file name, locates the dist directory, and then finds the file within | ||||
274 | it, verifying that the file actually exists, and that it is readable. | ||||
275 | |||||
276 | The filename should be a relative path in the format of your local | ||||
277 | filesystem. It will simply added to the directory using L<File::Spec>'s | ||||
278 | C<catfile> method. | ||||
279 | |||||
280 | Returns the file path as a string, or dies if the file or the dist's | ||||
281 | directory cannot be located, or the file is not readable. | ||||
282 | |||||
283 | =cut | ||||
284 | |||||
285 | sub dist_file | ||||
286 | { | ||||
287 | my $dist = _DIST(shift); | ||||
288 | my $file = _FILE(shift); | ||||
289 | |||||
290 | # Try the new version first, in doubt hand off to the legacy version | ||||
291 | my $path = _dist_file_new($dist, $file) || _dist_file_old($dist, $file); | ||||
292 | $path or Carp::croak("Failed to find shared file '$file' for dist '$dist'"); | ||||
293 | |||||
294 | -f $path or Carp::croak("File '$path': No such file"); | ||||
295 | -r $path or Carp::croak("File '$path': No read permission"); | ||||
296 | |||||
297 | return $path; | ||||
298 | } | ||||
299 | |||||
300 | sub _dist_file_new | ||||
301 | { | ||||
302 | my $dist = shift; | ||||
303 | my $file = shift; | ||||
304 | |||||
305 | # If it exists, what should the path be | ||||
306 | my $dir = _dist_dir_new($dist); | ||||
307 | return undef unless defined $dir; | ||||
308 | my $path = File::Spec->catfile($dir, $file); | ||||
309 | |||||
310 | # Does the file exist | ||||
311 | return undef unless -e $path; | ||||
312 | |||||
313 | return $path; | ||||
314 | } | ||||
315 | |||||
316 | sub _dist_file_old | ||||
317 | { | ||||
318 | my $dist = shift; | ||||
319 | my $file = shift; | ||||
320 | |||||
321 | # If it exists, what should the path be | ||||
322 | my $dir = _dist_dir_old($dist); | ||||
323 | return undef unless defined $dir; | ||||
324 | my $path = File::Spec->catfile($dir, $file); | ||||
325 | |||||
326 | # Does the file exist | ||||
327 | return undef unless -e $path; | ||||
328 | |||||
329 | return $path; | ||||
330 | } | ||||
331 | |||||
332 | =pod | ||||
333 | |||||
334 | =head2 module_file | ||||
335 | |||||
336 | # Find a file in our module shared dir | ||||
337 | my $dir = module_file('My::Module', 'file/name.txt'); | ||||
338 | |||||
339 | The C<module_file> function takes two parameters of the module name | ||||
340 | and file name. It locates the module directory, and then finds the file | ||||
341 | within it, verifying that the file actually exists, and that it is readable. | ||||
342 | |||||
343 | In order to find the directory, the module B<must> be loaded when | ||||
344 | calling this function. | ||||
345 | |||||
346 | The filename should be a relative path in the format of your local | ||||
347 | filesystem. It will simply added to the directory using L<File::Spec>'s | ||||
348 | C<catfile> method. | ||||
349 | |||||
350 | Returns the file path as a string, or dies if the file or the dist's | ||||
351 | directory cannot be located, or the file is not readable. | ||||
352 | |||||
353 | =cut | ||||
354 | |||||
355 | sub module_file | ||||
356 | { | ||||
357 | my $module = _MODULE(shift); | ||||
358 | my $file = _FILE(shift); | ||||
359 | my $dir = module_dir($module); | ||||
360 | my $path = File::Spec->catfile($dir, $file); | ||||
361 | |||||
362 | -e $path or Carp::croak("File '$path' does not exist in module dir"); | ||||
363 | -r $path or Carp::croak("File '$path': No read permission"); | ||||
364 | |||||
365 | return $path; | ||||
366 | } | ||||
367 | |||||
368 | =pod | ||||
369 | |||||
370 | =head2 class_file | ||||
371 | |||||
372 | # Find a file in our module shared dir, or in our parent class | ||||
373 | my $dir = class_file('My::Module', 'file/name.txt'); | ||||
374 | |||||
375 | The C<module_file> function takes two parameters of the module name | ||||
376 | and file name. It locates the module directory, and then finds the file | ||||
377 | within it, verifying that the file actually exists, and that it is readable. | ||||
378 | |||||
379 | In order to find the directory, the module B<must> be loaded when | ||||
380 | calling this function. | ||||
381 | |||||
382 | The filename should be a relative path in the format of your local | ||||
383 | filesystem. It will simply added to the directory using L<File::Spec>'s | ||||
384 | C<catfile> method. | ||||
385 | |||||
386 | If the file is NOT found for that module, C<class_file> will scan up | ||||
387 | the module's @ISA tree, looking for the file in all of the parent | ||||
388 | classes. | ||||
389 | |||||
390 | This allows you to, in effect, "subclass" shared files. | ||||
391 | |||||
392 | Returns the file path as a string, or dies if the file or the dist's | ||||
393 | directory cannot be located, or the file is not readable. | ||||
394 | |||||
395 | =cut | ||||
396 | |||||
397 | sub class_file | ||||
398 | { | ||||
399 | my $module = _MODULE(shift); | ||||
400 | my $file = _FILE(shift); | ||||
401 | |||||
402 | # Get the super path ( not including UNIVERSAL ) | ||||
403 | # Rather than using Class::ISA, we'll use an inlined version | ||||
404 | # that implements the same basic algorithm. | ||||
405 | my @path = (); | ||||
406 | my @queue = ($module); | ||||
407 | my %seen = ($module => 1); | ||||
408 | while (my $cl = shift @queue) | ||||
409 | { | ||||
410 | push @path, $cl; | ||||
411 | 2 | 525µs | 2 | 28µs | # spent 21µs (14+7) within File::ShareDir::BEGIN@411 which was called:
# once (14µs+7µs) by JSON::Schema::Modern::BEGIN@27 at line 411 # spent 21µs making 1 call to File::ShareDir::BEGIN@411
# spent 7µs making 1 call to strict::unimport |
412 | unshift @queue, grep { !$seen{$_}++ } | ||||
413 | map { my $s = $_; $s =~ s/^::/main::/; $s =~ s/\'/::/g; $s } (@{"${cl}::ISA"}); | ||||
414 | } | ||||
415 | |||||
416 | # Search up the path | ||||
417 | foreach my $class (@path) | ||||
418 | { | ||||
419 | my $dir = eval { module_dir($class); }; | ||||
420 | next if $@; | ||||
421 | my $path = File::Spec->catfile($dir, $file); | ||||
422 | -e $path or next; | ||||
423 | -r $path or Carp::croak("File '$file' cannot be read, no read permissions"); | ||||
424 | return $path; | ||||
425 | } | ||||
426 | Carp::croak("File '$file' does not exist in class or parent shared files"); | ||||
427 | } | ||||
428 | |||||
429 | ## no critic (BuiltinFunctions::ProhibitStringyEval) | ||||
430 | 1 | 66µs | 1 | 277µs | if (eval "use List::MoreUtils 0.428; 1;") # spent 277µs making 1 call to Exporter::Tiny::import # spent 583µs executing statements in string eval # includes 2.65ms spent executing 1 call to 1 sub defined therein. |
431 | { | ||||
432 | List::MoreUtils->import("firstres"); | ||||
433 | } | ||||
434 | else | ||||
435 | { | ||||
436 | ## no critic (ErrorHandling::RequireCheckingReturnValueOfEval) | ||||
437 | eval <<'END_OF_BORROWED_CODE'; | ||||
438 | sub firstres (&@) | ||||
439 | { | ||||
440 | my $test = shift; | ||||
441 | foreach (@_) | ||||
442 | { | ||||
443 | my $testval = $test->(); | ||||
444 | $testval and return $testval; | ||||
445 | } | ||||
446 | return undef; | ||||
447 | } | ||||
448 | END_OF_BORROWED_CODE | ||||
449 | } | ||||
450 | |||||
451 | ##################################################################### | ||||
452 | # Support Functions | ||||
453 | |||||
454 | sub _search_inc_path | ||||
455 | # spent 1.63ms (263µs+1.37) within File::ShareDir::_search_inc_path which was called 14 times, avg 116µs/call:
# 14 times (263µs+1.37ms) by File::ShareDir::_dist_dir_new at line 193, avg 116µs/call | ||||
456 | 14 | 15µs | my $path = shift; | ||
457 | |||||
458 | # Find the full dir within @INC | ||||
459 | my $dir = firstres( | ||||
460 | sub { | ||||
461 | 28 | 7µs | my $d; | ||
462 | 28 | 215µs | 84 | 125µs | $d = File::Spec->catdir($_, $path) if defined _STRING($_); # spent 83µs making 28 calls to File::Spec::Unix::catdir, avg 3µs/call
# spent 24µs making 28 calls to Params::Util::_STRING, avg 857ns/call
# spent 18µs making 28 calls to File::Spec::Unix::canonpath, avg 643ns/call |
463 | 28 | 1.05ms | 28 | 889µs | defined $d and -d $d ? $d : 0; # spent 889µs making 28 calls to File::ShareDir::CORE:ftdir, avg 32µs/call |
464 | }, | ||||
465 | @INC | ||||
466 | 14 | 154µs | 14 | 1.25ms | ) or return; # spent 1.25ms making 14 calls to List::MoreUtils::XS::firstres, avg 89µs/call |
467 | |||||
468 | 14 | 159µs | 14 | 120µs | Carp::croak("Found directory '$dir', but no read permissions") unless -r $dir; # spent 120µs making 14 calls to File::ShareDir::CORE:fteread, avg 9µs/call |
469 | |||||
470 | 14 | 71µs | return $dir; | ||
471 | } | ||||
472 | |||||
473 | sub _module_subdir | ||||
474 | { | ||||
475 | my $module = shift; | ||||
476 | $module =~ s/::/-/g; | ||||
477 | return $module; | ||||
478 | } | ||||
479 | |||||
480 | ## no critic (BuiltinFunctions::ProhibitStringyEval) | ||||
481 | 1 | 111µs | 1 | 94µs | if (eval "use Params::Util 1.07; 1;") # spent 94µs making 1 call to Exporter::import # spent 580µs executing statements in string eval # includes 1.33ms spent executing 1 call to 1 sub defined therein. |
482 | { | ||||
483 | Params::Util->import("_CLASS", "_STRING"); | ||||
484 | } | ||||
485 | else | ||||
486 | { | ||||
487 | ## no critic (ErrorHandling::RequireCheckingReturnValueOfEval) | ||||
488 | eval <<'END_OF_BORROWED_CODE'; | ||||
489 | # Inlined from Params::Util pure perl version | ||||
490 | sub _CLASS ($) | ||||
491 | { | ||||
492 | return (defined $_[0] and !ref $_[0] and $_[0] =~ m/^[^\W\d]\w*(?:::\w+)*\z/s) ? $_[0] : undef; | ||||
493 | } | ||||
494 | |||||
495 | sub _STRING ($) | ||||
496 | { | ||||
497 | (defined $_[0] and ! ref $_[0] and length($_[0])) ? $_[0] : undef; | ||||
498 | } | ||||
499 | END_OF_BORROWED_CODE | ||||
500 | } | ||||
501 | |||||
502 | # Maintainer note: The following private functions are used by | ||||
503 | # File::ShareDir::PAR. (It has to or else it would have to copy&fork) | ||||
504 | # So if you significantly change or even remove them, please | ||||
505 | # notify the File::ShareDir::PAR maintainer(s). Thank you! | ||||
506 | |||||
507 | # Matches a valid distribution name | ||||
508 | ### This is a total guess at this point | ||||
509 | sub _DIST ## no critic (Subroutines::RequireArgUnpacking) | ||||
510 | # spent 142µs (76+66) within File::ShareDir::_DIST which was called 14 times, avg 10µs/call:
# 14 times (76µs+66µs) by File::ShareDir::dist_dir at line 171, avg 10µs/call | ||||
511 | 14 | 142µs | 28 | 66µs | defined _STRING($_[0]) and $_[0] =~ /^[a-z0-9+_-]+$/is and return $_[0]; # spent 42µs making 14 calls to File::ShareDir::CORE:match, avg 3µs/call
# spent 24µs making 14 calls to Params::Util::_STRING, avg 2µs/call |
512 | Carp::croak("Not a valid distribution name"); | ||||
513 | } | ||||
514 | |||||
515 | # A valid and loaded module name | ||||
516 | sub _MODULE | ||||
517 | { | ||||
518 | my $module = _CLASS(shift) or Carp::croak("Not a valid module name"); | ||||
519 | Class::Inspector->loaded($module) and return $module; | ||||
520 | Carp::croak("Module '$module' is not loaded"); | ||||
521 | } | ||||
522 | |||||
523 | # A valid file name | ||||
524 | sub _FILE | ||||
525 | { | ||||
526 | my $file = shift; | ||||
527 | _STRING($file) or Carp::croak("Did not pass a file name"); | ||||
528 | File::Spec->file_name_is_absolute($file) and Carp::croak("Cannot use absolute file name '$file'"); | ||||
529 | return $file; | ||||
530 | } | ||||
531 | |||||
532 | 1 | 20µs | 1; | ||
533 | |||||
534 | =pod | ||||
535 | |||||
536 | =head1 EXTENDING | ||||
537 | |||||
538 | =head2 Overriding Directory Resolution | ||||
539 | |||||
540 | C<File::ShareDir> has two convenience hashes for people who have advanced usage | ||||
541 | requirements of C<File::ShareDir> such as using uninstalled C<share> | ||||
542 | directories during development. | ||||
543 | |||||
544 | # | ||||
545 | # Dist-Name => /absolute/path/for/DistName/share/dir | ||||
546 | # | ||||
547 | %File::ShareDir::DIST_SHARE | ||||
548 | |||||
549 | # | ||||
550 | # Module::Name => /absolute/path/for/Module/Name/share/dir | ||||
551 | # | ||||
552 | %File::ShareDir::MODULE_SHARE | ||||
553 | |||||
554 | Setting these values any time before the corresponding calls | ||||
555 | |||||
556 | dist_dir('Dist-Name') | ||||
557 | dist_file('Dist-Name','some/file'); | ||||
558 | |||||
559 | module_dir('Module::Name'); | ||||
560 | module_file('Module::Name','some/file'); | ||||
561 | |||||
562 | Will override the base directory for resolving those calls. | ||||
563 | |||||
564 | An example of where this would be useful is in a test for a module that | ||||
565 | depends on files installed into a share directory, to enable the tests | ||||
566 | to use the development copy without needing to install them first. | ||||
567 | |||||
568 | use File::ShareDir; | ||||
569 | use Cwd qw( getcwd ); | ||||
570 | use File::Spec::Functions qw( rel2abs catdir ); | ||||
571 | |||||
572 | $File::ShareDir::MODULE_SHARE{'Foo::Module'} = rel2abs(catfile(getcwd,'share')); | ||||
573 | |||||
574 | use Foo::Module; | ||||
575 | |||||
576 | # internal calls in Foo::Module to module_file('Foo::Module','bar') now resolves to | ||||
577 | # the source trees share/ directory instead of something in @INC | ||||
578 | |||||
579 | =head1 SUPPORT | ||||
580 | |||||
581 | Bugs should always be submitted via the CPAN request tracker, see below. | ||||
582 | |||||
583 | You can find documentation for this module with the perldoc command. | ||||
584 | |||||
585 | perldoc File::ShareDir | ||||
586 | |||||
587 | You can also look for information at: | ||||
588 | |||||
589 | =over 4 | ||||
590 | |||||
591 | =item * RT: CPAN's request tracker | ||||
592 | |||||
593 | L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=File-ShareDir> | ||||
594 | |||||
595 | =item * AnnoCPAN: Annotated CPAN documentation | ||||
596 | |||||
597 | L<http://annocpan.org/dist/File-ShareDir> | ||||
598 | |||||
599 | =item * CPAN Ratings | ||||
600 | |||||
601 | L<http://cpanratings.perl.org/s/File-ShareDir> | ||||
602 | |||||
603 | =item * CPAN Search | ||||
604 | |||||
605 | L<http://search.cpan.org/dist/File-ShareDir/> | ||||
606 | |||||
607 | =back | ||||
608 | |||||
609 | =head2 Where can I go for other help? | ||||
610 | |||||
611 | If you have a bug report, a patch or a suggestion, please open a new | ||||
612 | report ticket at CPAN (but please check previous reports first in case | ||||
613 | your issue has already been addressed). | ||||
614 | |||||
615 | Report tickets should contain a detailed description of the bug or | ||||
616 | enhancement request and at least an easily verifiable way of | ||||
617 | reproducing the issue or fix. Patches are always welcome, too. | ||||
618 | |||||
619 | =head2 Where can I go for help with a concrete version? | ||||
620 | |||||
621 | Bugs and feature requests are accepted against the latest version | ||||
622 | only. To get patches for earlier versions, you need to get an | ||||
623 | agreement with a developer of your choice - who may or not report the | ||||
624 | issue and a suggested fix upstream (depends on the license you have | ||||
625 | chosen). | ||||
626 | |||||
627 | =head2 Business support and maintenance | ||||
628 | |||||
629 | For business support you can contact the maintainer via his CPAN | ||||
630 | email address. Please keep in mind that business support is neither | ||||
631 | available for free nor are you eligible to receive any support | ||||
632 | based on the license distributed with this package. | ||||
633 | |||||
634 | =head1 AUTHOR | ||||
635 | |||||
636 | Adam Kennedy E<lt>adamk@cpan.orgE<gt> | ||||
637 | |||||
638 | =head2 MAINTAINER | ||||
639 | |||||
640 | Jens Rehsack E<lt>rehsack@cpan.orgE<gt> | ||||
641 | |||||
642 | =head1 SEE ALSO | ||||
643 | |||||
644 | L<File::ShareDir::Install>, | ||||
645 | L<File::ConfigDir>, L<File::HomeDir>, | ||||
646 | L<Module::Install>, L<Module::Install::Share>, | ||||
647 | L<File::ShareDir::PAR>, L<Dist::Zilla::Plugin::ShareDir> | ||||
648 | |||||
649 | =head1 COPYRIGHT | ||||
650 | |||||
651 | Copyright 2005 - 2011 Adam Kennedy, | ||||
652 | Copyright 2014 - 2018 Jens Rehsack. | ||||
653 | |||||
654 | This program is free software; you can redistribute | ||||
655 | it and/or modify it under the same terms as Perl itself. | ||||
656 | |||||
657 | The full text of the license can be found in the | ||||
658 | LICENSE file included with this module. | ||||
659 | |||||
660 | =cut | ||||
# spent 889µs within File::ShareDir::CORE:ftdir which was called 28 times, avg 32µs/call:
# 28 times (889µs+0s) by List::MoreUtils::XS::firstres at line 463, avg 32µs/call | |||||
# spent 120µs within File::ShareDir::CORE:fteread which was called 14 times, avg 9µs/call:
# 14 times (120µs+0s) by File::ShareDir::_search_inc_path at line 468, avg 9µs/call | |||||
# spent 42µs within File::ShareDir::CORE:match which was called 14 times, avg 3µs/call:
# 14 times (42µs+0s) by File::ShareDir::_DIST at line 511, avg 3µs/call |