Name | Total Lines | Lines of Code | Total Coverage | Code Coverage |
---|---|---|---|---|
lib/bee_target.rb | 304 | 207 | 100.00%
|
100.00%
|
Code reported as executed by Ruby looks like this...and this: this line is also marked as covered.Lines considered as run by rcov, but not reported by Ruby, look like this,and this: these lines were inferred by rcov (using simple heuristics).Finally, here's a line marked as not executed.
1 # Copyright 2006-2012 Michel Casabianca <michel.casabianca@gmail.com> |
2 # |
3 # Licensed under the Apache License, Version 2.0 (the "License"); |
4 # you may not use this file except in compliance with the License. |
5 # You may obtain a copy of the License at |
6 # |
7 # http://www.apache.org/licenses/LICENSE-2.0 |
8 # |
9 # Unless required by applicable law or agreed to in writing, software |
10 # distributed under the License is distributed on an "AS IS" BASIS, |
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 # See the License for the specific language governing permissions and |
13 # limitations under the License. |
14 |
15 require 'rubygems' |
16 require 'bee_util' |
17 |
18 module Bee |
19 |
20 # Class for a target. It is built from the YAML build file and manages a |
21 # target, in particular, tasks execution. |
22 class Target |
23 |
24 include Bee::Util::BuildErrorMixin |
25 include Bee::Util::HashCheckerMixin |
26 |
27 # Target key. |
28 KEY = 'target' |
29 # Target entry description. |
30 DESCRIPTION = { |
31 'target' => :mandatory, |
32 'depends' => :optional, |
33 'description' => :optional, |
34 'script' => :optional} |
35 |
36 # Targets for build. |
37 attr_accessor :targets |
38 # Name of the target. |
39 attr_reader :name |
40 # Target dependencies. |
41 attr_accessor :depends |
42 # Target description. |
43 attr_accessor :description |
44 # Script that run in the target. |
45 attr_reader :script |
46 |
47 # Constructor. |
48 # - object: object for target, resulting from YAML parsing. |
49 # - targets: build targets. |
50 def initialize(object, targets) |
51 check_hash(object, Target::DESCRIPTION) |
52 @targets = targets |
53 @name = object[Target::KEY] |
54 error "Target name cannot be 'null'" if @name == nil |
55 @depends = Array(object['depends']||[]) |
56 @description = object['description'] |
57 @script = Array(object['script']||[]) |
58 end |
59 |
60 # Run target. |
61 # - dry: tells if we run in dry mode. Defaults to false. |
62 def run(dry=false) |
63 current_dir = Dir.pwd |
64 begin |
65 for depend in @depends |
66 @targets.run_target(depend, dry) |
67 end |
68 @targets.build.listener.target(self) if |
69 @targets.build.listener and @targets.is_last(self) |
70 run_block(@script, dry) |
71 ensure |
72 Dir.chdir(current_dir) |
73 end |
74 end |
75 |
76 private |
77 |
78 # Run a task. |
79 # - task: the task to run. |
80 # - dry: whether to just print. |
81 def run_task(task, dry=false) |
82 @targets.build.listener.task(task) if @targets.build.listener |
83 case task |
84 when String |
85 # shell script |
86 run_shell(task, dry) |
87 when Hash |
88 if task.keys.length > 1 |
89 # construct |
90 run_construct(task, dry) |
91 else |
92 if task.key?('rb') |
93 # ruby script |
94 script = task['rb'] |
95 run_ruby(script, dry) |
96 elsif task.key?('sh') |
97 # shell script |
98 script = task['sh'] |
99 run_shell(script, dry) |
100 elsif task.key?('super') |
101 # call super target |
102 targets.call_super(self, dry) |
103 else |
104 # bee task |
105 run_bee_task(task, dry) |
106 end |
107 end |
108 else |
109 raise "Task must be a string or a hash" |
110 end |
111 end |
112 |
113 # Run a given shell script. |
114 # - script: the scrip to run. |
115 def run_shell(script, dry=false) |
116 @listener.task(script) if @listener |
117 return if dry |
118 evaluated_script = @targets.build.context.evaluate_object(script) |
119 if evaluated_script != '' |
120 system(evaluated_script) |
121 error "Script exited with value #{$?}" if $? != 0 |
122 end |
123 end |
124 |
125 # Run a given shell script. |
126 # - script: the scrip to run. |
127 # - dry: tells if we run in dry mode. |
128 def run_ruby(script, dry=false) |
129 @listener.task(script) if @listener |
130 return if dry |
131 begin |
132 @targets.build.context.evaluate_script(script) |
133 rescue Interrupt |
134 raise $! |
135 rescue Exception |
136 error "Error running Ruby script: #{$!}" |
137 end |
138 end |
139 |
140 # Run a given bee task. |
141 # - task: task to run as a Hash. |
142 def run_bee_task(task, dry=false) |
143 @listener.task(task) if @listener |
144 return if dry |
145 @targets.build.package_manager.run_task(task) |
146 end |
147 |
148 # Run a given construct. |
149 # - construct: construct to run as a Hash. |
150 # - dry: tells if we are running in dry mode. Defaults to false. |
151 def run_construct(construct, dry=false) |
152 @listener.task(construct) if @listener |
153 return if dry |
154 # if construct |
155 if construct.keys.include?('if') |
156 construct_if(construct, dry) |
157 # while construct |
158 elsif construct.keys.include?('while') |
159 construct_while(construct, dry) |
160 # for construct |
161 elsif construct.keys.include?('for') |
162 construct_for(construct, dry) |
163 # try construct |
164 elsif construct.keys.include?('try') |
165 construct_try(construct, dry) |
166 else |
167 error "Unknown construct '#{construct.keys.join('-')}'" |
168 end |
169 end |
170 |
171 # Run if construct. |
172 # - task: the construct as a hash. |
173 # - dry: tells if we run in dry mode. |
174 def construct_if(task, dry) |
175 # test entries |
176 error "If-then-else construct must include 'then' entry" if |
177 not task.keys.include?('then') |
178 unknown_keys = task.keys - ['if', 'then', 'else'] |
179 error "If-then-else construct may only include 'if', 'then' and 'else' entries" if |
180 unknown_keys.length > 0 |
181 error "If entry in if-then-else construct must be a string, a symbol or a boolean" if |
182 not task['if'].kind_of?(String) and |
183 not task['if'].kind_of?(Symbol) and |
184 not (task['if'].kind_of?(TrueClass) or task['if'].kind_of?(FalseClass)) |
185 error "Then entry in if-then-else construct must be a list" if |
186 not task['then'].kind_of?(Array) |
187 error "Else entry in if-then-else construct must be a list" if |
188 task['else'] and not task['else'].kind_of?(Array) |
189 # evaluate condition in the build context |
190 if evaluate(task['if']) |
191 run_block(task['then'], dry) |
192 else |
193 run_block(task['else'], dry) if task['else'] |
194 end |
195 end |
196 |
197 # Run while construct. |
198 # - task: the construct as a hash. |
199 # - dry: tells if we run in dry mode. |
200 def construct_while(task, dry) |
201 # test entries |
202 error "While-do construct must include 'do' entry" if |
203 not task.keys.include?('do') |
204 unknown_keys = task.keys - ['while', 'do'] |
205 error "While-do construct may only include 'while' and 'do' entries" if |
206 unknown_keys.length > 0 |
207 error "While entry in while-do construct must be a string" if |
208 not task['while'].kind_of?(String) |
209 error "Do entry in while-do construct must be a list" if |
210 not task['do'].kind_of?(Array) |
211 # evaluate condition in the build context |
212 while evaluate(task['while']) |
213 run_block(task['do'], dry) |
214 end |
215 end |
216 |
217 # Run for construct. |
218 # - task: the construct as a hash. |
219 # - dry: tells if we run in dry mode. |
220 def construct_for(task, dry) |
221 # test entries |
222 error "For-in-do construct must include 'in' and 'do' entries" if |
223 not task.keys.include?('in') or |
224 not task.keys.include?('do') |
225 unknown_keys = task.keys - ['for', 'in', 'do'] |
226 error "For-in-do construct may only include 'for', 'in' and 'do' entries" if |
227 unknown_keys.length > 0 |
228 error "For entry in for-in-do construct must be a string" if |
229 not task['for'].kind_of?(String) |
230 error "In entry in for-in-do construct must be a list, a string or a symbol" if |
231 not task['in'].kind_of?(Enumerable) and |
232 not task['in'].kind_of?(String) and |
233 not task['in'].kind_of?(Symbol) |
234 error "Do entry in for-in-do construct must be a list" if |
235 not task['do'].kind_of?(Array) |
236 # iterate over list |
237 if task['in'].kind_of?(String) or task['in'].kind_of?(Symbol) |
238 enumerable = evaluate(task['in']) |
239 error "In entry in for-in-do construct must result in an enumerable" if |
240 not enumerable.kind_of?(Enumerable) |
241 else |
242 enumerable = task['in'] |
243 end |
244 for element in enumerable |
245 begin |
246 @targets.build.context.set_property(task['for'], element) |
247 rescue |
248 error "Error setting property '#{task['for']}'" |
249 end |
250 run_block(task['do'], dry) |
251 end |
252 end |
253 |
254 # Run try-catch construct. |
255 # - task: the construct as a hash. |
256 # - dry: tells if we run in dry mode. |
257 def construct_try(task, dry) |
258 # test entries |
259 error "Try-catch construct must include 'catch' entry" if |
260 not task.keys.include?('catch') |
261 unknown_keys = task.keys - ['try', 'catch'] |
262 error "Try-catch construct may only include 'try' and 'catch' entries" if |
263 unknown_keys.length > 0 |
264 error "Try entry in try-catch construct must be a list" if |
265 not task['try'].kind_of?(Array) |
266 error "Catch entry in try-catch construct must be a list" if |
267 task['catch'] and not task['catch'].kind_of?(Array) |
268 # try and catch errors |
269 begin |
270 run_block(task['try'], dry) |
271 rescue |
272 @targets.build.listener.recover if @targets.build.listener |
273 run_block(task['catch'], dry) if task['catch'] |
274 |
275 end |
276 end |
277 |
278 # Run a block, that is a list of tasks. |
279 # - block: the block to run as a list of tasks. |
280 # - dry: tells if we run in dry mode. |
281 def run_block(block, dry) |
282 for task in block |
283 run_task(task, dry) |
284 end |
285 end |
286 |
287 # Evaluate a given expression and raise a BuildError if an error happens. |
288 def evaluate(expression) |
289 begin |
290 if expression.kind_of?(String) |
291 return @targets.build.context.evaluate_script(expression) |
292 elsif (expression.kind_of?(TrueClass) or expression.kind_of?(FalseClass)) |
293 return expression |
294 else |
295 return @targets.build.context.evaluate_object(expression) |
296 end |
297 rescue |
298 error "Error evaluating expression: #{$!}" |
299 end |
300 end |
301 |
302 end |
303 |
304 end |
Generated on Fri Oct 09 02:07:49 +0200 2015 with rcov 1.0.0