File Coverage

blib/lib/Test/Inline/IO/File.pm
Criterion Covered Total %
statement 55 57 96.4
branch 18 28 64.2
condition 4 6 66.6
subroutine 13 14 92.8
pod 7 9 77.7
total 97 114 85.0


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