File Coverage

blib/lib/Path/Class/Tiny.pm
Criterion Covered Total %
statement 88 89 98.8
branch 32 38 84.2
condition 11 21 52.3
subroutine 29 29 100.0
pod 18 18 100.0
total 178 195 91.2


line stmt bran cond sub pod time code
1             package Path::Class::Tiny;
2              
3 10     10   820911 use 5.10.0;
  10         101  
4 10     10   47 use strict;
  10         15  
  10         190  
5 10     10   45 use warnings;
  10         12  
  10         351  
6              
7             our $VERSION = '0.04'; # VERSION
8              
9 10     10   44 use Exporter;
  10         13  
  10         656  
10             our @EXPORT = qw< cwd path file >;
11              
12             sub import
13             {
14 10     10   57 no strict 'refs';
  10         15  
  10         927  
15 9 50 33 9   128 *{ caller . '::dir' } = \&_global_dir if @_ <= 1 or grep { $_ eq 'dir' } @_;
  9         32  
  0         0  
16 9         3604 goto \&Exporter::import;
17             }
18              
19              
20 10     10   57 use Carp;
  10         21  
  10         584  
21 10     10   3538 use Module::Runtime qw< require_module >;
  10         11969  
  10         46  
22              
23              
24 10     10   578 use File::Spec ();
  10         23  
  10         159  
25 10     10   6820 use Path::Tiny ();
  10         93154  
  10         9193  
26             our @ISA = qw< Path::Tiny >;
27              
28              
29             sub path
30             {
31 246     246 1 105818 bless Path::Tiny::path(@_), __PACKAGE__;
32             }
33              
34             sub cwd
35             {
36 3     3 1 2367 require Cwd;
37 3         3581 path(Cwd::getcwd());
38             }
39              
40             *file = \&path;
41 24 100   24   18719 sub _global_dir { @_ ? path(@_) : path(Path::Tiny->cwd) }
42              
43             # just like in Path::Tiny
44 2     2 1 516 sub new { shift; path(@_) }
  2         8  
45 27     27 1 9224 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 88     88 1 19532 sub parent { path( &Path::Tiny::parent ) }
65 33     33 1 812 sub realpath { path( &Path::Tiny::realpath ) }
66 2     2 1 836 sub copy_to { path( &Path::Tiny::copy ) }
67 1     1 1 291 sub children { map { path($_) } &Path::Tiny::children }
  1         111  
68              
69             # simple correspondences
70             *dir = \&parent;
71             *subdir = \&child;
72             *rmtree = \&Path::Tiny::remove_tree;
73              
74             # more complex corresondences
75 1     1 1 36 sub cleanup { path(shift->canonpath) }
76 5 100   5 1 2370 sub open { my $io_class = -d $_[0] ? 'IO::Dir' : 'IO::File'; require_module $io_class; $io_class->new(@_) }
  5         91  
  5         4396  
77              
78              
79             # wrappers
80             sub touch
81             {
82 9     9 1 8638 my ($self, $dt) = @_;
83 9 100 66     55 $dt = $dt->epoch if defined $dt and $dt->can('epoch');
84 9         124 $self->SUPER::touch($dt);
85             }
86              
87             sub move_to
88             {
89 1     1 1 609 my ($self, $dest) = @_;
90 1         7 $self->move($dest);
91             # if we get this far, the move must have succeeded
92             # this is basically the way Path::Class::File does it:
93 1         37 my $new = path($dest);
94 1 50       39 my $max_idx = $#$self > $#$new ? $#$self : $#$new;
95             # yes, this is a mutator, which could be considered bad
96             # OTOH, the file is actually mutating on the disk,
97             # so you can also consider it good that the object mutates to keep up
98 1         5 $self->[$_] = $new->[$_] foreach 0..$max_idx;
99 1         3 return $self;
100             }
101              
102              
103             # reimplementations
104              
105             sub dir_list
106             {
107 23     23 1 4434 my $self = shift;
108 23         47 my @list = ( File::Spec->splitdir($self->parent), $self->basename );
109              
110             # The return value of dir_list is remarkably similar to that of splice: it's identical for all
111             # cases in list context, and even for one case in scalar context. So we'll cheat and use splice
112             # for most of the cases, and handle the other two scalar context cases specially.
113 23 100       551 if (@_ == 0)
    100          
114             {
115 14         72 return @list; # will DTRT regardless of context
116             }
117             elsif (@_ == 1)
118             {
119 4 100       16 return wantarray ? splice @list, $_[0] : $list[shift];
120             }
121             else
122             {
123 5         17 return splice @list, $_[0], $_[1];
124             }
125             }
126             # components is really just an alias for `dir_list`
127             *components = \&dir_list;
128              
129              
130             # This is more or less how Path::Class::File does it.
131             sub slurp
132             {
133 12     12 1 5381 my ($self, %args) = @_;
134 12         23 my $splitter = delete $args{split};
135 12 50 0     27 $args{chomp} //= delete $args{chomped} if exists $args{chomped};
136 12   66     54 $args{binmode} //= delete $args{iomode};
137 12 100       44 $args{binmode} =~ s/^
138              
139 12 100       28 if (wantarray)
140             {
141 6         22 my @data = $self->lines(\%args);
142 6 100       1075 @data = map { [ split $splitter, $_ ] } @data if $splitter;
  4         31  
143 6         36 return @data;
144             }
145             else
146             {
147 6 50       9 croak "'split' argument can only be used in list context" if $splitter;
148 6 50       13 croak "'chomp' argument not implemented in scalar context" if exists $args{chomp};
149 6         37 return $self->Path::Tiny::slurp(\%args);
150             }
151             }
152              
153             # A bit trickier, as we have to distinguish between Path::Class::File style,
154             # which is optional hash + string-or-arrayref, and Path::Tiny style, which is
155             # optional hashref + string-or-arrayref. But, since each one's arg hash(ref)
156             # only accepts a single option, we should be able to fake it fairly simply.
157             sub spew
158             {
159 4     4 1 481 my ($self, @data) = @_;
160 4 100 66     20 if ( @data == 3 and $data[0] eq 'iomode' )
161             {
162 2         5 shift @data;
163 2         3 my $binmode = shift @data;
164 2         13 $binmode =~ s/^(>>?)//; # remove redundant openmode, if present
165 2 100       7 unshift @data, {binmode => $binmode} if $binmode;
166             # if openmode was '>>', redirect to `append`
167 2 100 66     19 return $self->append(@data) if $1 and $1 eq '>>';
168             }
169 3         11 return $self->Path::Tiny::spew(@data);
170             }
171              
172              
173             my $_iter;
174             sub next
175             {
176 6   66 6 1 750 $_iter //= Path::Tiny::path(shift)->iterator;
177 6         117 my $p = $_iter->();
178 6 100       406 return $p ? bless $p, __PACKAGE__ : undef $_iter;
179             }
180              
181              
182             # new methods
183              
184             sub ef
185             {
186 16     16 1 4596 my ($self, $other) = @_;
187 16         51 return $self->realpath eq path($other)->realpath;
188             }
189              
190              
191             sub mtime
192             {
193 3 50   3 1 2408 require Date::Easy::Datetime or croak("can't locate Date::Easy");
194 3         31531 return Date::Easy::Datetime->new(shift->stat->mtime);
195             }
196              
197              
198             1;
199              
200              
201             # ABSTRACT: a Path::Tiny wrapper for Path::Class compatibility
202             # COPYRIGHT
203              
204             __END__