File Coverage

blib/lib/Path/Class/Tiny.pm
Criterion Covered Total %
statement 92 93 98.9
branch 33 38 86.8
condition 11 21 52.3
subroutine 31 31 100.0
pod 20 20 100.0
total 187 203 92.1


line stmt bran cond sub pod time code
1             package Path::Class::Tiny;
2              
3 12     12   2737745 use 5.10.0;
  12         50  
4 12     12   71 use strict;
  12         36  
  12         329  
5 12     12   55 use warnings;
  12         27  
  12         995  
6              
7             our $VERSION = '0.07'; # VERSION
8              
9 12     12   66 use Exporter;
  12         75  
  12         1110  
10             our @EXPORT = qw< cwd path file tempfile tempdir >; # dir() handled by `import`
11              
12             sub import
13             {
14 12     12   103 no strict 'refs';
  12         36  
  12         1739  
15 11 50 33 11   175 *{ caller . '::dir' } = \&_global_dir if @_ <= 1 or grep { $_ eq 'dir' } @_;
  11         62  
  0         0  
16 11         8684 goto \&Exporter::import;
17             }
18              
19              
20 12     12   90 use Carp;
  12         39  
  12         1013  
21 12     12   5850 use Module::Runtime qw< require_module >;
  12         21179  
  12         110  
22              
23              
24 12     12   981 use File::Spec ();
  12         60  
  12         236  
25 12     12   11155 use Path::Tiny ();
  12         199388  
  12         16436  
26             our @ISA = qw< Path::Tiny >;
27              
28              
29             sub path
30             {
31 286     286 1 237589 bless Path::Tiny::path(@_), __PACKAGE__;
32             }
33              
34             sub cwd
35             {
36 3     3 1 206856 require Cwd;
37 3         5527 path(Cwd::getcwd());
38             }
39              
40             *file = \&path;
41 27 100   27   240824 sub _global_dir { @_ ? path(@_) : path(Path::Tiny->cwd) }
42              
43             # just like in Path::Tiny
44 2     2 1 166439 sub new { shift; path(@_) }
  2         18  
45 27     27 1 111018 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 38256 sub parent { path( &Path::Tiny::parent ) }
65 33     33 1 1006 sub realpath { path( &Path::Tiny::realpath ) }
66 2     2 1 1967 sub copy_to { path( &Path::Tiny::copy ) }
67 1     1 1 372 sub children { map { path($_) } &Path::Tiny::children }
  1         147  
68 2     2 1 233370 sub tempfile { bless &Path::Tiny::tempfile, __PACKAGE__ }
69 9     9 1 1289558 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 40 sub cleanup { path(shift->canonpath) }
79 8 100   8 1 4166 sub open { my $io_class = -d $_[0] ? 'IO::Dir' : 'IO::File'; require_module $io_class; $io_class->new(@_) }
  8         332  
  8         6239  
80              
81              
82             # wrappers
83             sub touch
84             {
85 9     9 1 12282 my ($self, $dt) = @_;
86 9 100 66     67 $dt = $dt->epoch if defined $dt and $dt->can('epoch');
87 9         156 $self->SUPER::touch($dt);
88             }
89              
90             sub move_to
91             {
92 1     1 1 1390 my ($self, $dest) = @_;
93 1         11 $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         267 my $new = path($dest);
97 1 50       50 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         8 $self->[$_] = $new->[$_] foreach 0..$max_idx;
102 1         16 return $self;
103             }
104              
105              
106             # reimplementations
107              
108             sub dir_list
109             {
110 23     23 1 6210 my $self = shift;
111 23         60 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       650 if (@_ == 0)
    100          
117             {
118 14         87 return @list; # will DTRT regardless of context
119             }
120             elsif (@_ == 1)
121             {
122 4 100       18 return wantarray ? splice @list, $_[0] : $list[shift];
123             }
124             else
125             {
126 5         21 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 15     15 1 15448 my ($self, %args) = @_;
137 15         37 my $splitter = delete $args{split};
138 15 50 0     57 $args{chomp} //= delete $args{chomped} if exists $args{chomped};
139 15   66     96 $args{binmode} //= delete $args{iomode};
140 15 100       52 $args{binmode} =~ s/^
141              
142 15 100       38 if (wantarray)
143             {
144 6         37 my @data = $self->lines(\%args);
145 6 100       1877 @data = map { [ split $splitter, $_ ] } @data if $splitter;
  4         70  
146 6         74 return @data;
147             }
148             else
149             {
150 9 50       22 croak "'split' argument can only be used in list context" if $splitter;
151 9         17 my $do_chomp = delete $args{chomp};
152 9         58 my $data = $self->Path::Tiny::slurp(\%args);
153 9 100       2327 chomp $data if $do_chomp;
154 9         48 return $data;
155             }
156             }
157              
158             # A bit trickier, as we have to distinguish between Path::Class::File style,
159             # which is optional hash + string-or-arrayref, and Path::Tiny style, which is
160             # optional hashref + string-or-arrayref. But, since each one's arg hash(ref)
161             # only accepts a single option, we should be able to fake it fairly simply.
162             sub spew
163             {
164 4     4 1 6683 my ($self, @data) = @_;
165 4 100 66     25 if ( @data == 3 and $data[0] eq 'iomode' )
166             {
167 2         3 shift @data;
168 2         5 my $binmode = shift @data;
169 2         13 $binmode =~ s/^(>>?)//; # remove redundant openmode, if present
170 2 100       11 unshift @data, {binmode => $binmode} if $binmode;
171             # if openmode was '>>', redirect to `append`
172 2 100 66     26 return $self->append(@data) if $1 and $1 eq '>>';
173             }
174 3         16 return $self->Path::Tiny::spew(@data);
175             }
176              
177              
178             my $_iter;
179             sub next
180             {
181 6   66 6 1 1378 $_iter //= Path::Tiny::path(shift)->iterator;
182 6         183 my $p = $_iter->();
183 6 100       635 return $p ? bless $p, __PACKAGE__ : undef $_iter;
184             }
185              
186              
187             # new methods
188              
189             sub ef
190             {
191 16     16 1 13894 my ($self, $other) = @_;
192 16         62 return $self->realpath eq path($other)->realpath;
193             }
194              
195              
196             sub mtime
197             {
198 3 50   3 1 3772 require Date::Easy::Datetime or croak("can't locate Date::Easy");
199 3         49906 return Date::Easy::Datetime->new(shift->stat->mtime);
200             }
201              
202              
203             1;
204              
205              
206             # ABSTRACT: a Path::Tiny wrapper for Path::Class compatibility
207             # COPYRIGHT
208              
209             __END__