File Coverage

blib/lib/Path/Abstract.pm
Criterion Covered Total %
statement 34 34 100.0
branch 6 8 75.0
condition 4 6 66.6
subroutine 10 10 100.0
pod n/a
total 54 58 93.1


line stmt bran cond sub pod time code
1             package Path::Abstract;
2              
3 5     5   328168 use warnings;
  5         9  
  5         152  
4 5     5   17 use strict;
  5         6  
  5         103  
5              
6             =head1 NAME
7              
8             Path::Abstract - Fast and featureful UNIX-style path manipulation
9              
10             =cut
11              
12 5     5   16 use vars qw/$VERSION $_0_093_warn %_0_093_warning/;
  5         9  
  5         317  
13              
14             $VERSION = '0.094_2';
15              
16             =head1 VERSION
17              
18             Version 0.094_2
19              
20             =head1 SYNOPSIS
21              
22             use Path::Abstract;
23              
24             my $path = Path::Abstract->new( '/apple/banana' )
25              
26             # $parent is '/apple'
27             my $parent = $path->parent
28              
29             # $cherry is '/apple/banana/cherry.txt'
30             my $cherry = $path->child( "cherry.txt" )
31              
32             path( '/a/b/c/' )->list # ( 'a', 'b', 'c' )
33             path( '/a/b/c/' )->split # ( '/a', 'b', 'c/' )
34              
35             path( '/a/b/c/' )->first # a
36             path( '/a/b/c/' )->beginning # /a
37              
38             path( '/a/b/c/' )->last # c
39             path( '/a/b/c/' )->ending # c/
40              
41             path( '/a/b/c/' ).at(0) # a (equivalent to ->first)
42             path( '/a/b/c/' ).at(-1) # c (equivalent to ->last)
43             path( '/a/b/c/' ).at(1) # b
44              
45             $path = path( 'a/b/c' )
46             $path->append( 'd', 'ef/g', 'h' ) # a/b/cd/ef/g/h
47              
48             path( 'a/b/c.html' )->extension # .html
49             path( 'a/b/c' )->extension # ''
50             path( 'a/b/c.tar.gz' )->extension # .gz
51             path( 'a/b/c.tar.gz' )->
52             extension({ match: '*' }) # .tar.gz
53              
54             path( 'a/b/c.html' )->extension( '.txt' ) # a/b/c.txt
55             path( 'a/b/c.html' )->extension( 'zip' ) # a/b/c.zip
56             path( 'a/b/c.html' )->extension( '' ) # a/b/c
57              
58             path( 'a/b/c' )->down( 'd/e' ) # a/b/c/d/e
59             path( 'a/b/c' )->child( 'd/e' ) # a/b/c/d/e (Same as ->down except
60             # returning a new path instead of
61             # modifying the original)
62            
63             path( 'a/b/c' )->up # a/b
64             path( 'a/b/c' )->parent # a/b (Same as ->up except
65             # returning a new path instead of
66             # modifying the original)
67              
68             =head1 DESCRIPTION
69              
70             Path::Abstract is a tool for parsing, interrogating, and modifying a UNIX-style path. The parsing behavior
71             is similar to L, except that trailing slashes are preserved (converted into a single slash).
72              
73             =cut
74              
75             $_0_093_warn = 1;
76              
77 5     5   2226 use Sub::Exporter;
  5         40162  
  5         22  
78             {
79             my $exporter = Sub::Exporter::build_exporter({
80             exports => [ path => sub { sub {
81 123     123   8974 return __PACKAGE__->new(@_)
82             } } ],
83             });
84              
85             sub import {
86 5 50 66 5   57 if (@_ && grep { defined && $_ eq '--no_0_093_warning' } @_) {
  10 100       116  
87 1         2 $_0_093_warn = 0;
88             }
89 5   66     10 @_ = grep { ! defined || $_ !~ m/^--/ } @_;
  10         51  
90 5         13 goto $exporter;
91             };
92             }
93              
94             use overload
95 5         28 '""' => 'get',
96             fallback => 1,
97 5     5   1136 ;
  5         6  
