File Coverage

blib/lib/Test/Inline/IO/File.pm
Criterion Covered Total %
statement 59 61 96.7
branch 18 28 64.2
condition 4 6 66.6
subroutine 15 16 93.7
pod 7 9 77.7
total 103 120 85.8


line stmt bran cond sub pod time code
1             package Test::Inline::IO::File;
2              
3             =pod
4              
5             =head1 NAME
6              
7             Test::Inline::IO::File - Test::Inline Local Filesystem IO Handler
8              
9             =head1 DESCRIPTION
10              
11             B is the default IO handler for L.
12              
13             L 2.0 was conceived in an enterprise setting, and retains
14             the flexibilty, power, and bulk that this created, although for most
15             users the power and complexity that is available is largely hidden away
16             under multiple layers of sensible defaults.
17              
18             The intent with the C and C parameters is to
19             allow L to be able to pull source data from anywhere, and
20             write the resulting test scripts to anywhere.
21              
22             Until a more powerful pure-OO file-system API comes along, this module
23             serves as a minimalist implementation of the subset of functionality
24             that L needs in order to work.
25              
26             An alternative IO Handler class need not subclass this one (although it
27             is recommended), merely implement the same interface, taking whatever
28             alternative arguments to the C constructor that it wishes.
29              
30             All methods in this class are provided with unix-style paths, and should do
31             the translating to the underlying filesystem themselves if required.
32              
33             =head1 METHODS
34              
35             =cut
36              
37 12     12   1292 use strict;
  12         22  
  12         442  
38 12     12   62 use File::Spec ();
  12         21  
  12         161  
39 12     12   10530 use File::chmod ();
  12         38795  
  12         285  
40 12     12   8709 use File::Remove ();
  12         24360  
  12         286  
41              
42 12     12   112 use vars qw{$VERSION};
  12         23  
  12         555  
