File Coverage

blib/lib/Path/Class/Tiny.pm
Criterion Covered Total %
statement 90 91 98.9
branch 32 38 84.2
condition 11 21 52.3
subroutine 31 31 100.0
pod 20 20 100.0
total 184 201 91.5


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