98              
99 5     5   351 use base qw/Path::Abstract::Underload/;
  5         7  
  5         1977  
100              
101 5     5   21 use Carp;
  5         4  
  5         860  
102             sub _0_093_warn {
103 44 50   44   80 if ($_0_093_warn) {
104 44         121 my ($package, $filename, $line, $subroutine) = caller(1);
105 44 100       852 if (! $_0_093_warning{$subroutine}) {
106 4         8 $_0_093_warning{$subroutine} = 1;
107 4         58 $subroutine =~ s///g;
108 4         78 carp "** $subroutine behavior has changed since 0.093\n" .
109             "** To disable this warning: use Path::Abstract qw/--no_0_093_warning/"
110             }
111             }
112             }
113              
114             =head1 Different behavior since 0.093
115              
116             Some methods of Path::Abstract have changed since 0.093 with the goal of having better/more consistent behavior
117              
118             Unfortunately, this MAY result in code that worked with 0.093 and earlier be updated to reflect the new behavior
119              
120             The following has changed:
121              
122             =head2 $path->list
123              
124             The old behavior (kept the leading slash but dropped trailing slash):
125              
126             path('/a/b/c/')->list # ( '/a', 'b', 'c' )
127             path('a/b/c/')->list # ( 'a', 'b', 'c' )
128              
129             The new behavior (neither slash is kept):
130              
131             path('/a/b/c/')->list # ( 'a', 'b', 'c' )
132             path('a/b/c/')->list # ( 'a', 'b', 'c' )
133              
134             In addition, $path->split was an alias for $path->list, but this has changed. Now split
135             WILL keep BOTH leading and trailing slashes (if any):
136              
137             path('/a/b/c/')->split # ( '/a', 'b', 'c/' )
138             path('a/b/c/')->split # ( 'a', 'b', 'c/' )
139             path('a/b/c')->split # ( 'a', 'b', 'c' ) Effectively equivalent to ->list
140              
141             =head2 $path->split
142              
143             See the above note on $path->list
144              
145             =head2 $path->first
146              
147             The old behavior:
148              
149             1. Would return undef for the empty path
150             2. Would include the leading slash (if present)
151             3. Would NOT include the trailing slash (if present)
152            
153             path(undef)->first # undef
154             path('')->first # undef
155             path('/a')->first # /a
156             path('/a/')->first # /a
157             path('a')->first # a
158              
159             The new behavior:
160              
161             1. Always returns at least the empty string
162             2. Never includes any slashes
163              
164             path(undef)->first # ''
165             path('')->first # ''
166             path('/a')->first # a
167             path('/a/')->first # a
168             path('a')->first # a
169              
170             For an alternative to ->first, try ->beginning
171              
172             =head2 $path->last
173              
174             Simlar to ->first
175              
176             The old behavior:
177            
178             1. Would return undef for the empty path
179             2. Would include the leading slash (if present)
180             3. Would NOT include the trailing slash (if present)
181            
182             path(undef)->last # undef
183             path('')->last # undef
184             path('/a')->last # /a
185             path('/a/')->last # /a
186             path('a')->last # a
187             path('a/b')->last # b
188             path('a/b/')->last # b
189              
190             The new behavior:
191              
192             1. Always returns at least the empty string
193             2. Never includes any slashes
194              
195             path(undef)->last # ''
196             path('')->last # ''
197             path('/a')->last # a
198             path('/a/')->last # a
199             path('a')->last # a
200             path('a/b')->last # b
201             path('a/b/')->last # b
202              
203             For an alternative to ->last, try ->ending
204              
205             =head2 $path->is_branch
206              
207             The old behavior:
208            
209             1. The empty patch ('') would not be considered a branch
210            
211             The new behavior:
212            
213             1. The empty patch ('') IS considered a branch
214              
215             =back
216              
217             =head1 METHODS
218              
219             =head2 Path::Abstract->new( )
220              
221             =head2 Path::Abstract->new( , [ , ..., ] )
222              
223             Create a new C object using or by joining each with "/"
224              
225             Returns the new C object
226              
227             =cut
228              
229             =head2 Path::Abstract::path( )
230              
231             =head2 Path::Abstract::path( , [ , ..., ] )
232              
233             Create a new C object using or by joining each with "/"
234              
235             Returns the new C object
236              
237             =cut
238              
239             =head2 $path->clone
240              
241             Returns an exact copy of $path
242              
243             =cut
244              
245             =head2 $path->set( )
246              
247             =head2 $path->set( , [ , ..., ] )
248              
249             Set the path of $path to or the concatenation of each (separated by "/")
250              
251             Returns $path
252              
253             =cut
254              
255             =head2 $path->is_nil
256              
257             =head2 $path->is_empty
258              
259             Returns true if $path is equal to ""
260              
261             =cut
262              
263             =head2 $path->is_root
264              
265             Returns true if $path is equal to "/"
266              
267             =cut
268              
269             =head2 $path->is_tree
270              
271             Returns true if $path begins with "/"
272              
273             path("/a/b")->is_tree # Returns true
274             path("c/d")->is_tree # Returns false
275              
276             =cut
277              
278             =head2 $path->is_branch
279              
280             Returns true if $path does NOT begin with a "/"
281              
282             path("")->is_branch # Returns true
283             path("/")->is_branch # Returns false
284             path("c/d")->is_branch # Returns true
285             path("/a/b")->is_branch # Returns false
286              
287             =cut
288              
289             =head2 $path->to_tree
290              
291             Change $path by prefixing a "/" if it doesn't have one already
292              
293             Returns $path
294              
295             =cut
296              
297             =head2 $path->to_branch
298              
299             Change $path by removing a leading "/" if it has one
300              
301             Returns $path
302              
303             =cut
304              
305             =head2 $path->list
306              
307             Returns the path in list form by splitting at each "/"
308              
309             path("c/d")->list # Returns ("c", "d")
310             path("/a/b/")->last # Returns ("a", "b")
311              
312             NOTE: This behavior is different since 0.093 (see above)
313              
314             =cut
315              
316             =head2 $path->split
317              
318             =cut
319              
320             =head2 $path->first
321              
322             Returns the first part of $path up to the first "/" (but not including the leading slash, if any)
323              
324             path("c/d")->first # Returns "c"
325             path("/a/b")->first # Returns "a"
326              
327             This is equivalent to $path->at(0)
328              
329             =cut
330              
331             =head2 $path->last
332              
333             Returns the last part of $path up to the last "/"
334              
335             path("c/d")->last # Returns "d"
336             path("/a/b/")->last # Returns "b"
337              
338             This is equivalent to $path->at(-1)
339              
340             =cut
341              
342             =head2 $path->at( $index )
343              
344             Returns the part of path at $index, not including any slashes
345             You can use a negative $index to start from the end of path
346              
347             path("/a/b/c/").at(0) # a (equivalent to $path->first)
348             path("/a/b/c/").at(-1) # c (equivalent to $path->last)
349             path("/a/b/c/").at(1) # b
350              
351             =cut
352              
353             =head2 $path->beginning
354              
355             Returns the first part of path, including the leading slash, if any
356              
357             path("/a/b/c/")->beginning # /a
358             path("a/b/c/")->beginning # a
359              
360             =cut
361              
362             =head2 $path->ending
363              
364             Returns the first part of path, including the leading slash, if any
365              
366             path("/a/b/c/")->ending # c/
367             path("/a/b/c")->ending # c
368              
369             =cut
370              
371             =head2 $path->get
372              
373             =head2 $path->stringify
374              
375             Returns the path in string or scalar form
376              
377             path("c/d")->list # Returns "c/d"
378             path("/a/b/")->last # Returns "/a/b"
379              
380             =cut
381              
382             =head2 $path->push( , [ , ..., ] )
383              
384             =head2 $path->down( , [ , ..., ] )
385              
386             Modify $path by appending each to the end of \$path, separated by "/"
387              
388             Returns $path
389              
390             path( "a/b/c" )->down( "d/e" ) # a/b/c/d/e
391              
392             =cut
393              
394             =head2 $path->child( , [ , ..., ] )
395              
396             Make a copy of $path and push each to the end of the new path.
397              
398             Returns the new child path
399              
400             path( "a/b/c" )->child( "d/e" ) # a/b/c/d/e
401              
402             =cut
403              
404             =head2 $path->append( $part1, [ $part2 ], ... )
405              
406             Modify path by appending $part1 WITHOUT separating it by a slash. Any, optional,
407             following $part2, ..., will be separated by slashes as normal
408              
409             $path = path( "a/b/c" )
410             $path->append( "d", "ef/g", "h" ) # "a/b/cd/ef/g/h"
411              
412             =cut
413              
414             =head2 $path->extension
415              
416             Returns the extension of path, including the leading the dot
417              
418             Returns "" if path does not have an extension
419              
420             path( "a/b/c.html" )->extension # .html
421             path( "a/b/c" )->extension # ""
422             path( "a/b/c.tar.gz" )->extension # .gz
423             path( "a/b/c.tar.gz" )->extension({ match: "*" }) # .tar.gz
424              
425             =head2 $path->extension( $extension )
426              
427             Modify path by changing the existing extension of path, if any, to $extension
428              
429             path( "a/b/c.html" )->extension( ".txt" ) # a/b/c.txt
430             path( "a/b/c.html" )->extension( "zip" ) # a/b/c.zip
431             path( "a/b/c.html" )->extension( "" ) # a/b/c
432              
433             Returns path
434              
435             =cut
436              
437             =head2 $path->pop( )
438              
439             Modify $path by removing parts from the end of $path
440              
441             Returns the removed path as a C object
442              
443             =cut
444              
445             =head2 $path->up( )
446              
447             Modify $path by removing parts from the end of $path
448              
449             Returns $path
450              
451             =cut
452              
453             =head2 $path->parent( )
454              
455             Make a copy of $path and pop parts from the end of the new path
456              
457             Returns the new parent path
458              
459             =cut
460              
461             =head2 $path->file
462              
463             =head2 $path->file( , [ , ..., ] )
464              
465             Create a new C object using $path as a base, and optionally extending it by each
466              
467             Returns the new file object
468              
469             =cut
470              
471             =head2 $path->dir
472              
473             =head2 $path->dir( , [ , ..., ] )
474              
475             Create a new C object using $path as a base, and optionally extending it by each
476              
477             Returns the new dir object
478              
479             =cut
480              
481             =head1 SEE ALSO
482              
483             L
484              
485             L
486              
487             L
488              
489             L
490              
491             L
492              
493             L
494              
495             =head1 AUTHOR
496              
497             Robert Krimen, C<< >>
498              
499             =head1 SOURCE
500              
501             You can contribute or fork this project via GitHub:
502              
503             L
504              
505             git clone git://github.com/robertkrimen/path-abstract.git Path-Abstract
506              
507             =head1 BUGS
508              
509             Please report any bugs or feature requests to
510             C, or through the web interface at
511             L.
512             I will be notified, and then you'll automatically be notified of progress on
513             your bug as I make changes.
514              
515             =head1 SUPPORT
516              
517             You can find documentation for this module with the perldoc command.
518              
519             perldoc Path::Abstract
520              
521             You can also look for information at:
522              
523             =over 4
524              
525             =item * AnnoCPAN: Annotated CPAN documentation
526              
527             L
528              
529             =item * CPAN Ratings
530              
531             L
532              
533             =item * RT: CPAN's request tracker
534              
535             L
536              
537             =item * Search CPAN
538              
539             L
540              
541             =back
542              
543             =head1 ACKNOWLEDGEMENTS
544              
545             Thanks to Joshua ben Jore, Max Kanat-Alexander, and Scott McWhirter for discovering the "use overload ..." slowdown issue.
546              
547             =head1 COPYRIGHT & LICENSE
548              
549             Copyright 2007 Robert Krimen, all rights reserved.
550              
551             This program is free software; you can redistribute it and/or modify it
552             under the same terms as Perl itself.
553              
554             =cut
555              
556             1; # End of Path::Abstract