File Coverage

blib/lib/Enbld/Target.pm
Criterion Covered Total %
statement 260 302 86.0
branch 63 94 67.0
condition 4 6 66.6
subroutine 47 49 95.9
pod 0 11 0.0
total 374 462 80.9


line stmt bran cond sub pod time code
1             package Enbld::Target;
2              
3 2     2   546 use strict;
  2         2  
  2         46  
4 2     2   6 use warnings;
  2         2  
  2         41  
5              
6 2     2   6 use Carp;
  2         1  
  2         89  
7              
8 2     2   788 use version;
  2         2973  
  2         7  
9              
10 2     2   116 use File::Spec;
  2         3  
  2         45  
11 2     2   6 use File::Path qw/make_path remove_tree/;
  2         2  
  2         100  
12 2     2   6 use File::Find;
  2         2  
  2         82  
13 2     2   877 use File::Copy::Recursive qw/rcopy/;
  2         6870  
  2         100  
14 2     2   389 use autodie;
  2         11160  
  2         13  
15 2     2   6706 use List::Util qw/first/;
  2         3  
  2         6354  
16              
17             require Enbld::Definition;
18             require Enbld::Feature;
19             require Enbld::Condition;
20             require Enbld::Message;
21             require Enbld::Home;
22             require Enbld::HTTP;
23             require Enbld::Target::Symlink;
24             require Enbld::Error;
25             require Enbld::Deployed;
26              
27             sub new {
28 47     47 0 1728 my ( $class, $name, $config ) = @_;
29              
30 47         382 my $self = {
31             name => $name,
32             config => $config,
33             attributes => undef,
34             build => undef,
35             install => undef,
36             PATH => undef,
37             conditions => undef,
38             };
39              
40 47         115 bless $self, $class;
41              
42 47         179 $self->_set_config;
43 47         116 $self->_set_attributes;
44 46         322 $self->_set_PATH;
45              
46 46         250 return $self;
47             }
48              
49             sub install {
50 14     14 0 18 my $self = shift;
51            
52 14 100       38 if ( ! $self->_is_install_ok ) {
53 1         13 die( Enbld::Error->new( "'$self->{name}' is already installed." ) );
54             }
55              
56 13         109 my $condition = Enbld::Condition->new;
57              
58 13         55 $self->{attributes}->add( 'VersionCondition', $condition->version );
59              
60 13         55 $self->_build( $condition );
61              
62 12         142 return $self->{config};
63             }
64              
65             sub _is_install_ok {
66 14     14   28 my $self = shift;
67              
68 14 100       71 return 1 if Enbld::Feature->is_force_install;
69 13 100       52 return if $self->is_installed;
70 12         33 return 1;
71             }
72              
73             sub deploy {
74 1     1 0 4 my $self = shift;
75              
76 1         7 my $condition = Enbld::Condition->new;
77              
78 1         6 $self->{attributes}->add( 'VersionCondition', $condition->version );
79              
80 1         6 $self->_build_to_deploy( $condition );
81              
82 1         10 return $self->{config};
83             }
84              
85             sub install_declared {
86 14     14 0 38 my ( $self, $declared_conditions ) = @_;
87              
88             $self->{attributes}->add(
89             'VersionCondition',
90             $declared_conditions->{$self->{name}}{version}
91 14         74 );
92              
93             return unless $self->_is_install_declared_ok(
94             $declared_conditions->{$self->{name}}
95 14 100       59 );
96              
97 13         22 $self->{conditions} = $declared_conditions;
98              
99 13         69 $self->_build( $declared_conditions->{$self->{name}} );
100              
101 13         92 return $self->{config};
102             }
103              
104             sub deploy_declared {
105 1     1 0 3 my ( $self, $declared_conditions ) = @_;
106              
107             $self->{attributes}->add(
108             'VersionCondition',
109             $declared_conditions->{$self->{name}}{version}
110 1         8 );
111              
112 1         2 $self->{conditions} = $declared_conditions;
113              
114 1         6 $self->_build_to_deploy( $declared_conditions->{$self->{name}} );
115              
116 1         10 return $self->{config};
117             }
118              
119             sub _is_install_declared_ok {
120 14     14   25 my ( $self, $condition ) = @_;
121              
122 14 100       59 return 1 if Enbld::Feature->is_force_install;
123 13 100       52 return 1 unless $self->{config}->enabled;
124 3 100       15 return 1 unless $condition->is_equal_to( $self->{config}->condition );
125 1 50       6 return if $self->{config}->enabled eq $self->{attributes}->Version;
126              
127 0         0 return 1;
128             }
129              
130             sub upgrade {
131 3     3 0 7 my $self = shift;
132              
133 3 100       18 if ( ! $self->is_installed ) {
134 1         19 die( Enbld::Error->new( "'$self->{name}' is not installed yet." ) );
135             }
136              
137             $self->{attributes}->add(
138             'VersionCondition',
139             $self->{config}->condition->version
140 2         16 );
141              
142 2         15 my $current = $self->{attributes}->Version;
143 2         11 my $enabled = $self->{config}->enabled;
144              
145 2         11 my $VersionList = $self->{attributes}->SortedVersionList;
146              
147             my $index_current =
148 2     4   16 first { ${ $VersionList }[$_] eq $current } 0..$#{ $VersionList };
  4         5  
  4         11  
  2         17  
149              
150             my $index_enabled =
151 2     3   13 first { ${ $VersionList }[$_] eq $enabled } 0..$#{ $VersionList };
  3         4  
  3         5  
  2         6  
152              
153 2 100       8 if ( $index_current <= $index_enabled ) {
154 1         12 die( Enbld::Error->new( "'$self->{name}' is up to date." ) );
155             }
156              
157 1         10 $self->_build( $self->{config}->condition );
158              
159 1         14 return $self->{config};
160             }
161              
162             sub off {
163 2     2 0 8 my $self = shift;
164              
165 2 100       12 if ( ! $self->is_installed ) {
166 1         11 die( Enbld::Error->new( "'$self->{name}' is not installed yet." ) );
167             }
168              
169 1         11 $self->_drop;
170              
171 1         7 $self->{config}->drop_enabled;
172              
173 1         4 return $self->{config};
174             }
175              
176             sub rehash {
177 0     0 0 0 my $self = shift;
178              
179 0 0       0 if ( ! $self->is_installed ) {
180 0         0 die( Enbld::Error->new( "'$self->{name}' isn't installed yet." ) );
181             }
182              
183 0         0 $self->_switch( $self->{config}->enabled );
184              
185 0         0 return $self->{config};
186             }
187              
188             sub use {
189 4     4 0 16 my ( $self, $version ) = @_;
190              
191 4 50       17 if ( ! $self->{config}->installed ) {
192 0         0 die( Enbld::Error->new( "'$self->{name}' isn't installed yet." ) );
193             }
194              
195 4         25 my $form = $self->{attributes}->VersionForm;
196 4 100       37 if ( $version !~ /^$form$/ ) {
197 1         8 die( Enbld::Error->new( "'$version' is not valid version form." ) );
198             }
199              
200 3 100 66     15 if ( $self->{config}->enabled && $self->{config}->enabled eq $version ) {
201 1         7 die( Enbld::Error->new( "'$version' is current enabled version." ) );
202             }
203              
204 2 100       13 if ( ! $self->{config}->is_installed_version( $version ) ) {
205 1         6 die( Enbld::Error->new( "'$version' isn't installed yet" ) );
206             }
207              
208 1         14 $self->_switch( $version );
209              
210 1         7 return $self->{config};
211             }
212              
213             sub is_installed {
214 22     22 0 45 my $self = shift;
215              
216 22         110 return $self->{config}->enabled;
217             }
218              
219             sub is_outdated {
220 3     3 0 15 my $self = shift;
221              
222 3 100       16 return unless ( $self->{config}->enabled );
223              
224             $self->{attributes}->add(
225             'VersionCondition', $self->{config}->condition->version
226 2         19 );
227              
228 2         15 my $current = $self->{attributes}->Version;
229 2         11 my $enabled = $self->{config}->enabled;
230              
231 2         14 my $VersionList = $self->{attributes}->SortedVersionList;
232              
233             my $index_current =
234 2     4   23 first { ${ $VersionList }[$_] eq $current } 0..$#{ $VersionList };
  4         5  
  4         7  
  2         13  
235              
236             my $index_enabled =
237 2     3   13 first { ${ $VersionList }[$_] eq $enabled } 0..$#{ $VersionList };
  3         4  
  3         5  
  2         7  
238              
239 2 100       12 if ( $index_current > $index_enabled ) {
240 1         12 return $current;
241             }
242              
243 1         14 return;
244             }
245              
246             sub _set_config {
247 47     47   62 my $self = shift;
248              
249 47 100       169 if ( ! $self->{config} ) {
250 27         473 require Enbld::Config;
251 27         192 $self->{config} = Enbld::Config->new( name => $self->{name} );
252             }
253             }
254              
255             sub _set_attributes {
256 47     47   59 my $self = shift;
257              
258 47         380 $self->{attributes} = Enbld::Definition->new( $self->{name} )->parse;
259             }
260              
261             sub _set_PATH {
262 46     46   69 my $self = shift;
263              
264 46         279 my $path = File::Spec->catdir( Enbld::Home->install_path, 'bin' );
265              
266 46         226 $self->{PATH} = $path . ':' . $ENV{PATH};
267             }
268              
269             sub _switch {
270 1     1   5 my ( $self, $version ) = @_;
271              
272             my $path = File::Spec->catdir(
273             Enbld::Home->depository,
274             $self->{attributes}->DistName
275 1         14 );
276              
277 1         11 my $new = File::Spec->catdir( $path, $version );
278              
279 1         9 Enbld::Target::Symlink->delete_symlink( $path );
280 1         11 Enbld::Target::Symlink->create_symlink( $new );
281              
282             $self->{config}->set_enabled(
283             $version,
284 1         15 $self->{config}->condition( $version ),
285             );
286             }
287              
288             sub _drop {
289 1     1   6 my $self = shift;
290              
291             my $path = File::Spec->catdir(
292             Enbld::Home->depository,
293             $self->{attributes}->DistName,
294 1         13 );
295              
296 1         17 Enbld::Target::Symlink->delete_symlink( $path );
297              
298 1         9 $self->{config}->drop_enabled;
299             }
300              
301             sub _build {
302 27     27   49 my ( $self, $condition ) = @_;
303              
304 27         225 Enbld::Message->notify( "=====> Start building target '$self->{name}'." );
305              
306 27         215 local $ENV{PATH} = $self->{PATH};
307              
308 27         104 $self->_solve_dependencies;
309              
310 27         163 $self->_setup_install_directory;
311 27         80 $self->_exec_build_command( $condition );
312              
313 26 50       463 if ( $condition->modules ) {
314 0         0 $self->_install_module( $condition );
315             }
316              
317 26         150 $self->_postbuild;
318              
319 26         146 my $finish_msg = "=====> Finish building target '$self->{name}'.";
320 26         322 Enbld::Message->notify( $finish_msg );
321              
322 26         256 $self->{config}->set_enabled( $self->{attributes}->Version, $condition );
323             }
324              
325             sub _build_to_deploy {
326 2     2   7 my ( $self, $condition ) = @_;
327              
328 2         16 Enbld::Message->notify( "=====> Start building target '$self->{name}'." );
329              
330 2         14 local $ENV{PATH} = $self->{PATH};
331              
332 2         9 $self->_solve_dependencies_to_deploy;
333              
334 2         13 $self->{install} = Enbld::Home->deploy_path;
335              
336 2         5 $self->_exec_build_command( $condition );
337              
338 2 50       47 if ( $condition->modules ) {
339 0         0 $self->_install_module( $condition );
340             }
341              
342 2         15 my $finish_msg = "=====> Finish building target '$self->{name}'.";
343 2         38 Enbld::Message->notify( $finish_msg );
344              
345 2         29 $self->{config}->set_enabled( $self->{attributes}->Version, $condition );
346             }
347              
348             sub _exec_build_command {
349 29     29   35 my $self = shift;
350 29         21 my $condition = shift;
351              
352 29         113 $self->_setup_build_directory;
353 29         234 chdir $self->{build};
354              
355 29         3059 $self->_prebuild;
356              
357 29 50       711 $self->_configure( $condition ) if $self->{attributes}->CommandConfigure;
358 28 50       1121 $self->_make if $self->{attributes}->CommandMake;
359              
360 28 100 66     616 if ( $condition->make_test or Enbld::Feature->is_make_test_all ) {
361 1         24 $self->_test;
362             }
363              
364 28 50       846 $self->_install if $self->{attributes}->CommandInstall;
365             }
366              
367             sub _solve_dependencies {
368 27     27   46 my $self = shift;
369              
370 27 100       35 return if ( ! @{ $self->{attributes}->Dependencies } );
  27         191  
371              
372 3         20 Enbld::Message->notify( "=====> Found dependencies." );
373              
374 3         17 require Enbld::App::Configuration;
375              
376 3         7 foreach my $dependency ( @{ $self->{attributes}->Dependencies } ) {
  3         21  
377              
378 3         21 Enbld::Message->notify( "--> Dependency '$dependency'." );
379              
380 3         32 my $config = Enbld::App::Configuration->search_config( $dependency );
381 3         19 my $target = Enbld::Target->new( $dependency, $config );
382              
383 3 100       14 if ( $target->is_installed ) {
384 1         5 my $installed_msg = "--> $dependency is already installed.";
385 1         7 Enbld::Message->notify( $installed_msg );
386 1         6 next;
387             }
388              
389 2         14 Enbld::Message->notify( "--> $dependency is not installed yet." );
390              
391             my $condition = $self->{conditions}{$dependency} ?
392 2 100       13 $self->{conditions}{$dependency} : undef;
393              
394 2         4 my $installed;
395 2 100       6 if ( $condition ) {
396 1         7 $installed = $target->install_declared( $self->{conditions} );
397             } else {
398 1         7 $installed = $target->install;
399             }
400            
401 2         27 Enbld::App::Configuration->set_config( $installed );
402             }
403             }
404              
405             sub _solve_dependencies_to_deploy {
406 2     2   5 my $self = shift;
407              
408 2 50       5 return if ( ! @{ $self->{attributes}->Dependencies } );
  2         12  
409              
410 0         0 Enbld::Message->notify( "=====> Found dependencies." );
411              
412 0         0 foreach my $dependency ( @{ $self->{attributes}->Dependencies } ) {
  0         0  
413              
414 0 0       0 next if ( Enbld::Deployed->is_deployed( $dependency ));
415              
416 0         0 Enbld::Message->notify( "--> Dependency '$dependency'." );
417 0         0 Enbld::Message->notify( "--> $dependency is not installed yet." );
418            
419 0         0 my $target = Enbld::Target->new( $dependency );
420              
421             my $condition = $self->{conditions}{$dependency} ?
422 0 0       0 $self->{conditions}{$dependency} : undef;
423              
424 0         0 my $installed;
425 0 0       0 if ( $condition ) {
426 0         0 $installed = $target->deploy_declared( $self->{conditions} );
427             } else {
428 0         0 $installed = $target->deploy;
429             }
430              
431 0         0 Enbld::Deployed->add( $installed );
432             }
433             }
434              
435             sub _prebuild {
436 29     29   50 my $self = shift;
437              
438 29 50       256 $self->_apply_patchfiles if $self->{attributes}->PatchFiles;
439             }
440              
441             sub _configure {
442 29     29   79 my $self = shift;
443 29         59 my $condition = shift;
444              
445 29 50       157 return $self unless $self->{attributes}->CommandConfigure;
446              
447 29         51 my $configure;
448              
449 29         128 $configure = $self->{attributes}->CommandConfigure . ' ';
450 29         152 $configure .= $self->{attributes}->Prefix . $self->{install};
451              
452 29 50       180 if( $self->{attributes}->AdditionalArgument ) {
453 0         0 $configure .= ' ' . $self->{attributes}->AdditionalArgument;
454             }
455              
456 29 50       211 if ( $condition->arguments ) {
457 0         0 $configure .= ' ' . $condition->arguments;
458             }
459              
460 29         98 $self->_exec( $configure );
461             }
462              
463             sub _make {
464 28     28   59 my $self = shift;
465              
466 28 50       205 if ( $self->{attributes}->CommandConfigure ) {
467 28         164 $self->_exec( $self->{attributes}->CommandMake );
468 28         297 return $self;
469             }
470              
471             # this code for tree command...tree don't has configure
472 0         0 my $args = $self->{attributes}->Prefix . $self->{install};
473              
474 0 0       0 if ( $self->{attributes}->AdditionalArgument ) {
475 0         0 $args .= ' ' . $self->{attributes}->AdditionalArgument;
476             }
477              
478 0         0 $self->_exec( $self->{attributes}->CommandMake . ' ' . $args );
479              
480 0         0 return $self;
481             }
482              
483             sub _test {
484 1     1   8 my $self = shift;
485              
486 1 50       61 return $self unless $self->{attributes}->CommandTest;
487              
488 1         13 $self->_exec( $self->{attributes}->CommandTest );
489             }
490              
491             sub _install {
492 28     28   56 my $self = shift;
493              
494 28 50       163 if ( $self->{attributes}->CommandConfigure ) {
495 28         138 $self->_exec( $self->{attributes}->CommandInstall );
496 28         281 return $self;
497             }
498              
499 0         0 my $args = $self->{attributes}->Prefix . $self->{install};
500              
501 0 0       0 if ( $self->{attributes}->AdditionalArgument ) {
502 0         0 $args .= ' ' . $self->{attributes}->AdditionalArgument;
503             }
504              
505 0         0 $self->_exec( $self->{attributes}->CommandInstall . ' ' . $args );
506              
507 0         0 return $self;
508             }
509              
510             sub _install_module {
511 0     0   0 my ( $self, $condition ) = @_;
512              
513 0         0 require Enbld::Module;
514             my $module = Enbld::Module->new(
515             name => $self->{name},
516             path => $self->{install},
517 0         0 );
518              
519 0         0 $module->install( $condition->modules );
520             }
521              
522             sub _postbuild {
523 26     26   70 my $self = shift;
524              
525 26         102 $self->_copy_files;
526              
527             my $path = File::Spec->catdir(
528             Enbld::Home->depository,
529             $self->{attributes}->DistName,
530 26         618 );
531              
532 26         389 Enbld::Target::Symlink->delete_symlink( $path );
533 26         195 Enbld::Target::Symlink->create_symlink( $self->{install} );
534             }
535              
536             sub _copy_files {
537 26     26   45 my $self = shift;
538              
539 26 50       530 return $self unless ( my $dirs = $self->{attributes}->CopyFiles );
540              
541 26         54 for my $dir ( @{ $dirs } ) {
  26         136  
542             rcopy(
543             File::Spec->catdir( $self->{build}, $dir ),
544 0         0 File::Spec->catdir( $self->{install}, $dir )
545             );
546             }
547              
548             }
549              
550             sub _exec {
551 86     86   162 my ( $self, $cmd ) = @_;
552              
553 86         1164 require Enbld::Logger;
554 86         1224 my $logfile = Enbld::Logger->logfile;
555              
556 86         1188 Enbld::Message->notify( "--> $cmd" );
557              
558 86         19268247 system( "LANG=C;$cmd >> $logfile 2>&1" );
559              
560 86 100       2573 return $self unless $?;
561              
562 1 50       30 if ( $? == -1 ) {
    50          
563 0         0 die( Enbld::Error->new( "Failed to execute:$cmd" ));
564             } elsif ( $? & 127 ) {
565 0         0 my $err = "Child died with signal:$cmd";
566 0         0 die( Enbld::Error->new( $err ));
567             } else {
568 1         16 my $err = "Build fail.Command:$cmd return code:" . ( $? >> 8 );
569 1         25 die( Enbld::Error->new( $err ));
570             }
571             }
572              
573             sub _apply_patchfiles {
574 29     29   46 my $self = shift;
575              
576 29         143 my $patchfiles = $self->{attributes}->PatchFiles;
577              
578 29         194 require Enbld::HTTP;
579 29         114 require Enbld::Message;
580 29         74 require Enbld::Logger;
581 29         220 my $logfile = Enbld::Logger->logfile;
582 29         50 foreach my $patchfile ( @{ $patchfiles } ) {
  29         85  
583 25         135 my @parse = split( /\//, $patchfile );
584 25         276 my $path = File::Spec->catfile( $self->{build}, $parse[-1] );
585              
586 25         178 Enbld::HTTP->download( $patchfile, $path );
587 25         312 Enbld::Message->notify( "--> Apply patch $parse[-1]." );
588              
589 25         106904 system( "patch -p0 < $path >> $logfile 2>&1" );
590             }
591             }
592              
593             sub _setup_build_directory {
594 29     29   38 my $self = shift;
595            
596             my $path = File::Spec->catfile(
597             Enbld::Home->dists,
598             $self->{attributes}->Filename
599 29         158 );
600              
601             my $archivefile =
602 29         136 Enbld::HTTP->download_archivefile( $self->{attributes}->URL, $path );
603              
604 29         207 my $build = $archivefile->extract( Enbld::Home->build );
605              
606 29         163 return ( $self->{build} = $build );
607             }
608              
609             sub _setup_install_directory {
610 27     27   36 my $self = shift;
611            
612             my $depository = File::Spec->catdir(
613             Enbld::Home->depository,
614             $self->{attributes}->DistName,
615             $self->{attributes}->Version,
616 27         224 );
617              
618 27 50       690 remove_tree( $depository ) if ( -d $depository );
619              
620 27         63 return ( $self->{install} = $depository );
621             }
622              
623             1;