File Coverage

blib/lib/Path/Class/Tiny.pm
Criterion Covered Total %
statement 89 90 98.8
branch 32 38 84.2
condition 11 21 52.3
subroutine 30 30 100.0
pod 19 19 100.0
total 181 198 91.4


line stmt bran cond sub pod time code
1             package Path::Class::Tiny;
2              
3 11     11   1165381 use 5.10.0;
  11         124  
4 11     11   64 use strict;
  11         20  
  11         238  
5 11     11   53 use warnings;
  11         25  
  11         487  
6              
7             our $VERSION = '0.05'; # VERSION
8              
9 11     11   80 use Exporter;
  11         23  
  11         908  
10             our @EXPORT = qw< cwd path file tempfile >; # dir() handled by `import`
11              
12             sub import
13             {
14 11     11   76 no strict 'refs';
  11         23  
  11         1309  
15 10 50 33 10   151 *{ caller . '::dir' } = \&_global_dir if @_ <= 1 or grep { $_ eq 'dir' } @_;
  10         42  
  0         0  
16 10         4529 goto \&Exporter::import;
17             }
18              
19              
20 11     11   76 use Carp;
  11         23  
  11         784  
21 11     11   5117 use Module::Runtime qw< require_module >;
  11         17791  
  11         66  
22              
23              
24 11     11   763 use File::Spec ();
  11         26  
  11         193  
25 11     11   9690 use Path::Tiny ();
  11         130327  
  11         13322  
26             our @ISA = qw< Path::Tiny >;
27              
28              
29             sub path
30             {
31 282     282 1 123804 bless Path::Tiny::path(@_), __PACKAGE__;
32             }
33              
34             sub cwd
35             {
36 3     3 1 3110 require Cwd;
37 3         4637 path(Cwd::getcwd());
38             }
39              
40             *file = \&path;
41 26 100   26   48059 sub _global_dir { @_ ? path(@_) : path(Path::Tiny->cwd) }
42              
43             # just like in Path::Tiny
44 2     2 1 639 sub new { shift; path(@_) }
  2         11  
45 27     27 1 11200 sub child { path(shift->[0], @_) }
46              
47              
48             # This seemed like a good idea when I originally conceived this class. Now,
49             # after further thought, it seems wildly reckless. Who knows? I may swing
50             # back the other way before we're all done. But, for now, I think we're
51             # leaving this out, and that may very well end up being a permanent thing.
52             #
53             # sub isa
54             # {
55             # my ($obj, $type) = @_;
56             # return 1 if $type eq 'Path::Class::File';
57             # return 1 if $type eq 'Path::Class::Dir';
58             # return 1 if $type eq 'Path::Class::Entity';
59             # return $obj->SUPER::isa($type);
60             # }
61              
62              
63             # essentially just reblessings
64 121     121 1 28738 sub parent { path( &Path::Tiny::parent ) }
65 33     33 1 817 sub realpath { path( &Path::Tiny::realpath ) }
66 2     2 1 1493 sub copy_to { path( &Path::Tiny::copy ) }
67 1     1 1 367 sub children { map { path($_) } &Path::Tiny::children }
  1         135  
68 2     2 1 1710 sub tempfile { bless &Path::Tiny::tempfile, __PACKAGE__ }
69              
70             # simple correspondences
71             *dir = \&parent;
72             *dirname = \&parent;
73             *subdir = \&child;
74             *rmtree = \&Path::Tiny::remove_tree;
75              
76             # more complex corresondences
77 1     1 1 37 sub cleanup { path(shift->canonpath) }
78 5 100   5 1 6259 sub open { my $io_class = -d $_[0] ? 'IO::Dir' : 'IO::File'; require_module $io_class; $io_class->new(@_) }
  5         114  
  5         5372  