43             BEGIN {
44 12     12   8965 $VERSION = '2.213';
45             }
46              
47              
48              
49              
50              
51             #####################################################################
52             # Constructor and Accessors
53              
54             =pod
55              
56             =head2 new
57              
58             # Simplified usage
59             $io_handler = Test::Inline::IO::File->new( $path );
60            
61             # Full key/value usage
62             $io_handler = Test::Inline::IO::File->new(
63             path => $path,
64             readonly => 1,
65             );
66              
67             The C constructor takes a root path on the local filesystem
68             and returns a new C object to that
69             location.
70              
71             =cut
72              
73             sub new {
74 35     35 1 988 my $class = shift;
75 35         87 my @params = @_;
76 35 100       103 if ( @params < 2 ) {
77 18 50       93 my $path = defined $_[0] ? shift : File::Spec->curdir;
78 18         55 @params = ( path => $path );
79             }
80              
81             # Create the object
82 35         143 my $self = bless { @params }, $class;
83              
84             # Apply defaults
85 35         140 $self->{readonly} = !! $self->{readonly};
86              
87 35         150 return $self;
88             }
89              
90             sub path {
91 0     0 0 0 $_[0]->{path};
92             }
93              
94             sub readonly {
95 18     18 0 100 $_[0]->{readonly};
96             }
97              
98             # Resolve the full path for any file
99             sub _path {
100 66     66   755 my $self = shift;
101 66 50       200 my $file = defined $_[0] ? shift : return undef;
102 66         915 File::Spec->catfile( $self->{path}, $file );
103             }
104              
105              
106              
107              
108              
109             #####################################################################
110             # Filesystem API
111              
112             =pod
113              
114             =head2 exists_file $file
115              
116             The C method checks to see if a particular file currently
117             exists in the input handler.
118              
119             Returns true if it exists, or false if not.
120              
121             =cut
122              
123             sub exists_file {
124 17     17 1 539 my $self = shift;
125 17 50       57 my $file = $self->_path(shift) or return undef;
126 17         623 !! -f $file;
127             }
128              
129             =pod
130              
131             =head2 exists_dir $dir
132              
133             The C method checks to see if a particular directory currently
134             exists in the input handler.
135              
136             Returns true if it exists, or false if not.
137              
138             =cut
139              
140             sub exists_dir {
141 6     6 1 18 my $self = shift;
142 6 50       20 my $dir = $self->_path(shift) or return undef;
143 6         144 !! -d $dir;
144             }
145              
146             =pod
147              
148             =head2 read $file
149              
150             The C method reads in the entire contents of a single file,
151             returning it as a reference to a SCALAR. It also localises the
152             newlines as it does this, so files from different operating
153             systems should read as you expect.
154              
155             Returns a SCALAR reference, or C on error.
156              
157             =cut
158              
159             sub read {
160 21     21 1 1747 my $self = shift;
161 21 50       72 my $file = $self->_path(shift) or return undef;
162 21         9745 require File::Flat;
163 21 100       105259 my $content = File::Flat->slurp($file) or return undef;
164 20         8562 $$content =~ s/\015{1,2}\012|\015|\012/\n/g;
165 20         162 $content;
166             }
167              
168             =pod
169              
170             =head2 write $file, $content
171              
172             The C method writes a string to a file in one hit, creating
173             it and it's path if needed.
174              
175             =cut
176              
177             sub write {
178 18     18 1 27 my $self = shift;
179 18 50       41 my $file = $self->_path(shift) or return undef;
180 18 50 66     363 if ( -f $file and ! -w $file ) {
181 0 0       0 File::Remove::remove($file) or return undef;
182              
183             }
184 18         117 require File::Flat;
185 18         109 my $rv = File::Flat->write( $file, @_ );
186 18 100 66     11270 if ( $rv and $self->readonly ) {
187 8         25 File::chmod::symchmod('a-w', $file);
188             }
189 18         7170 return $rv;
190             }
191              
192             =pod
193              
194             =head2 class_file $class
195              
196             Assuming your input FileHandler is pointing at the root directory
197             of a lib path (meaning that My::Module will be located at My/Module.pm
198             within it) the C method will take a class name, and check to see
199             if the file for that class exists in the FileHandler.
200              
201             Returns a reference to an ARRAY containing the filename if it exists,
202             or C on error.
203              
204             =cut
205              
206             sub class_file {
207 2     2 1 5 my $self = shift;
208 2 50       7 my $_class = defined $_[0] ? shift : return undef;
209 2         33 my $file = File::Spec->catfile( split /(?:::|')/, $_class ) . '.pm';
210 2 100       8 $self->exists_file($file) and [ $file ];
211             }
212              
213             =pod
214              
215             =head2 find $class
216              
217             The C method takes as argument a directory root class, and then scans within
218             the input FileHandler to find all files contained in that class or any
219             other classes under it's namespace.
220              
221             Returns a reference to an ARRAY containing all the files within the class,
222             or C on error.
223              
224             =cut
225              
226             sub find {
227 5     5 1 12 my $self = shift;
228 5 100       22 my $dir = $self->exists_dir($_[0]) ? shift : return undef;
229              
230             # Search within the path
231 4         3107 require File::Find::Rule;
232 4         26659 my @files = File::Find::Rule->file
233             ->name('*.pm')
234             ->relative
235             ->in( $self->_path($dir) );
236 4         4394 @files = map { File::Spec->catfile( $dir, $_ ) } sort @files;
  17         155  
237 4         76 return \@files;
238             }
239              
240             1;
241              
242             =pod
243              
244             =head1 TO DO
245              
246             - Convert to using L objects, once they exist
247              
248             =head1 SUPPORT
249              
250             See the main L section.
251              
252             =head1 AUTHOR
253              
254             Adam Kennedy Eadamk@cpan.orgE, L
255              
256             =head1 COPYRIGHT
257              
258             Copyright 2004 - 2013 Adam Kennedy.
259              
260             This program is free software; you can redistribute
261             it and/or modify it under the same terms as Perl itself.
262              
263             The full text of the license can be found in the
264             LICENSE file included with this module.
265              
266             =cut