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