79              
80              
81             # wrappers
82             sub touch
83             {
84 9     9 1 9685 my ($self, $dt) = @_;
85 9 100 66     58 $dt = $dt->epoch if defined $dt and $dt->can('epoch');
86 9         124 $self->SUPER::touch($dt);
87             }
88              
89             sub move_to
90             {
91 1     1 1 751 my ($self, $dest) = @_;
92 1         10 $self->move($dest);
93             # if we get this far, the move must have succeeded
94             # this is basically the way Path::Class::File does it:
95 1         54 my $new = path($dest);
96 1 50       43 my $max_idx = $#$self > $#$new ? $#$self : $#$new;
97             # yes, this is a mutator, which could be considered bad
98             # OTOH, the file is actually mutating on the disk,
99             # so you can also consider it good that the object mutates to keep up
100 1         7 $self->[$_] = $new->[$_] foreach 0..$max_idx;
101 1         5 return $self;
102             }
103              
104              
105             # reimplementations
106              
107             sub dir_list
108             {
109 23     23 1 5515 my $self = shift;
110 23         58 my @list = ( File::Spec->splitdir($self->parent), $self->basename );
111              
112             # The return value of dir_list is remarkably similar to that of splice: it's identical for all
113             # cases in list context, and even for one case in scalar context. So we'll cheat and use splice
114             # for most of the cases, and handle the other two scalar context cases specially.
115 23 100       697 if (@_ == 0)
    100          
116             {
117 14         118 return @list; # will DTRT regardless of context
118             }
119             elsif (@_ == 1)
120             {
121 4 100       22 return wantarray ? splice @list, $_[0] : $list[shift];
122             }
123             else
124             {
125 5         21 return splice @list, $_[0], $_[1];
126             }
127             }
128             # components is really just an alias for `dir_list`
129             *components = \&dir_list;
130              
131              
132             # This is more or less how Path::Class::File does it.
133             sub slurp
134             {
135 12     12 1 7322 my ($self, %args) = @_;
136 12         29 my $splitter = delete $args{split};
137 12 50 0     36 $args{chomp} //= delete $args{chomped} if exists $args{chomped};
138 12   66     68 $args{binmode} //= delete $args{iomode};
139 12 100       46 $args{binmode} =~ s/^
140              
141 12 100       31 if (wantarray)
142             {
143 6         33 my @data = $self->lines(\%args);
144 6 100       1308 @data = map { [ split $splitter, $_ ] } @data if $splitter;
  4         51  
145 6         44 return @data;
146             }
147             else
148             {
149 6 50       12 croak "'split' argument can only be used in list context" if $splitter;
150 6 50       15 croak "'chomp' argument not implemented in scalar context" if exists $args{chomp};
151 6         29 return $self->Path::Tiny::slurp(\%args);
152             }
153             }
154              
155             # A bit trickier, as we have to distinguish between Path::Class::File style,
156             # which is optional hash + string-or-arrayref, and Path::Tiny style, which is
157             # optional hashref + string-or-arrayref. But, since each one's arg hash(ref)
158             # only accepts a single option, we should be able to fake it fairly simply.
159             sub spew
160             {
161 4     4 1 622 my ($self, @data) = @_;
162 4 100 66     24 if ( @data == 3 and $data[0] eq 'iomode' )
163             {
164 2         4 shift @data;
165 2         5 my $binmode = shift @data;
166 2         13 $binmode =~ s/^(>>?)//; # remove redundant openmode, if present
167 2 100       8 unshift @data, {binmode => $binmode} if $binmode;
168             # if openmode was '>>', redirect to `append`
169 2 100 66     24 return $self->append(@data) if $1 and $1 eq '>>';
170             }
171 3         13 return $self->Path::Tiny::spew(@data);
172             }
173              
174              
175             my $_iter;
176             sub next
177             {
178 6   66 6 1 907 $_iter //= Path::Tiny::path(shift)->iterator;
179 6         140 my $p = $_iter->();
180 6 100       490 return $p ? bless $p, __PACKAGE__ : undef $_iter;
181             }
182              
183              
184             # new methods
185              
186             sub ef
187             {
188 16     16 1 3892 my ($self, $other) = @_;
189 16         47 return $self->realpath eq path($other)->realpath;
190             }
191              
192              
193             sub mtime
194             {
195 3 50   3 1 3200 require Date::Easy::Datetime or croak("can't locate Date::Easy");
196 3         41247 return Date::Easy::Datetime->new(shift->stat->mtime);
197             }
198              
199              
200             1;
201              
202              
203             # ABSTRACT: a Path::Tiny wrapper for Path::Class compatibility
204             # COPYRIGHT
205              
206             __END__