File Coverage

blib/lib/Alien/Build/CommandSequence.pm
Criterion Covered Total %
statement 92 93 98.9
branch 32 36 88.8
condition 6 6 100.0
subroutine 15 15 100.0
pod 3 3 100.0
total 148 153 96.7


line stmt bran cond sub pod time code
1             package Alien::Build::CommandSequence;
2              
3 9     9   230833 use strict;
  9         27  
  9         315  
4 9     9   53 use warnings;
  9         23  
  9         260  
5 9     9   206 use 5.008004;
  9         35  
6 9     9   2605 use Text::ParseWords qw( shellwords );
  9         7350  
  9         658  
7 9     9   614 use Capture::Tiny qw( capture );
  9         27004  
  9         12149  
8              
9             # ABSTRACT: Alien::Build command sequence
10             our $VERSION = '2.45'; # VERSION
11              
12              
13             sub new
14             {
15 68     68 1 47162 my($class, @commands) = @_;
16 68         270 my $self = bless {
17             commands => \@commands,
18             }, $class;
19 68         236 $self;
20             }
21              
22              
23             sub apply_requirements
24             {
25 57     57 1 153 my($self, $meta, $phase) = @_;
26 57         219 my $intr = $meta->interpolator;
27 57         122 foreach my $command (@{ $self->{commands} })
  57         225  
28             {
29 103 100       246 next if ref $command eq 'CODE';
30 94 100       172 if(ref $command eq 'ARRAY')
31             {
32 47         69 foreach my $arg (@$command)
33             {
34 175 100       316 next if ref $arg eq 'CODE';
35 152         327 $meta->add_requires($phase, $intr->requires($arg))
36             }
37             }
38             else
39             {
40 47         183 $meta->add_requires($phase, $intr->requires($command));
41             }
42             }
43 57         129 $self;
44             }
45              
46             my %built_in = (
47              
48             cd => sub {
49             my(undef, $dir) = @_;
50             if(!defined $dir)
51             {
52             die "undef passed to cd";
53             }
54             elsif(-d $dir)
55             {
56             chdir($dir) || die "unable to cd $dir $!";
57             }
58             else
59             {
60             die "unable to cd $dir, does not exist";
61             }
62             },
63              
64             );
65              
66             sub _run_list
67             {
68 12     12   43 my($build, @cmd) = @_;
69 12         162 $build->log("+ @cmd");
70 12 100       100 return $built_in{$cmd[0]}->(@cmd) if $built_in{$cmd[0]};
71 11         19134 system @cmd;
72 11 100       34250 die "external command failed" if $?;
73             }
74              
75             sub _run_string
76             {
77 7     7   29 my($build, $cmd) = @_;
78 7         150 $build->log("+ $cmd");
79              
80             {
81 7         30 my $cmd = $cmd;
  7         28  
82 7 50       69 $cmd =~ s{\\}{\\\\}g if $^O eq 'MSWin32';
83 7         55 my @cmd = shellwords($cmd);
84 7 100       1328 return $built_in{$cmd[0]}->(@cmd) if $built_in{$cmd[0]};
85             }
86              
87 6         9395 system $cmd;
88 6 100       2854 die "external command failed" if $?;
89             }
90              
91             sub _run_with_code
92             {
93 6     6   37 my($build, @cmd) = @_;
94 6         22 my $code = pop @cmd;
95 6         87 $build->log("+ @cmd");
96 6         49 my %args = ( command => \@cmd );
97              
98 6 100       39 if($built_in{$cmd[0]})
99             {
100 1         8 my $error;
101             ($args{out}, $args{err}, $error) = capture {
102 1     1   2046 eval { $built_in{$cmd[0]}->(@cmd) };
  1         15  
103 1         12 $@;
104 1         162 };
105 1 50       1148 $args{exit} = $error eq '' ? 0 : 2;
106 1         14 $args{builtin} = 1;
107             }
108             else
109             {
110             ($args{out}, $args{err}, $args{exit}) = capture {
111 5     5   5305 system @cmd; $?
  5         439  
112 5         158 };
113             }
114 6         4030 $build->log("[output consumed by Alien::Build recipe]");
115 6         49 $code->($build, \%args);
116             }
117              
118              
119             sub _apply
120             {
121 9     9   69 my($where, $prop, $value) = @_;
122 9 100       45 if($where =~ /^(.*?)\.(.*?)$/)
123             {
124 6         22 _apply($2, $prop->{$1}, $value);
125             }
126             else
127             {
128 3         42 $prop->{$where} = $value;
129             }
130             }
131              
132             sub execute
133             {
134 21     21 1 4560 my($self, $build) = @_;
135 21         97 my $intr = $build->meta->interpolator;
136              
137 21         187 my $prop = $build->_command_prop;
138              
139 21         57 foreach my $command (@{ $self->{commands} })
  21         83  
140             {
141 27 100       188 if(ref($command) eq 'CODE')
    100          
142             {
143 2         29 $command->($build);
144             }
145             elsif(ref($command) eq 'ARRAY')
146             {
147 18         116 my($command, @args) = @$command;
148 18         34 my $code;
149 18 100 100     203 $code = pop @args if $args[-1] && ref($args[-1]) eq 'CODE';
150              
151 18 100 100     129 if($args[-1] && ref($args[-1]) eq 'SCALAR')
152             {
153 3         5 my $dest = ${ pop @args };
  3         7  
154 3 50       27 if($dest =~ /^\%\{((?:alien|)\.(?:install|runtime|hook)\.[a-z\.0-9_]+)\}$/)
155             {
156 3         11 $dest = $1;
157 3         8 $dest =~ s/^\./alien./;
158             $code = sub {
159 3     3   9 my($build, $args) = @_;
160 3 50       11 die "external command failed" if $args->{exit};
161 3         7 my $out = $args->{out};
162 3         8 chomp $out;
163 3         9 _apply($dest, $prop, $out);
164 3         17 };
165             }
166             else
167             {
168 0         0 die "illegal destination: $dest";
169             }
170             }
171              
172 18         89 ($command, @args) = map { $intr->interpolate($_, $prop) } ($command, @args);
  41         205  
173              
174 18 100       65 if($code)
175             {
176 6         69 _run_with_code $build, $command, @args, $code;
177             }
178             else
179             {
180 12         52 _run_list $build, $command, @args;
181             }
182             }
183             else
184             {
185 7         130 my $command = $intr->interpolate($command,$prop);
186 7         62 _run_string $build, $command;
187             }
188             }
189             }
190              
191             1;
192              
193             __END__