File Coverage

blib/lib/Enbld/RcFile.pm
Criterion Covered Total %
statement 89 167 53.2
branch 20 74 27.0
condition 2 6 33.3
subroutine 19 25 76.0
pod 0 9 0.0
total 130 281 46.2


line stmt bran cond sub pod time code
1             package Enbld::RcFile;
2              
3 2     2   10 use strict;
  2         4  
  2         66  
4 2     2   9 use warnings;
  2         4  
  2         45  
5              
6 2     2   11 use autodie;
  2         2  
  2         16  
7 2     2   9923 use File::Spec;
  2         4  
  2         90  
8 2     2   12 use File::Path qw/make_path/;
  2         3  
  2         134  
9 2     2   1435 use File::Temp;
  2         9995  
  2         194  
10 2     2   1204 use File::Copy;
  2         3184  
  2         124  
11              
12 2     2   1780 use Digest::file qw/digest_file_hex/;
  2         5227  
  2         131  
13 2     2   3962 use Digest::SHA qw/sha1_hex/;
  2         15424  
  2         231  
14              
15 2     2   20 use Carp;
  2         5  
  2         6465  
16              
17             require Enbld::Message;
18             require Enbld::Error;
19             require Enbld::Exception;
20              
21             our @cmd_list = qw/load copy set/;
22              
23             sub new {
24 3     3 0 2143 my $class = shift;
25              
26 3         32 my $self = {
27             command => undef,
28             filepath => undef,
29              
30             from => undef,
31              
32             source => undef,
33             url => undef,
34              
35             contents => undef,
36              
37             directory => undef,
38              
39             fullpath => undef,
40             filename => undef,
41              
42             digest => undef,
43              
44             @_,
45             };
46              
47 3         9 bless $self, $class;
48              
49 3         13 $self->_parse_filepath;
50 3         76 $self->_validate;
51              
52 3         19 return $self;
53             }
54              
55             sub do {
56 2     2 0 14 my $self = shift;
57              
58 2 50 33     12 if ( $self->{command} eq 'load' && $self->{from} ) {
59 0         0 $self->{url} = $self->{from};
60             }
61              
62 2 50 33     10 if ( $self->{command} eq 'copy' && $self->{from} ) {
63 0         0 $self->{source} = $self->{from};
64             }
65              
66 2         10 my $cmd = 'do_' . $self->{command};
67 2         13 my $result = $self->$cmd;
68              
69 2         11 return $result;
70             }
71              
72             sub _validate {
73 3     3   9 my $self = shift;
74              
75 3 50       23 _err( "Configuration file's command is not specified." ) unless $self->{command};
76              
77 3 50       14 if ( ! grep { $_ eq $self->{command} } @cmd_list ) {
  9         51  
78 0         0 _err( "'$self->{command}' is invalid command type." );
79             }
80              
81 3 50       12 _err( "Configuration file's path not set." ) unless $self->{filepath};
82              
83 3 50       95 unless ( -d $self->{directory} ) {
84 0         0 make_path( $self->{directory} );
85             }
86             }
87              
88             sub _parse_filepath {
89 3     3   6 my $self = shift;
90              
91 3 50       22 $self->{directory} = $ENV{HOME} unless $self->{directory};
92              
93 3 50       66 $self->{fullpath} = File::Spec->file_name_is_absolute( $self->{filepath} ) ?
94             $self->{filepath} :
95             File::Spec->catfile( $self->{directory}, $self->{filepath} );
96              
97 3         10 my $dirs;
98 3         50 ( undef, $dirs, $self->{filename} ) = File::Spec->splitpath( $self->{fullpath} );
99              
100 3 50       12 if ( ! _check_permission( $dirs )) {
101 0         0 _err( "Please check write permission for $dirs." );
102             }
103              
104 3 100       64 if ( -f $self->{fullpath} ) {
105 2         12 $self->{digest} = digest_file_hex( $self->{fullpath}, 'SHA-1' );
106             }
107              
108 3         425978 return $self->{fullpath};
109             }
110              
111             sub _check_permission {
112 3     3   6 my $dir = shift;
113              
114 3         90 my @list = File::Spec->splitdir( $dir );
115              
116 3         14 while( @list ) {
117 3         23 my $path = File::Spec->catdir( @list );
118              
119 3 50       88 return $path if ( -d -w $path );
120              
121 0         0 pop @list;
122             }
123              
124 0         0 return;
125             }
126              
127             sub do_load {
128 0     0 0 0 my $self = shift;
129              
130 0 0       0 _err( "Download URL is not set." ) unless $self->{url};
131              
132 0         0 _notify( "=====> Load configuration file '$self->{filename}' from '$self->{url}'." );
133              
134 0         0 require Enbld::HTTP;
135 0         0 my $temp = File::Temp->newdir;
136 0         0 my $path = File::Spec->catfile( $temp, $self->{filename} );
137 0         0 my $downloaded = Enbld::HTTP->download( $self->{url}, $path );
138            
139 0 0       0 unless ( -f -T $downloaded ) {
140 0         0 _err( "Configuration file '$self->{filename}' isn't text file." );
141             }
142              
143 0 0       0 if ( $self->{contents} ) {
144 0         0 open my $temphandle, '>>', $downloaded;
145 0         0 print $temphandle $self->{contents};
146 0         0 close $temphandle;
147             }
148              
149 0 0       0 if ( $self->{digest} ) {
150 0         0 my $digest = digest_file_hex( $path, 'SHA-1' );
151              
152 0 0       0 if ( $self->{digest} eq $digest ) {
153 0         0 _notify( "Configuration file not have the necessity for change." );
154 0         0 return;
155             }
156              
157 0         0 my ( undef, $dir, $filename ) = File::Spec->splitpath( $self->{fullpath} );
158              
159 0 0       0 move( $self->{fullpath}, File::Spec->catfile( $dir, $filename . time ) )
160             or _err( $! );
161             }
162              
163 0 0       0 copy( $path, $self->{fullpath} ) or _err( $! );
164              
165 0         0 _notify( "=====> Finish configuration file '$self->{filename}'" );
166              
167 0         0 return $self->{filename};
168             }
169              
170             sub do_set {
171 2     2 0 4 my $self = shift;
172              
173 2 50       9 _err( "Configuration file's contents isn't set." ) unless $self->{contents};
174              
175 2         15 _notify( "=====> Set configuration file '$self->{filename}'" );
176              
177 2         88 my ( undef, $dir, $filename ) = File::Spec->splitpath( $self->{fullpath} );
178              
179 2 100       108 if ( $self->{digest} ) {
180 1 50       188 if ( $self->{digest} eq sha1_hex( $self->{contents}) ) {
181 1         9 _notify( "Configuration file not have the necessity for change." );
182 1         5 return;
183             };
184              
185 0 0       0 move( $self->{fullpath}, File::Spec->catfile( $dir, $filename . time ))
186             or _err( $! );
187             }
188              
189 1         81 make_path( $dir );
190              
191 1         45 open my $fh, '>', $self->{fullpath};
192 1         2275 print $fh $self->{contents};
193 1         6 close $fh;
194              
195 1         1027 _notify( "=====> Finish configuration file '$self->{filename}'" );
196              
197 1         11 return $self->{filename};
198             }
199              
200             sub do_copy {
201 0     0 0 0 my $self = shift;
202              
203 0 0       0 _err( "Configuration file's source path is not set." ) unless $self->{source};
204              
205 0 0       0 unless ( -f -T $self->{source} ) {
206 0         0 _err( "Configuration file '$self->{filename}' isn't text file." );
207             }
208              
209 0         0 _notify( "=====> Copy configuration file '$self->{filename}'" );
210              
211 0         0 my $temp = File::Temp->newdir;
212 0         0 my $path = File::Spec->catfile( $temp, $self->{filename} );
213 0         0 copy( $self->{source}, $path );
214              
215 0 0       0 if ( $self->{contents} ) {
216 0         0 open my $temphandle, '>>', $path;
217 0         0 print $temphandle $self->{contents};
218 0         0 close $temphandle;
219             }
220              
221 0 0       0 if ( $self->{digest} ) {
222 0         0 my ( undef, $dir, $filename ) = File::Spec->splitpath( $self->{fullpath} );
223              
224 0         0 my $digest = digest_file_hex( $path, 'SHA-1' );
225              
226 0 0       0 if ( $self->{digest} eq $digest ) {
227 0         0 _notify( "Configuration file not have the necessity for change." );
228 0         0 return;
229             }
230 0 0       0 move( $self->{fullpath}, File::Spec->catfile( $dir, $filename . time ) )
231             or _err( $! );
232             }
233              
234 0 0       0 copy( $path, $self->{fullpath} ) or _err( $! );
235              
236 0         0 _notify( "=====> Finish configuration file '$self->{filename}'" );
237              
238 0         0 return $self->{filename};
239             }
240              
241             sub filename {
242 6     6 0 20 my $self = shift;
243              
244 6         38 return $self->{filename};
245             }
246              
247             sub filepath {
248 0     0 0 0 my $self = shift;
249              
250 0         0 return $self->{filepath};
251             }
252              
253             sub serialize {
254 1     1 0 3 my $self = shift;
255              
256 1         2 my $serialized;
257              
258 1         4 $serialized->{filepath} = $self->{filepath};
259 1         5 $serialized->{command} = $self->{command};
260              
261 1 50       6 $serialized->{contents} = $self->{contents} if $self->{contents};
262 1 50       6 $serialized->{url} = $self->{url} if $self->{url};
263 1 50       6 $serialized->{source} = $self->{source} if $self->{source};
264              
265 1 50       5 if ( $self->{directory} ne $ENV{HOME} ) {
266 0         0 $serialized->{directory} = $self->{directory};
267             }
268              
269 1         6 return $serialized;
270             }
271              
272             sub DSL {
273 0     0 0 0 my $self = shift;
274              
275 0         0 my @rcfile;
276              
277 0         0 my $str = "conf '" . $self->{filepath} . "' => " . $self->{command} . " {\n";
278              
279 0         0 push @rcfile, $str;
280              
281 0 0       0 if ( $self->{command} eq 'load' ) {
282 0         0 push @rcfile, ' ' . "from '" . $self->{url} . "';\n";
283             }
284              
285 0 0       0 if ( $self->{command} eq 'copy' ) {
286 0         0 push @rcfile, ' ' . "from '" . $self->{source} . "';\n";
287             }
288              
289 0 0       0 if ( $self->{directory} ne $ENV{HOME} ) {
290 0         0 push @rcfile, ' ' . "to '" . $self->{directory} . "';\n";
291             }
292              
293 0 0       0 if ( $self->{contents} ) {
294 0         0 my @contents = split( "\n", $self->{contents} );
295              
296 0         0 foreach my $line ( @contents ) {
297 0         0 push @rcfile, ' ' . "content '" . $line . "';\n";
298             }
299             }
300              
301 0         0 push @rcfile, "};\n";
302              
303 0         0 return \@rcfile;
304             }
305              
306             sub _err {
307 0     0   0 my $err = shift;
308 0         0 my $param = shift;
309              
310 0         0 die( Enbld::Error->new( $err, $param ));
311             }
312              
313             sub _exception {
314 0     0   0 my $exception = shift;
315 0         0 my $param = shift;
316              
317 0         0 croak( Enbld::Exception->new( $exception, $param ));
318             }
319              
320             sub _notify {
321 4     4   11 my $msg = shift;
322              
323 4         40 Enbld::Message->notify( $msg );
324             }
325              
326             1;