File Coverage

blib/lib/Perl/Dist/Machine.pm
Criterion Covered Total %
statement 87 108 80.5
branch 22 36 61.1
condition 2 6 33.3
subroutine 16 17 94.1
pod 0 8 0.0
total 127 175 72.5


line stmt bran cond sub pod time code
1             package Perl::Dist::Machine;
2              
3             =pod
4              
5             =head1 NAME
6              
7             Perl::Dist::Machine - Generate an entire set of related distributions
8              
9             =head1 DESCRIPTION
10              
11             Perl::Dist::Machine is a Perl::Dist multiplexor.
12              
13             It provides the functionality required to generate several
14             variations of a distribution at the same time.
15              
16             Please note the API is still evolving, and as such will remain
17             undocumented for now.
18              
19             However, if you are adventurous and happy to read the source code,
20             it should be pretty clear.
21              
22             =cut
23              
24 1     1   56112 use 5.005;
  1         5  
  1         40  
25 1     1   6 use strict;
  1         1  
  1         29  
26 1     1   6 use Carp 'croak';
  1         2  
  1         50  
27 1     1   885 use File::Copy ();
  1         2668  
  1         27  
28 1     1   993 use Params::Util qw{ _STRING _IDENTIFIER _ARRAY0 _HASH0 _DRIVER };
  1         3132  
  1         104  
29 1     1   1015 use File::HomeDir ();
  1         7100  
  1         28  
30              
31 1     1   10 use vars qw{$VERSION};
  1         2  
  1         45  
32             BEGIN {
33 1     1   20 $VERSION = '1.16';
34             }
35              
36 1         7 use Object::Tiny qw{
37             class
38             output
39             state
40 1     1   824 };
  1         408  
