File Coverage

blib/lib/IO/All/File.pm
Criterion Covered Total %
statement 122 137 89.0
branch 38 58 65.5
condition 7 15 46.6
subroutine 28 31 90.3
pod 11 18 61.1
total 206 259 79.5


line stmt bran cond sub pod time code
1 56     56   246 use strict; use warnings;
  56     56   75  
  56         1809  
  56         246  
  56         73  
  56         2828  
2             package IO::All::File;
3              
4 56     56   20649 use IO::All::Filesys -base;
  56         113  
  56         701  
5 56     56   303 use IO::All -base;
  56         83  
  56         388  
6 56     56   29734 use IO::File;
  56         104139  
  56         7371  
7 56     56   30301 use File::Copy ();
  56         122596  
  56         79847  
8              
9             #===============================================================================
10             const type => 'file';
11             field tied_file => undef;
12              
13             #===============================================================================
14             sub file {
15 333     333 1 394 my $self = shift;
16 333         642 bless $self, __PACKAGE__;
17             # should we die here if $self->name is already set and there are args?
18 333 100 100     1904 if (@_ && @_ > 1) {
    100          
19 9         69 $self->name( $self->_spec_class->catfile( @_ ) )
20             } elsif (@_) {
21 304         954 $self->name($_[0])
22             }
23 333         949 return $self->_init;
24             }
25              
26             sub file_handle {
27 0     0 0 0 my $self = shift;
28 0         0 bless $self, __PACKAGE__;
29 0 0       0 $self->_handle(shift) if @_;
30 0         0 return $self->_init;
31             }
32              
33             #===============================================================================
34             sub assert_filepath {
35 4     4 0 5 my $self = shift;
36 4 50       11 my $name = $self->pathname
37             or return;
38 4         6 my $directory;
39 4         8 (undef, $directory) = File::Spec->splitpath($self->pathname);
40 4         25 $self->_assert_dirpath($directory);
41             }
42              
43             sub assert_open_backwards {
44 8     8 0 3 my $self = shift;
45 8 100       16 return if $self->is_open;
46 2         12 require File::ReadBackwards;
47 2         6 my $file_name = $self->pathname;
48 2 50       11 my $io_handle = File::ReadBackwards->new($file_name)
49             or $self->throw("Can't open $file_name for backwards:\n$!");
50 2         121 $self->io_handle($io_handle);
51 2         3 $self->is_open(1);
52             }
53              
54             sub _assert_open {
55 218     218   214 my $self = shift;
56 218 100       433 return if $self->is_open;
57 101 50       384 $self->mode(shift) unless $self->mode;
58 101         203 $self->open;
59             }
60              
61             sub assert_tied_file {
62 6     6 0 9 my $self = shift;
63 6   66     18 return $self->tied_file || do {
64             eval {require Tie::File};
65             $self->throw("Tie::File required for file array operations:\n$@")
66             if $@;
67             my $array_ref = do { my @array; \@array };
68             my $name = $self->pathname;
69             my @options = $self->_rdonly ? (mode => O_RDONLY) : ();
70             push @options, (recsep => $self->separator);
71             tie @$array_ref, 'Tie::File', $name, @options;
72             $self->throw("Can't tie 'Tie::File' to '$name':\n$!")
73             unless tied @$array_ref;
74             $self->tied_file($array_ref);
75             };
76             }
77              
78             sub open {
79 116     116 1 131 my $self = shift;
80 116         242 $self->is_open(1);
81 116 100       388 $self->assert_filepath if $self->_assert;
82 116         162 my ($mode, $perms) = @_;
83 116 100       330 $self->mode($mode) if defined $mode;
84 116 100       288 $self->mode('<') unless defined $self->mode;
85 116 50       294 $self->perms($perms) if defined $perms;
86 116         321 my @args = ($self->mode);
87 116 50       420 push @args, $self->perms if defined $self->perms;
88 116 50 0     349 if (defined $self->pathname) {
    0          
89 116         549 $self->io_handle(IO::File->new);
90 116 100       244 $self->io_handle->open($self->pathname, @args)
91             or $self->throw($self->open_msg);
92             }
93             elsif (defined $self->_handle and
94             not $self->io_handle->opened
95             ) {
96             # XXX Not tested
97 0         0 $self->io_handle->fdopen($self->_handle, @args);
98             }
99 115         7911 $self->set_lock;
100 115         476 $self->_set_binmode;
101             }
102              
103 0     0 1 0 sub exists { -f shift->pathname }
104              
105             my %mode_msg = (
106             '>' => 'output',
107             '<' => 'input',
108             '>>' => 'append',
109             );
110             sub open_msg {
111 1     1 0 43 my $self = shift;
112 1 50       2 my $name = defined $self->pathname
113             ? " '" . $self->pathname . "'"
114             : '';
115 1 50       3 my $direction = defined $mode_msg{$self->mode}
116             ? ' for ' . $mode_msg{$self->mode}
117             : '';
118 1         17 return qq{Can't open file$name$direction:\n$!};
119             }
120              
121             #===============================================================================
122             sub copy {
123 1     1 1 6 my ($self, $new) = @_;
124              
125 1 50       2 File::Copy::copy($self->name, $new)
126             or die "failed to copy $self to $new: $!";
127 1         433 $self->file($new)
128             }
129              
130             sub close {
131 126     126 1 11722 my $self = shift;
132 126 100       276 return unless $self->is_open;
133 120         269 $self->is_open(0);
134 120         237 my $io_handle = $self->io_handle;
135 120         436 $self->unlock;
136 120         242 $self->io_handle(undef);
137 120         282 $self->mode(undef);
138 120 100       349 if (my $tied_file = $self->tied_file) {
139 3 100       16 if (ref($tied_file) eq 'ARRAY') {
140 1         12 untie @$tied_file;
141             }
142             else {
143 2         24 untie %$tied_file;
144             }
145 3         75 $self->tied_file(undef);
146 3         31 return 1;
147             }
148 117 50       692 $io_handle->close(@_)
149             if defined $io_handle;
150 117         3381 return $self;
151             }
152              
153             sub empty {
154 1     1 1 3 my $self = shift;
155 1         3 -z $self->pathname;
156             }
157              
158             sub filepath {
159 1     1 1 2 my $self = shift;
160 1         12 my ($volume, $path) = $self->splitpath;
161 1         49 return File::Spec->catpath($volume, $path, '');
162             }
163              
164             sub getline_backwards {
165 8     8 0 7 my $self = shift;
166 8         11 $self->assert_open_backwards;
167 8         25 return $self->io_handle->readline;
168             }
169              
170             sub getlines_backwards {
171 1     1 0 4 my $self = shift;
172 1         1 my @lines;
173 1         2 while (defined (my $line = $self->getline_backwards)) {
174 3         87 push @lines, $line;
175             }
176 1         12 return @lines;
177             }
178              
179             sub head {
180 2     2 1 3 my $self = shift;
181 2   100     9 my $lines = shift || 10;
182 2         2 my @return;
183 2         5 $self->close;
184              
185             LINES:
186 2         7 while ($lines--) {
187 15 50       44 if (defined (my $l = $self->getline)) {
188 15         47 push @return, $l;
189             }
190             else {
191 0         0 last LINES;
192             }
193             }
194              
195 2         6 $self->close;
196 2 50       31 return wantarray ? @return : join '', @return;
197             }
198              
199             sub tail {
200 0     0 1 0 my $self = shift;
201 0   0     0 my $lines = shift || 10;
202 0         0 my @return;
203 0         0 $self->close;
204 0         0 while ($lines--) {
205 0   0     0 unshift @return, ($self->getline_backwards or last);
206             }
207 0         0 $self->close;
208 0 0       0 return wantarray ? @return : join '', @return;
209             }
210              
211             sub touch {
212 2     2 1 5 my $self = shift;
213 2 100       13 return $self->SUPER::touch(@_)
214             if -e $self->pathname;
215 1 50       9 return $self if $self->is_open;
216 1         10 my $mode = $self->mode;
217 1         4 $self->mode('>>')->open->close;
218 1         4 $self->mode($mode);
219 1         5 return $self;
220             }
221              
222             sub unlink {
223 3     3 1 3326 my $self = shift;
224 3         67 unlink $self->pathname;
225             }
226              
227             #===============================================================================
228             sub _overload_table {
229 63     63   64 my $self = shift;
230             (
231 63         254 $self->SUPER::_overload_table(@_),
232             'file > file' => '_overload_file_to_file',
233             'file < file' => '_overload_file_from_file',
234             '${} file' => '_overload_file_as_scalar',
235             '@{} file' => '_overload_file_as_array',
236             '%{} file' => '_overload_file_as_dbm',
237             )
238             }
239              
240             sub _overload_file_to_file {
241 2     2   13 require File::Copy;
242 2         6 File::Copy::copy($_[1]->pathname, $_[2]->pathname);
243 2         501 $_[2];
244             }
245              
246             sub _overload_file_from_file {
247 2     2   10 require File::Copy;
248 2         6 File::Copy::copy($_[2]->pathname, $_[1]->pathname);
249 2         453 $_[1];
250             }
251              
252             sub _overload_file_as_array {
253 6     6   21 $_[1]->assert_tied_file;
254             }
255              
256             sub _overload_file_as_dbm {
257 5 50   5   24 $_[1]->dbm
258             unless $_[1]->isa('IO::All::DBM');
259 5         13 $_[1]->_assert_open;
260             }
261              
262             sub _overload_file_as_scalar {
263 10     10   69 my $scalar = $_[1]->scalar;
264 10         63 return \$scalar;
265             }
266              
267             1;