bee 0.9.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README +1 -1
- data/egg/application.yml +2 -2
- data/egg/application/build.yml +23 -23
- data/egg/package.yml +2 -2
- data/egg/package/build.erb +21 -21
- data/egg/package/egg.yml +2 -2
- data/egg/package/egg_build.erb +5 -5
- data/egg/script.yml +2 -2
- data/egg/script/build.yml +5 -5
- data/egg/sinatra.yml +2 -2
- data/egg/sinatra/build.yml +8 -8
- data/egg/source.yml +2 -2
- data/egg/xmlrpc.yml +2 -2
- data/egg/xmlrpc/build.yml +6 -6
- data/lib/bee.rb +44 -569
- data/lib/bee_console.rb +25 -28
- data/lib/bee_context.rb +138 -0
- data/lib/bee_properties.rb +145 -0
- data/lib/bee_target.rb +287 -0
- metadata +6 -3
data/lib/bee_console.rb
CHANGED
@@ -62,7 +62,7 @@ targets Targets to run (default target if omitted).'
|
|
62
62
|
| |__ ___ ___
|
63
63
|
____ | '_ \ / _ \/ _ \ _____ _____ _____ _____ _____ _____ _____ _____ _____
|
64
64
|
|____| | |_) | __/ __/ |_____|_____|_____|_____|_____|_____|_____|_____|_____|
|
65
|
-
|_.__/ \___|\___| 0.
|
65
|
+
|_.__/ \___|\___| 0.10.0 http://bee.rubyforge.org
|
66
66
|
|
67
67
|
EOF
|
68
68
|
|
@@ -180,7 +180,12 @@ EOF
|
|
180
180
|
puts "ERROR: parsing command line (type 'bee -h' for help)"
|
181
181
|
exit(EXIT_PARSING_CMDLINE)
|
182
182
|
end
|
183
|
-
|
183
|
+
begin
|
184
|
+
formatter = Formatter.new(style, color)
|
185
|
+
rescue
|
186
|
+
puts "ERROR: bad format string '#{style}'"
|
187
|
+
exit(EXIT_PARSING_CMDLINE)
|
188
|
+
end
|
184
189
|
begin
|
185
190
|
if logo
|
186
191
|
puts BEE_LOGO
|
@@ -372,7 +377,7 @@ EOF
|
|
372
377
|
help << "build: #{build.name}\n"
|
373
378
|
end
|
374
379
|
if build.extends
|
375
|
-
help << "extends: #{build.extends}\n"
|
380
|
+
help << "extends: #{build.extends.map{|b| b.name}.join(', ')}\n"
|
376
381
|
end
|
377
382
|
if build.description
|
378
383
|
help << format_description('description', build.description, 0, false)
|
@@ -434,10 +439,8 @@ EOF
|
|
434
439
|
end
|
435
440
|
description = 'No description found'
|
436
441
|
if properties
|
437
|
-
|
438
|
-
|
439
|
-
description = property['description']
|
440
|
-
end
|
442
|
+
if properties['description']
|
443
|
+
description = properties['description']
|
441
444
|
end
|
442
445
|
end
|
443
446
|
help << format_title(name)
|
@@ -475,33 +478,27 @@ EOF
|
|
475
478
|
return colorized
|
476
479
|
end
|
477
480
|
|
478
|
-
# Parse style from command line.
|
479
|
-
# nil (which means default style).
|
481
|
+
# Parse style from command line.
|
480
482
|
# - string: style to parse.
|
481
483
|
def parse_style_from_command_line(string)
|
482
484
|
return if not string
|
483
485
|
style = {}
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
not COLORS.member?(value) and not STYLES.member?(value)
|
497
|
-
end
|
498
|
-
style[key] = value
|
486
|
+
for pair in string.split(',')
|
487
|
+
key, value = pair.split(':')
|
488
|
+
key = SHORT_STYLE_KEYS[key] || key
|
489
|
+
key = key.to_sym
|
490
|
+
if key == :line_length
|
491
|
+
value = value.to_i
|
492
|
+
elsif key == :line_character
|
493
|
+
value = ' ' if not value or value.length == 0
|
494
|
+
else
|
495
|
+
value = value.to_sym
|
496
|
+
error "Unkown color or style '#{value}'" if
|
497
|
+
not COLORS.member?(value) and not STYLES.member?(value)
|
499
498
|
end
|
500
|
-
|
501
|
-
rescue
|
502
|
-
# if parsing fails, return default style (nil)
|
503
|
-
return nil
|
499
|
+
style[key] = value
|
504
500
|
end
|
501
|
+
return style
|
505
502
|
end
|
506
503
|
|
507
504
|
# Format a description.
|
data/lib/bee_context.rb
ADDED
@@ -0,0 +1,138 @@
|
|
1
|
+
# Copyright 2006-2010 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
|
+
# Module for Bee core classes.
|
16
|
+
module Bee
|
17
|
+
|
18
|
+
# Class for Ruby scripts context. All embedded Ruby scripts run in this
|
19
|
+
# context where build properties are defined as Ruby variables.
|
20
|
+
class Context
|
21
|
+
|
22
|
+
include Bee::Util::BuildErrorMixin
|
23
|
+
|
24
|
+
# The binding of this context.
|
25
|
+
attr_reader :context_binding
|
26
|
+
|
27
|
+
# Constructor.
|
28
|
+
def initialize(properties)
|
29
|
+
@properties = properties
|
30
|
+
@context_binding = get_binding
|
31
|
+
end
|
32
|
+
|
33
|
+
# Set a given property in context.
|
34
|
+
# - name: the property name.
|
35
|
+
# - value: the property value.
|
36
|
+
# - override: tells if we can overwrite an existing value.
|
37
|
+
def set_property(name, value, overwrite=true)
|
38
|
+
error "Property '#{name}' was already defined" if
|
39
|
+
!overwrite and properties.include?(name.to_s)
|
40
|
+
begin
|
41
|
+
eval("#{name} = #{value.inspect}", @context_binding)
|
42
|
+
rescue Exception
|
43
|
+
error "Error setting property '#{name} = #{value.inspect}': #{$!}"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# Get a given property in context.
|
48
|
+
# - name: the property name.
|
49
|
+
# - strict: raise an error if given property was not set.
|
50
|
+
def get_property(name, strict=false)
|
51
|
+
error "Property '#{name}' was not set" if
|
52
|
+
strict and !properties.include?(name.to_s)
|
53
|
+
begin
|
54
|
+
eval("#{name}", @context_binding)
|
55
|
+
rescue NameError
|
56
|
+
error "Property '#{name}' was not set"
|
57
|
+
rescue Exception
|
58
|
+
error "Error getting property '#{name}': #{$!}"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# Return list of properties (as local variables of binding).
|
63
|
+
def properties
|
64
|
+
return eval('local_variables', @context_binding).map{ |var| var.to_s }
|
65
|
+
end
|
66
|
+
|
67
|
+
# Evaluate a script in context.
|
68
|
+
# - script: source of the script to evaluate.
|
69
|
+
def evaluate_script(script)
|
70
|
+
eval(script, @context_binding)
|
71
|
+
end
|
72
|
+
|
73
|
+
# Process a given object, replacing properties references with their
|
74
|
+
# string value, symbol with their raw value. Property references have
|
75
|
+
# same form than variable references in ruby strings: '#{variable}'
|
76
|
+
# will be replaced with variable string value.
|
77
|
+
# - object: object to process.
|
78
|
+
def evaluate_object(object)
|
79
|
+
case object
|
80
|
+
when NilClass
|
81
|
+
# nil: return nil
|
82
|
+
return nil
|
83
|
+
when String
|
84
|
+
# string: replace embedded Ruby expressions
|
85
|
+
object = object.gsub(/#\{.+?\}/) do |match|
|
86
|
+
expression = match[2..-2]
|
87
|
+
begin
|
88
|
+
value = evaluate_script(expression)
|
89
|
+
rescue
|
90
|
+
error "Error evaluating expression '#{expression}': #{$!}"
|
91
|
+
end
|
92
|
+
value
|
93
|
+
end
|
94
|
+
return object
|
95
|
+
when Symbol
|
96
|
+
# symbol: return property object
|
97
|
+
property = object.to_s
|
98
|
+
begin
|
99
|
+
value = eval("#{property}", @context_binding)
|
100
|
+
rescue
|
101
|
+
error "Property '#{property}' was not set"
|
102
|
+
end
|
103
|
+
return evaluate_object(value)
|
104
|
+
when Array
|
105
|
+
# array: evaluate each element
|
106
|
+
return object.collect { |element| evaluate_object(element) }
|
107
|
+
when Hash
|
108
|
+
# hash: evaluate all keys and values
|
109
|
+
evaluated = {}
|
110
|
+
object.each_pair do |key, value|
|
111
|
+
evaluated[evaluate_object(key)] = evaluate_object(value)
|
112
|
+
end
|
113
|
+
return evaluated
|
114
|
+
else
|
115
|
+
return object
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
private
|
120
|
+
|
121
|
+
# Get a binding as script context.
|
122
|
+
def get_binding
|
123
|
+
return binding
|
124
|
+
end
|
125
|
+
|
126
|
+
# Catch missing properties
|
127
|
+
def method_missing(name, *args, &block)
|
128
|
+
stack = Thread.current[:stack]
|
129
|
+
if stack
|
130
|
+
@properties.evaluate_property(name, self)
|
131
|
+
else
|
132
|
+
raise NoMethodError.new("undefined method `#{name}'", name, args)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
end
|
137
|
+
|
138
|
+
end
|
@@ -0,0 +1,145 @@
|
|
1
|
+
# Copyright 2006-2010 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 'bee_context'
|
16
|
+
|
17
|
+
# Module for Bee core classes.
|
18
|
+
module Bee
|
19
|
+
|
20
|
+
# Class to manage properties.
|
21
|
+
class Properties
|
22
|
+
|
23
|
+
include Bee::Util::BuildErrorMixin
|
24
|
+
|
25
|
+
# Key for properties entry.
|
26
|
+
KEY = 'properties'
|
27
|
+
|
28
|
+
# List of system properties
|
29
|
+
SYSTEM_PROPERTIES = [:base, :here]
|
30
|
+
|
31
|
+
# Properties expressions as a hash.
|
32
|
+
attr_reader :expressions
|
33
|
+
# Properties values as a hash
|
34
|
+
attr_reader :values
|
35
|
+
|
36
|
+
# Constructor.
|
37
|
+
# - build: build object.
|
38
|
+
def initialize(build)
|
39
|
+
@build = build
|
40
|
+
@expressions = {}
|
41
|
+
@values = {}
|
42
|
+
defaults
|
43
|
+
end
|
44
|
+
|
45
|
+
# Write properties. Will raise an error on duplicate definitions.
|
46
|
+
# - object: object tree resulting from YAML build file parsing or string
|
47
|
+
# for a properties file to load.
|
48
|
+
def write(object)
|
49
|
+
properties = object[Properties::KEY]
|
50
|
+
if properties.kind_of?(String)
|
51
|
+
begin
|
52
|
+
source = Bee::Util::get_file(properties, @build.base)
|
53
|
+
hash = YAML::load(source)
|
54
|
+
set_properties(hash, false)
|
55
|
+
rescue Exception
|
56
|
+
error "Error loading properties file '#{properties}': #{$!}"
|
57
|
+
end
|
58
|
+
else
|
59
|
+
set_properties(properties, false)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# Overwrite properties with those passed.
|
64
|
+
# - properties: properties as a hash.
|
65
|
+
def overwrite(properties)
|
66
|
+
set_properties(properties, true)
|
67
|
+
end
|
68
|
+
|
69
|
+
# Extend with properties of parent build.
|
70
|
+
# - properties: properties of parent build.
|
71
|
+
def extend(properties)
|
72
|
+
for name in properties.expressions.keys
|
73
|
+
@expressions[name] = properties.expressions[name] if
|
74
|
+
!@expressions.include?(name)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# Evaluate properties in context.
|
79
|
+
# - context: build context where properties must be evaluated.
|
80
|
+
def evaluate(context)
|
81
|
+
for name in @expressions.keys
|
82
|
+
Thread.current[:stack] = []
|
83
|
+
evaluate_property(name, context) if !@values[name]
|
84
|
+
end
|
85
|
+
Thread.current[:stack] = nil
|
86
|
+
end
|
87
|
+
|
88
|
+
# Evaluate a given property.
|
89
|
+
# - name: the name of the property to evaluate.
|
90
|
+
# - context: the context in which the property must be evaluated.
|
91
|
+
# - stack: the stack of evaluated objects.
|
92
|
+
def evaluate_property(name, context)
|
93
|
+
stack = Thread.current[:stack]
|
94
|
+
error "Unknown property '#{name}'" if !@expressions.keys.include?(name)
|
95
|
+
error "Circular properties: #{stack.join(', ')}" if stack.include?(name)
|
96
|
+
begin
|
97
|
+
stack.push(name)
|
98
|
+
value = context.evaluate_object(@expressions[name])
|
99
|
+
stack.pop
|
100
|
+
@values[name] = value
|
101
|
+
context.set_property(name, value, true)
|
102
|
+
rescue
|
103
|
+
error "Error evaluating property '#{name}': #{$!}"
|
104
|
+
end
|
105
|
+
value
|
106
|
+
end
|
107
|
+
|
108
|
+
private
|
109
|
+
|
110
|
+
# Set default properties.
|
111
|
+
def defaults
|
112
|
+
set(:base, @build.base, false)
|
113
|
+
set(:here, @build.here, false)
|
114
|
+
end
|
115
|
+
|
116
|
+
# Set properties.
|
117
|
+
# - properties: properties as a hash.
|
118
|
+
# - overwrite: tells if we can overwrite existing properties.
|
119
|
+
def set_properties(properties, overwrite)
|
120
|
+
error "Properties must be a hash" if not properties.kind_of?(Hash)
|
121
|
+
for name in properties.keys
|
122
|
+
expression = properties[name]
|
123
|
+
set(name, expression, overwrite)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
# Set a property.
|
128
|
+
# - name: property name (as a string or symbol).
|
129
|
+
# - expression: property expression (as a string) to be evaluated in
|
130
|
+
# context to get value.
|
131
|
+
# - overwrite: tells if we can overwrite existing properties.
|
132
|
+
def set(name, expression, overwrite)
|
133
|
+
error "Property '#{name}' collides with a function of the context" if
|
134
|
+
Bee::Context.method_defined?(name) or
|
135
|
+
Bee::Context.private_method_defined?(name)
|
136
|
+
return if expression == nil
|
137
|
+
name = name.to_sym
|
138
|
+
error "Duplicate property definition: '#{name}'" if
|
139
|
+
not overwrite and @expressions.has_key?(name)
|
140
|
+
@expressions[name] = expression
|
141
|
+
end
|
142
|
+
|
143
|
+
end
|
144
|
+
|
145
|
+
end
|
data/lib/bee_target.rb
ADDED
@@ -0,0 +1,287 @@
|
|
1
|
+
# Copyright 2006-2010 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
|
+
# Module for Bee core classes.
|
16
|
+
module Bee
|
17
|
+
|
18
|
+
# Class for a target. It is built from the YAML build file and manages a
|
19
|
+
# target, in particular, tasks execution.
|
20
|
+
class Target
|
21
|
+
|
22
|
+
include Bee::Util::BuildErrorMixin
|
23
|
+
include Bee::Util::HashCheckerMixin
|
24
|
+
|
25
|
+
# Target key.
|
26
|
+
KEY = 'target'
|
27
|
+
# Target entry description.
|
28
|
+
DESCRIPTION = {
|
29
|
+
'target' => :mandatory,
|
30
|
+
'depends' => :optional,
|
31
|
+
'description' => :optional,
|
32
|
+
'script' => :optional}
|
33
|
+
|
34
|
+
# Targets for build.
|
35
|
+
attr_accessor :targets
|
36
|
+
# Name of the target.
|
37
|
+
attr_reader :name
|
38
|
+
# Target dependencies.
|
39
|
+
attr_accessor :depends
|
40
|
+
# Target description.
|
41
|
+
attr_accessor :description
|
42
|
+
# Script that run in the target.
|
43
|
+
attr_reader :script
|
44
|
+
|
45
|
+
# Constructor.
|
46
|
+
# - object: object for target, resulting from YAML parsing.
|
47
|
+
# - targets: build targets.
|
48
|
+
def initialize(object, targets)
|
49
|
+
check_hash(object, Target::DESCRIPTION)
|
50
|
+
@targets = targets
|
51
|
+
@name = object[Target::KEY]
|
52
|
+
error "Target name cannot be 'null'" if @name == nil
|
53
|
+
@depends = object['depends']||[]
|
54
|
+
@depends = Array(@depends)
|
55
|
+
@description = object['description']
|
56
|
+
@script = object['script']
|
57
|
+
@script = [@script] if @script.kind_of?(String)
|
58
|
+
@script = [] if not @script
|
59
|
+
end
|
60
|
+
|
61
|
+
# Run target.
|
62
|
+
# - dry: tells if we run in dry mode. Defaults to false.
|
63
|
+
def run(dry=false)
|
64
|
+
current_dir = Dir.pwd
|
65
|
+
begin
|
66
|
+
for depend in @depends
|
67
|
+
@targets.run_target(depend, dry)
|
68
|
+
end
|
69
|
+
@targets.build.listener.target(self) if
|
70
|
+
@targets.build.listener and @targets.is_last(self)
|
71
|
+
run_block(@script, dry)
|
72
|
+
ensure
|
73
|
+
Dir.chdir(current_dir)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
# Run a task.
|
80
|
+
# - task: the task to run.
|
81
|
+
# - dry: whether to just print.
|
82
|
+
def run_task(task, dry=false)
|
83
|
+
@targets.build.listener.task(task) if @targets.build.listener
|
84
|
+
case task
|
85
|
+
when String
|
86
|
+
# shell script
|
87
|
+
run_shell(task, dry)
|
88
|
+
when Hash
|
89
|
+
if task.keys.length > 1
|
90
|
+
# construct
|
91
|
+
run_construct(task, dry)
|
92
|
+
else
|
93
|
+
if task.key?('rb')
|
94
|
+
# ruby script
|
95
|
+
script = task['rb']
|
96
|
+
run_ruby(script, dry)
|
97
|
+
elsif task.key?('sh')
|
98
|
+
# shell script
|
99
|
+
script = task['sh']
|
100
|
+
run_shell(script, dry)
|
101
|
+
elsif task.key?('super')
|
102
|
+
# call super target
|
103
|
+
targets.call_super(self, dry)
|
104
|
+
else
|
105
|
+
# must be a task
|
106
|
+
run_bee_task(task, dry)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
# Run a given shell script.
|
113
|
+
# - script: the scrip to run.
|
114
|
+
def run_shell(script, dry=false)
|
115
|
+
@listener.task(script) if @listener
|
116
|
+
return if dry
|
117
|
+
evaluated_script = @targets.build.context.evaluate_object(script)
|
118
|
+
if evaluated_script != ''
|
119
|
+
system(evaluated_script)
|
120
|
+
error "Script exited with value #{$?}" if $? != 0
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
# Run a given shell script.
|
125
|
+
# - script: the scrip to run.
|
126
|
+
# - dry: tells if we run in dry mode.
|
127
|
+
def run_ruby(script, dry=false)
|
128
|
+
@listener.task(script) if @listener
|
129
|
+
return if dry
|
130
|
+
begin
|
131
|
+
@targets.build.context.evaluate_script(script)
|
132
|
+
rescue Exception
|
133
|
+
error "Error running Ruby script: #{$!}"
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
# Run a given bee task.
|
138
|
+
# - task: task to run as a Hash.
|
139
|
+
def run_bee_task(task, dry=false)
|
140
|
+
@listener.task(task) if @listener
|
141
|
+
return if dry
|
142
|
+
@targets.build.package_manager.run_task(task)
|
143
|
+
end
|
144
|
+
|
145
|
+
# Run a given construct.
|
146
|
+
# - construct: construct to run as a Hash.
|
147
|
+
def run_construct(construct, dry=false)
|
148
|
+
@listener.task(construct) if @listener
|
149
|
+
return if dry
|
150
|
+
# if construct
|
151
|
+
if construct.keys.include?('if')
|
152
|
+
construct_if(construct, dry)
|
153
|
+
# while construct
|
154
|
+
elsif construct.keys.include?('while')
|
155
|
+
construct_while(construct, dry)
|
156
|
+
# for construct
|
157
|
+
elsif construct.keys.include?('for')
|
158
|
+
construct_for(construct, dry)
|
159
|
+
# try construct
|
160
|
+
elsif construct.keys.include?('try')
|
161
|
+
construct_try(construct, dry)
|
162
|
+
else
|
163
|
+
error "Unknown construct '#{construct.keys.join('-')}'"
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
# Run if construct.
|
168
|
+
# - task: the construct as a hash.
|
169
|
+
# - dry: tells if we run in dry mode.
|
170
|
+
def construct_if(task, dry)
|
171
|
+
# test entries
|
172
|
+
error "If-then-else construct must include 'then' entry" if
|
173
|
+
not task.keys.include?('then')
|
174
|
+
unknown_keys = task.keys - ['if', 'then', 'else']
|
175
|
+
error "If-then-else construct may only include 'if', 'then' and 'else' entries" if
|
176
|
+
unknown_keys.length > 0
|
177
|
+
error "If entry in if-then-else construct must be a string" if
|
178
|
+
not task['if'].kind_of?(String)
|
179
|
+
error "Then entry in if-then-else construct must be a list" if
|
180
|
+
not task['then'].kind_of?(Array)
|
181
|
+
error "Else entry in if-then-else construct must be a list" if
|
182
|
+
task['else'] and not task['else'].kind_of?(Array)
|
183
|
+
# evaluate condition in the build context
|
184
|
+
if evaluate(task['if'])
|
185
|
+
run_block(task['then'], dry)
|
186
|
+
else
|
187
|
+
run_block(task['else'], dry) if task['else']
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
# Run while construct.
|
192
|
+
# - task: the construct as a hash.
|
193
|
+
# - dry: tells if we run in dry mode.
|
194
|
+
def construct_while(task, dry)
|
195
|
+
# test entries
|
196
|
+
error "While-do construct must include 'do' entry" if
|
197
|
+
not task.keys.include?('do')
|
198
|
+
unknown_keys = task.keys - ['while', 'do']
|
199
|
+
error "While-do construct may only include 'while' and 'do' entries" if
|
200
|
+
unknown_keys.length > 0
|
201
|
+
error "While entry in while-do construct must be a string" if
|
202
|
+
not task['while'].kind_of?(String)
|
203
|
+
error "Do entry in while-do construct must be a list" if
|
204
|
+
not task['do'].kind_of?(Array)
|
205
|
+
# evaluate condition in the build context
|
206
|
+
while evaluate(task['while'])
|
207
|
+
run_block(task['do'], dry)
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
# Run for construct.
|
212
|
+
# - task: the construct as a hash.
|
213
|
+
# - dry: tells if we run in dry mode.
|
214
|
+
def construct_for(task, dry)
|
215
|
+
# test entries
|
216
|
+
error "For-in-do construct must include 'in' and 'do' entries" if
|
217
|
+
not task.keys.include?('in') or not task.keys.include?('do')
|
218
|
+
unknown_keys = task.keys - ['for', 'in', 'do']
|
219
|
+
error "For-in-do construct may only include 'for', 'in' and 'do' entries" if
|
220
|
+
unknown_keys.length > 0
|
221
|
+
error "For entry in for-in-do construct must be a string" if
|
222
|
+
not task['for'].kind_of?(String)
|
223
|
+
error "In entry in for-in-do construct must be a list or a string" if
|
224
|
+
not task['in'].kind_of?(Enumerable) and not task['in'].kind_of?(String)
|
225
|
+
error "Do entry in for-in-do construct must be a list" if
|
226
|
+
not task['do'].kind_of?(Array)
|
227
|
+
# iterate over list
|
228
|
+
if task['in'].kind_of?(String)
|
229
|
+
enumerable = evaluate(@targets.build.context.
|
230
|
+
evaluate_object(task['in']))
|
231
|
+
else
|
232
|
+
enumerable = task['in']
|
233
|
+
end
|
234
|
+
for element in enumerable
|
235
|
+
begin
|
236
|
+
@targets.build.context.set_property(task['for'], element)
|
237
|
+
rescue
|
238
|
+
error "Error setting property '#{task['for']}'"
|
239
|
+
end
|
240
|
+
run_block(task['do'], dry)
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
# Run try-catch construct.
|
245
|
+
# - task: the construct as a hash.
|
246
|
+
# - dry: tells if we run in dry mode.
|
247
|
+
def construct_try(task, dry)
|
248
|
+
# test entries
|
249
|
+
error "Try-catch construct must include 'catch' entry" if
|
250
|
+
not task.keys.include?('catch')
|
251
|
+
unknown_keys = task.keys - ['try', 'catch']
|
252
|
+
error "Try-catch construct may only include 'try' and 'catch' entries" if
|
253
|
+
unknown_keys.length > 0
|
254
|
+
error "Try entry in try-catch construct must be a list" if
|
255
|
+
not task['try'].kind_of?(Array)
|
256
|
+
error "Catch entry in try-catch construct must be a list" if
|
257
|
+
not task['catch'].kind_of?(Array)
|
258
|
+
# try and catch errors
|
259
|
+
begin
|
260
|
+
run_block(task['try'], dry)
|
261
|
+
rescue
|
262
|
+
@targets.build.listener.recover if @targets.build.listener
|
263
|
+
run_block(task['catch'], dry)
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
# Run a block, that is a list of tasks.
|
268
|
+
# - block: the block to run as a list of tasks.
|
269
|
+
# - dry: tells if we run in dry mode.
|
270
|
+
def run_block(block, dry)
|
271
|
+
for task in block
|
272
|
+
run_task(task, dry)
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
276
|
+
# Evaluate a given expression and raise a BuildError if an error happens.
|
277
|
+
def evaluate(expression)
|
278
|
+
begin
|
279
|
+
return @targets.build.context.evaluate_script(expression)
|
280
|
+
rescue
|
281
|
+
error "Error evaluating expression: #{$!}"
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
285
|
+
end
|
286
|
+
|
287
|
+
end
|