41              
42              
43              
44              
45              
46             #####################################################################
47             # Constructor
48              
49             sub new {
50 1     1 0 736 my $class = shift;
51              
52             # All passed arguments go into the common param pool by default
53 1         12 my $self = bless { @_,
54             dimensions => [ ],
55             options => { },
56             state => undef,
57             eos => 0, # End of State
58             }, $class;
59              
60             # Check params
61 1 50 33     32 unless (
62             _DRIVER($self->class, 'Perl::Dist::Inno') or
63             _DRIVER($self->class, 'Perl::Dist::WiX') ) {
64 0         0 croak("Missing or invalid class param");
65             }
66 1 50       260 unless ( defined $self->output ) {
67 0         0 $self->{output} = File::HomeDir->my_desktop;
68             }
69 1 50       31 unless ( _STRING($self->output) ) {
70 0         0 croak("Missing or invalid output param");
71             }
72 1 50 33     129 unless ( -d $self->output and -w $self->output ) {
73 0         0 my $output = $self->output;
74 0         0 croak("The output directory '$output' does not exist, or is not writable");
75             }
76 1 50       84 if ( _HASH0($self->{common}) ) {
77 1         2 $self->{common} = [ %{ $self->{common} } ];
  1         5  
78             }
79 1 50       7 unless ( _ARRAY0($self->{common}) ) {
80 0         0 croak("Did not provide a common param");
81             }
82              
83 1         4 return $self;
84             }
85              
86             sub common {
87 6     6 0 8 return @{$_[0]->{common}};
  6         21  
88             }
89              
90             sub dimensions {
91 15     15 0 1413 return @{$_[0]->{dimensions}};
  15         51  
92             }
93              
94              
95              
96              
97              
98             #####################################################################
99             # Setup Methods
100              
101             sub add_dimension {
102 2     2 0 4 my $self = shift;
103 2 50       62 my $name = _IDENTIFIER(shift) or croak("Missing or invalid dimension name");
104 2 50       67 if ( defined $self->state ) {
105 0         0 croak("Cannot alter params once iterating");
106             }
107 2 50       25 if ( $self->{options}->{$name} ) {
108 0         0 croak("The dimension '$name' already exists");
109             }
110 2         3 push @{ $self->{dimensions} }, $name;
  2         6  
111 2         7 $self->{options}->{$name} = [ ];
112 2         17 return 1;
113             }
114              
115             sub add_option {
116 5     5 0 10 my $self = shift;
117 5 50       152 my $name = _IDENTIFIER(shift) or croak("Missing or invalid dimension name");
118 5 50       164 if ( defined $self->state ) {
119 0         0 croak("Cannot alter params once iterating");
120             }
121 5 50       37 unless ( $self->{options}->{$name} ) {
122 0         0 croak("The dimension '$name' does not exist");
123             }
124 5         6 push @{ $self->{options}->{$name} }, [ @_ ];
  5         18  
125 5         23 return 1;
126             }
127              
128              
129              
130              
131              
132             #####################################################################
133             # Iterator Methods
134              
135             sub all {
136 1     1 0 3 my $self = shift;
137 1         2 my @objects = ();
138 1         2 while ( 1 ) {
139 7 100       18 my $object = $self->next or last;
140 6         86 push @objects, $object;
141             }
142 1         5 return @objects;
143             }
144              
145             sub next {
146 7     7 0 11 my $self = shift;
147 7 50       20 if ( $self->{eos} ) {
148             # Already at last state
149 0         0 return undef;
150             }
151              
152             # Initialize the iterator if needed
153 7         11 my $options = $self->{options};
154 7         190 my $state = $self->state;
155 7 100       34 if ( $state ) {
156             # Move to the next position
157 6         7 my $found = 0;
158 6         16 foreach my $name ( $self->dimensions ) {
159 9 100       15 unless ( $state->{$name} == $#{ $options->{$name} } ) {
  9         31  
160             # Normal iteration
161 5         7 $state->{$name}++;
162 5         8 $found = 1;
163 5         9 last;
164             }
165              
166             # We've hit the end of a dimension.
167             # Loop the state to the start, so the
168             # next dimension will iterate to the
169             # correct value.
170 4         10 $state->{$name} = 0;
171             }
172 6 100       20 unless ( $found ) {
173 1         3 $self->{eos} = 1;
174 1         6 return undef;
175             }
176             } else {
177             # Initialize to the first position
178 1         4 $state = $self->{state} = { };
179 1         4 foreach my $name ( $self->dimensions ) {
180 2 50       3 unless ( @{ $options->{$name} } ) {
  2         9  
181 0         0 croak("No options for dimension '$name'");
182             }
183 2         6 $state->{$name} = 0;
184             }
185             }
186              
187             # Create the param-set
188 6         15 my @params = $self->common;
189 6         16 foreach my $name ( $self->dimensions ) {
190 12         14 push @params, @{ $options->{$name}->[ $state->{$name} ] };
  12         40  
191             }
192              
193             # Create the object with those params
194 6         168 return $self->class->new( @params );
195             }
196              
197              
198              
199              
200              
201             #####################################################################
202             # Execution Methods
203              
204             sub run {
205 0     0 0   my $self = shift;
206 0           while ( my $dist = $self->next ) {
207 0           $dist->prepare;
208 0           $dist->run;
209              
210             # Copy the output products for this run to the
211             # main output area.
212 0           foreach my $file ( @{$dist->output_file} ) {
  0            
213 0           File::Copy::move( $file, $self->output );
214             }
215              
216             # Flush out the image dir for the next run
217 0           File::Remove::remove(\1, $dist->image_dir);
218             }
219 0           return 1;
220             }
221              
222             1;
223              
224             =pod
225              
226             =head1 SUPPORT
227              
228             Bugs should be reported via the CPAN bug tracker at
229              
230             L
231              
232             For other issues, contact the author.
233              
234             =head1 AUTHOR
235              
236             Adam Kennedy Eadamk@cpan.orgE
237              
238             =head1 COPYRIGHT
239              
240             Copyright 2007 - 2009 Adam Kennedy.
241              
242             This program is free software; you can redistribute
243             it and/or modify it under the same terms as Perl itself.
244              
245             The full text of the license can be found in the
246             LICENSE file included with this module.
247              
248             =cut