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   181133 use strict;
  9         24  
  9         273  
4 9     9   70 use warnings;
  9         20  
  9         256  
5 9     9   185 use 5.008004;
  9         30  
6 9     9   2134 use Text::ParseWords qw( shellwords );
  9         6186  
  9         564  
7 9     9   456 use Capture::Tiny qw( capture );
  9         19390  
  9         10331  
8              
9             # ABSTRACT: Alien::Build command sequence
10             our $VERSION = '2.47'; # VERSION
11              
12              
13             sub new
14             {
15 68     68 1 35582 my($class, @commands) = @_;
16 68         204 my $self = bless {
17             commands => \@commands,
18             }, $class;
19 68         227 $self;
20             }
21              
22              
23             sub apply_requirements
24             {
25 57     57 1 123 my($self, $meta, $phase) = @_;
26 57         176 my $intr = $meta->interpolator;
27 57         107 foreach my $command (@{ $self->{commands} })
  57         191  
28             {
29 103 100       303 next if ref $command eq 'CODE';
30 94 100       209 if(ref $command eq 'ARRAY')
31             {
32 47         73 foreach my $arg (@$command)
33             {
34 175 100       277 next if ref $arg eq 'CODE';
35 152         315 $meta->add_requires($phase, $intr->requires($arg))
36             }
37             }
38             else
39             {
40 47         154 $meta->add_requires($phase, $intr->requires($command));
41             }
42             }
43 57         110 $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   48 my($build, @cmd) = @_;
69 12         115 $build->log("+ @cmd");
70 12 100       79 return $built_in{$cmd[0]}->(@cmd) if $built_in{$cmd[0]};
71 11         14598 system @cmd;
72 11 100       31643 die "external command failed" if $?;
73             }
74              
75             sub _run_string
76             {
77 7     7   28 my($build, $cmd) = @_;
78 7         66 $build->log("+ $cmd");
79              
80             {
81 7         34 my $cmd = $cmd;
  7         27  
82 7 50       48 $cmd =~ s{\\}{\\\\}g if $^O eq 'MSWin32';
83 7         56 my @cmd = shellwords($cmd);
84 7 100       1181 return $built_in{$cmd[0]}->(@cmd) if $built_in{$cmd[0]};
85             }
86              
87 6         12106 system $cmd;
88 6 100       2352 die "external command failed" if $?;
89             }
90              
91             sub _run_with_code
92             {
93 6     6   36 my($build, @cmd) = @_;
94 6         18 my $code = pop @cmd;
95 6         60 $build->log("+ @cmd");
96 6         35 my %args = ( command => \@cmd );
97              
98 6 100       28 if($built_in{$cmd[0]})
99             {
100 1         5 my $error;
101             ($args{out}, $args{err}, $error) = capture {
102 1     1   1230 eval { $built_in{$cmd[0]}->(@cmd) };
  1         12  
103 1         4 $@;
104 1         96 };
105 1 50       724 $args{exit} = $error eq '' ? 0 : 2;
106 1         9 $args{builtin} = 1;
107             }
108             else
109             {
110             ($args{out}, $args{err}, $args{exit}) = capture {
111 5     5   4319 system @cmd; $?
  5         342  
112 5         124 };
113             }
114 6         3245 $build->log("[output consumed by Alien::Build recipe]");
115 6         37 $code->($build, \%args);
116             }
117              
118              
119             sub _apply
120             {
121 9     9   18 my($where, $prop, $value) = @_;
122 9 100       35 if($where =~ /^(.*?)\.(.*?)$/)
123             {
124 6         20 _apply($2, $prop->{$1}, $value);
125             }
126             else
127             {
128 3         32 $prop->{$where} = $value;
129             }
130             }
131              
132             sub execute
133             {
134 21     21 1 2863 my($self, $build) = @_;
135 21         77 my $intr = $build->meta->interpolator;
136              
137 21         158 my $prop = $build->_command_prop;
138              
139 21         52 foreach my $command (@{ $self->{commands} })
  21         73  
140             {
141 27 100       161 if(ref($command) eq 'CODE')
    100          
142             {
143 2         31 $command->($build);
144             }
145             elsif(ref($command) eq 'ARRAY')
146             {
147 18         73 my($command, @args) = @$command;
148 18         39 my $code;
149 18 100 100     159 $code = pop @args if $args[-1] && ref($args[-1]) eq 'CODE';
150              
151 18 100 100     100 if($args[-1] && ref($args[-1]) eq 'SCALAR')
152             {
153 3         5 my $dest = ${ pop @args };
  3         5  
154 3 50       22 if($dest =~ /^\%\{((?:alien|)\.(?:install|runtime|hook)\.[a-z\.0-9_]+)\}$/)
155             {
156 3         10 $dest = $1;
157 3         8 $dest =~ s/^\./alien./;
158             $code = sub {
159 3     3   8 my($build, $args) = @_;
160 3 50       8 die "external command failed" if $args->{exit};
161 3         6 my $out = $args->{out};
162 3         7 chomp $out;
163 3         8 _apply($dest, $prop, $out);
164 3         14 };
165             }
166             else
167             {
168 0         0 die "illegal destination: $dest";
169             }
170             }
171              
172 18         69 ($command, @args) = map { $intr->interpolate($_, $prop) } ($command, @args);
  41         172  
173              
174 18 100       45 if($code)
175             {
176 6         71 _run_with_code $build, $command, @args, $code;
177             }
178             else
179             {
180 12         35 _run_list $build, $command, @args;
181             }
182             }
183             else
184             {
185 7         113 my $command = $intr->interpolate($command,$prop);
186 7         54 _run_string $build, $command;
187             }
188             }
189             }
190              
191             1;
192              
193             __END__