File Coverage

blib/lib/Enbld/RcFile.pm
Criterion Covered Total %
statement 86 167 51.5
branch 16 74 21.6
condition 2 6 33.3
subroutine 19 25 76.0
pod 0 9 0.0
total 123 281 43.7


line stmt bran cond sub pod time code
1             package Enbld::RcFile;
2              
3 2     2   6 use strict;
  2         2  
  2         46  
4 2     2   6 use warnings;
  2         1  
  2         41  
5              
6 2     2   8 use autodie;
  2         2  
  2         12  
7 2     2   5743 use File::Spec;
  2         4  
  2         44  
8 2     2   6 use File::Path qw/make_path/;
  2         2  
  2         95  
9 2     2   610 use File::Temp;
  2         6178  
  2         115  
10 2     2   483 use File::Copy;
  2         1669  
  2         97  
11              
12 2     2   796 use Digest::file qw/digest_file_hex/;
  2         2264  
  2         94  
13 2     2   932 use Digest::SHA qw/sha1_hex/;
  2         4002  
  2         125  
14              
15 2     2   10 use Carp;
  2         3  
  2         3575  
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 1440 my $class = shift;
25              
26 3         26 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         4 bless $self, $class;
48              
49 3         9 $self->_parse_filepath;
50 3         7 $self->_validate;
51              
52 3         9 return $self;
53             }
54              
55             sub do {
56 2     2 0 9 my $self = shift;
57              
58 2 0 33     7 if ( $self->{command} eq 'load' && $self->{from} ) {
59 0         0 $self->{url} = $self->{from};
60             }
61              
62 2 0 33     7 if ( $self->{command} eq 'copy' && $self->{from} ) {
63 0         0 $self->{source} = $self->{from};
64             }
65              
66 2         5 my $cmd = 'do_' . $self->{command};
67 2         8 my $result = $self->$cmd;
68              
69 2         7 return $result;
70             }
71              
72             sub _validate {
73 3     3   4 my $self = shift;
74              
75 3 50       13 _err( "Configuration file's command is not specified." ) unless $self->{command};
76              
77 3 50       8 if ( ! grep { $_ eq $self->{command} } @cmd_list ) {
  9         21  
78 0         0 _err( "'$self->{command}' is invalid command type." );
79             }
80              
81 3 50       8 _err( "Configuration file's path not set." ) unless $self->{filepath};
82              
83 3 50       36 unless ( -d $self->{directory} ) {
84 0         0 make_path( $self->{directory} );
85             }
86             }
87              
88             sub _parse_filepath {
89 3     3   4 my $self = shift;
90              
91 3 50       19 $self->{directory} = $ENV{HOME} unless $self->{directory};
92              
93             $self->{fullpath} = File::Spec->file_name_is_absolute( $self->{filepath} ) ?
94             $self->{filepath} :
95 3 50       63 File::Spec->catfile( $self->{directory}, $self->{filepath} );
96              
97 3         7 my $dirs;
98 3         46 ( undef, $dirs, $self->{filename} ) = File::Spec->splitpath( $self->{fullpath} );
99              
100 3 50       8 if ( ! _check_permission( $dirs )) {
101 0         0 _err( "Please check write permission for $dirs." );
102             }
103              
104 3 100       71 if ( -f $self->{fullpath} ) {
105 1         6 $self->{digest} = digest_file_hex( $self->{fullpath}, 'SHA-1' );
106             }
107              
108 3         127 return $self->{fullpath};
109             }
110              
111             sub _check_permission {
112 3     3   4 my $dir = shift;
113              
114 3         21 my @list = File::Spec->splitdir( $dir );
115              
116 3         9 while( @list ) {
117 3         15 my $path = File::Spec->catdir( @list );
118              
119 3 50       59 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 3 my $self = shift;
172              
173 2 50       6 _err( "Configuration file's contents isn't set." ) unless $self->{contents};
174              
175 2         10 _notify( "=====> Set configuration file '$self->{filename}'" );
176              
177 2         30 my ( undef, $dir, $filename ) = File::Spec->splitpath( $self->{fullpath} );
178              
179 2 50       7 if ( $self->{digest} ) {
180 0 0       0 if ( $self->{digest} eq sha1_hex( $self->{contents}) ) {
181 0         0 _notify( "Configuration file not have the necessity for change." );
182 0         0 return;
183             };
184              
185 0 0       0 move( $self->{fullpath}, File::Spec->catfile( $dir, $filename . time ))
186             or _err( $! );
187             }
188              
189 2         92 make_path( $dir );
190              
191 2         10 open my $fh, '>', $self->{fullpath};
192 2         2460 print $fh $self->{contents};
193 2         7 close $fh;
194              
195 2         966 _notify( "=====> Finish configuration file '$self->{filename}'" );
196              
197 2         13 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 9 my $self = shift;
243              
244 6         21 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 2 my $self = shift;
255              
256 1         3 my $serialized;
257              
258 1         4 $serialized->{filepath} = $self->{filepath};
259 1         3 $serialized->{command} = $self->{command};
260              
261 1 50       5 $serialized->{contents} = $self->{contents} if $self->{contents};
262 1 50       4 $serialized->{url} = $self->{url} if $self->{url};
263 1 50       4 $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         5 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   7 my $msg = shift;
322              
323 4         25 Enbld::Message->notify( $msg );
324             }
325              
326             1;