File Coverage

lib/Path/Extended/Entity.pm
Criterion Covered Total %
statement 126 140 90.0
branch 45 58 77.5
condition 18 24 75.0
subroutine 37 40 92.5
pod 19 19 100.0
total 245 281 87.1


line stmt bran cond sub pod time code
1             package Path::Extended::Entity;
2              
3 28     28   52900 use strict;
  28         208  
  28         924  
4 28     28   112 use warnings;
  28         35  
  28         626  
5 28     28   112 use Carp ();
  28         34  
  28         391  
6 28     28   99 use File::Spec;
  28         32  
  28         496  
7 28     28   13664 use Log::Dump;
  28         47067  
  28         144  
8 28     28   6645 use Scalar::Util qw( blessed );
  28         39  
  28         3127  
9              
10             use overload
11 224     224   4609 '""' => sub { shift->path },
12 53     53   235 'cmp' => sub { return "$_[0]" cmp "$_[1]" },
13 964     964   1910 'bool' => sub { shift->_boolify },
14 28     28   30938 '*{}' => sub { shift->_handle };
  28     150   23893  
  28         336  
  150         216  
15              
16             sub new {
17 504     504 1 17617 my $class = shift;
18 504         1075 my $self = bless {}, $class;
19              
20 504 100       1406 $self->_initialize(@_) or return;
21              
22 503         1018 $self;
23             }
24              
25 4     4   11 sub _initialize {1}
26 964     964   1539 sub _boolify {1}
27              
28             sub _class {
29 318     318   631 my ($self, $type) = @_;
30 318         413 my $class = ref $self;
31 318         1605 $class =~ s/::(?:File|Dir|Entity)$//;
32 318 100       600 return $class unless $type;
33 310 100       1188 return $class.'::'.($type eq 'file' ? 'File' : 'Dir');
34             }
35              
36             sub _set_path {
37 499     499   519 my ($self, $path) = @_;
38 499         855 $self->{input_path} = $self->_unixify($path);
39 499         4259 $self->{abs_path} = $self->_unixify( File::Spec->rel2abs($path) );
40              
41             # respect setting of _attribute when already done
42 499   100     1971 $self->{_stringify_absolute} ||= File::Spec->file_name_is_absolute($path);
43             }
44              
45             sub _related {
46 299     299   557 my ($self, $type, @parts) = @_;
47              
48 299         509 my $class = $self->_class($type);
49 299 50       15305 eval "require $class" or Carp::croak $@;
50 299         548 my $item;
51 299 100 66     2486 if ( @parts && $parts[0] eq '..' ) { # parent
    100 66        
52 101         304 require File::Basename;
53 101         226 $item = $class->new( File::Basename::dirname($self->_absolute) );
54             }
55             elsif ( @parts && File::Spec->file_name_is_absolute($parts[0]) ) {
56 10         31 $item = $class->new( @parts );
57             }
58             else {
59 188         388 $item = $class->new( $self->_absolute, @parts );
60             }
61 299         449 foreach my $key ( grep /^_/, keys %{ $self } ) {
  299         1485  
62 390         741 $item->{$key} = $self->{$key};
63             }
64 299         1021 $item;
65             }
66              
67             sub _unixify {
68 2280     2280   2223 my ($self, $path) = @_;
69              
70 2280 50       4770 $path =~ s{\\}{/}g if $^O eq 'MSWin32';
71              
72 2280         44494 return $path;
73             }
74              
75 182     182   1075 sub _handle { shift->{handle} }
76              
77             sub _stringify_absolute {
78 300     300   274 my $self = shift;
79 300 100 100     1729 $self->{_stringify_absolute} && !$self->{_base} ? 1 : '';
80             }
81              
82             # returns the string version of the path
83             sub path {
84 300     300 1 288 my $self = shift;
85 300 100       446 return ( $self->_stringify_absolute ) ? $self->_absolute : $self->_relative;
86             }
87              
88 27     27 1 40 sub stringify { shift->path }
89              
90 103     103 1 266 sub is_dir { shift->{is_dir} }
91 457 100   457 1 2033 sub is_open { shift->{handle} ? 1 : 0 }
92              
93              
94             sub is_absolute {
95 8     8 1 26 my $self = shift;
96 8         53 File::Spec->file_name_is_absolute($self->{input_path});
97             }
98              
99             sub resolve {
100 2     2 1 4 my $self = shift;
101 2 50       65 Carp::croak "$self: $!" unless -e $self->{abs_path};
102             # WoP :
103             # Cwd::realpath returns the resolved absolute path
104             # calling File::Spec->file_name_is_absolute() not necessary
105 2         42 $self->{abs_path} = $self->_unixify(Cwd::realpath($self->{abs_path}));
106 2         12 $self->{_stringify_absolute} = File::Spec->file_name_is_absolute($self->{abs_path});
107 2         2882 $self;
108             }
109              
110             sub _absolute {
111 1128     1128   2370 my ($self, %options) = @_;
112              
113 1128         3387 my $path = File::Spec->canonpath( $self->{abs_path} );
114 1128 50       2523 if ( $options{native} ) {
    100          
115 0         0 return $path;
116             }
117             elsif ( $self->{_compat} ) {
118 265         2221 my ($vol, @parts) = File::Spec->splitpath( $path );
119 265 50       534 $vol = '' if $Path::Extended::IgnoreVolume;
120 265         1917 return $self->_unixify( File::Spec->catpath($vol, File::Spec->catdir( @parts ), '') );
121             }
122             else {
123 863         1316 return $self->_unixify($path);
124             }
125             }
126              
127             sub _relative {
128 152     152   180 my $self = shift;
129 152 100       290 my $base = @_ % 2 ? shift : undef;
130 152         197 my %options = @_;
131              
132 152   100     513 $base ||= $options{base} || $self->{_base};
      100        
133              
134 152         5452 my $path = File::Spec->abs2rel( $self->{abs_path}, $base );
135 152 50       488 $path = $self->_unixify($path) unless $options{native};
136              
137 152         2187 $path;
138             }
139              
140 41     41 1 156 sub absolute { shift->_absolute(@_) }
141 62     62 1 181 sub relative { shift->_relative(@_) }
142              
143 97     97 1 965 sub parent { shift->_related( dir => '..' ); }
144              
145             sub unlink {
146 33     33 1 2196 my $self = shift;
147              
148 33 100       61 $self->close if $self->is_open;
149 33 100       66 unlink $self->_absolute if $self->exists;
150             }
151              
152             sub exists {
153 238     238 1 441 my $self = shift;
154              
155 238 100       447 -e $self->_absolute ? 1 : 0;
156             }
157              
158             sub is_writable {
159 0     0 1 0 my $self = shift;
160              
161 0 0       0 -w $self->_absolute ? 1 : 0;
162             }
163              
164             sub is_readable {
165 0     0 1 0 my $self = shift;
166              
167 0 0       0 -r $self->_absolute ? 1 : 0;
168             }
169              
170             sub copy_to {
171 4     4 1 34 my ($self, $destination) = @_;
172              
173 4 100       12 unless ( $destination ) {
174 1         8 $self->log( fatal => 'requires destination' );
175 1         20 return;
176             }
177              
178 3         6 my $class = ref $self;
179 3         11 $destination = $class->new( "$destination" );
180              
181 3         1128 require File::Copy::Recursive;
182             File::Copy::Recursive::rcopy( $self->_absolute, $destination->_absolute )
183 3 50       9651 or do { $self->log( error => "Can't copy $self to $destination: $!" ); return; };
  0         0  
  0         0  
184              
185 3         1746 $self;
186             }
187              
188             sub move_to {
189 4     4 1 15 my ($self, $destination) = @_;
190              
191 4 100       13 unless ( $destination ) {
192 1         4 $self->log( fatal => 'requires destination' );
193 1         11 return;
194             }
195              
196 3         7 my $class = ref $self;
197 3         12 $destination = $class->new( "$destination" );
198              
199 3 100       7 $self->close if $self->is_open;
200              
201 3         20 require File::Copy::Recursive;
202             File::Copy::Recursive::rmove( $self->_absolute, $destination->_absolute )
203 3 50       9 or do { $self->log( error => "Can't move $self to $destination: $!" ); return; };
  0         0  
  0         0  
204              
205 3         1808 $self->{abs_path} = $destination->_absolute;
206              
207 3         10 $self;
208             }
209              
210             sub rename_to {
211 4     4 1 14 my ($self, $destination) = @_;
212              
213 4 100       11 unless ( $destination ) {
214 1         2 $self->log( fatal => 'requires destination' );
215 1         11 return;
216             }
217              
218 3         34 my $class = ref $self;
219 3         10 $destination = $class->new( "$destination" );
220              
221 3 100       8 $self->close if $self->is_open;
222              
223             rename $self->_absolute => $destination->_absolute
224 3 50       8 or do { $self->log( error => "Can't rename $self to $destination: $!" ); return; };
  0         0  
  0         0  
225              
226 3         9 $self->{abs_path} = $destination->_absolute;
227              
228 3         8 $self;
229             }
230              
231             sub stat {
232 6     6 1 554 my $self = shift;
233              
234 6         1591 require File::stat;
235 6   66     16752 File::stat::stat( $self->{handle} || $self->{abs_path} );
236             }
237              
238             sub lstat {
239 0     0 1   my $self = shift;
240              
241 0           require File::stat;
242 0   0       File::stat::lstat( $self->{handle} || $self->{abs_path} );
243             }
244              
245             1;
246              
247             __END__