bee 0.4.0 → 0.5.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/bin/bee +1 -1
- data/bin/bee.bat +1 -1
- data/egg/package.yml +100 -0
- data/egg/package/bee_task.erb +25 -0
- data/egg/package/build.erb +70 -0
- data/egg/package/egg.yml +58 -0
- data/egg/package/egg_build.erb +57 -0
- data/egg/package/egg_launcher.erb +6 -0
- data/egg/package/egg_script.rb +31 -0
- data/egg/package/gem_spec.erb +23 -0
- data/egg/package/license +202 -0
- data/egg/package/readme.erb +23 -0
- data/egg/package/test.erb +28 -0
- data/egg/package/test_build.erb +16 -0
- data/{test → egg/package}/test_build.rb +1 -1
- data/{test → egg/package}/test_build_listener.rb +3 -1
- data/{test/ts_bee.rb → egg/package/test_suite.rb} +1 -1
- data/lib/bee.rb +468 -167
- data/lib/bee_console.rb +174 -94
- data/lib/bee_task.rb +121 -19
- data/lib/bee_task_default.rb +1016 -229
- data/lib/bee_util.rb +217 -64
- metadata +73 -58
- data/test/tc_bee_build.rb +0 -216
- data/test/tc_bee_console.rb +0 -106
- data/test/tc_bee_console_formatter.rb +0 -81
- data/test/tc_bee_context.rb +0 -84
- data/test/tc_bee_task_default.rb +0 -467
- data/test/tc_bee_util.rb +0 -85
- data/test/tmp_test_case.rb +0 -58
@@ -0,0 +1,23 @@
|
|
1
|
+
= <%= name.capitalize %>
|
2
|
+
|
3
|
+
<%= summary %>
|
4
|
+
|
5
|
+
= Home Page
|
6
|
+
|
7
|
+
This software is hosted on RubyForge (thanks to them for their great job!)
|
8
|
+
at <%= homepage %>.
|
9
|
+
|
10
|
+
= Documentation
|
11
|
+
|
12
|
+
For more information about this software, please read the documentation
|
13
|
+
in "<%= name %>" section on Gem server (type "gem_server" and go at URL
|
14
|
+
http://localhost:8808) if you installed it using Gem.
|
15
|
+
|
16
|
+
= License
|
17
|
+
|
18
|
+
bee is Open Source and released under the Apache License (see LICENE file
|
19
|
+
or go to URL http://www.apache.org/licenses/LICENSE-2.0).
|
20
|
+
|
21
|
+
= Copyright
|
22
|
+
|
23
|
+
<%= name.capitalize %> version <%= version %> (C) <%= author %> - <%= years %>
|
@@ -0,0 +1,28 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'bee'
|
4
|
+
require 'test/unit'
|
5
|
+
$:.unshift(File.join(File.expand_path(File.dirname(__FILE__))))
|
6
|
+
require 'test_build'
|
7
|
+
require 'test_build_listener'
|
8
|
+
$:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
9
|
+
require 'bee_task_<%= project_short_name %>'
|
10
|
+
|
11
|
+
# Test case for bee task.
|
12
|
+
class TestBeeTask<%= project_short_name.capitalize %> < Test::Unit::TestCase
|
13
|
+
|
14
|
+
# Create a context object and load tasks in it.
|
15
|
+
def setup
|
16
|
+
super
|
17
|
+
@context = Bee::Context.new
|
18
|
+
@listener = TestBuildListener.new
|
19
|
+
@build = TestBuild.new(@context, @listener)
|
20
|
+
@package = Bee::Task::<%= project_short_name.capitalize %>.new(@build)
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_hello
|
24
|
+
@package.hello('TEST')
|
25
|
+
assert_equal("Hello TEST!\n", @listener.output)
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
- build: package_test
|
2
|
+
default: all
|
3
|
+
description: Build file to test generated and installed package
|
4
|
+
|
5
|
+
- target: task
|
6
|
+
description: Test task for generated package
|
7
|
+
script:
|
8
|
+
- <%= project_short_name %>.hello: "World"
|
9
|
+
|
10
|
+
- target: egg
|
11
|
+
description: Test egg for generated package
|
12
|
+
script:
|
13
|
+
- "bee -t '<%= project_short_name %>.hello'"
|
14
|
+
|
15
|
+
- target: all
|
16
|
+
depends: [task, egg]
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright 2006-
|
1
|
+
# Copyright 2006-2008 Michel Casabianca <michel.casabianca@gmail.com>
|
2
2
|
#
|
3
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
4
|
# you may not use this file except in compliance with the License.
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright 2006-
|
1
|
+
# Copyright 2006-2008 Michel Casabianca <michel.casabianca@gmail.com>
|
2
2
|
#
|
3
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
4
|
# you may not use this file except in compliance with the License.
|
@@ -22,11 +22,13 @@ class TestBuildListener
|
|
22
22
|
attr_reader :success
|
23
23
|
attr_reader :errors
|
24
24
|
attr_accessor :output
|
25
|
+
attr_reader :verbose
|
25
26
|
|
26
27
|
def initialize
|
27
28
|
@targets = []
|
28
29
|
@tasks = []
|
29
30
|
@output = ''
|
31
|
+
@verbose = false
|
30
32
|
end
|
31
33
|
|
32
34
|
def build_started(build)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
# Copyright 2006-
|
3
|
+
# Copyright 2006-2008 Michel Casabianca <michel.casabianca@gmail.com>
|
4
4
|
#
|
5
5
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
6
|
# you may not use this file except in compliance with the License.
|
data/lib/bee.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright 2006-
|
1
|
+
# Copyright 2006-2008 Michel Casabianca <michel.casabianca@gmail.com>
|
2
2
|
#
|
3
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
4
|
# you may not use this file except in compliance with the License.
|
@@ -13,44 +13,61 @@
|
|
13
13
|
# limitations under the License.
|
14
14
|
|
15
15
|
require 'yaml'
|
16
|
+
require 'bee_task'
|
16
17
|
require 'bee_util'
|
17
18
|
|
18
19
|
# Module for Bee core classes.
|
19
20
|
module Bee
|
20
|
-
|
21
|
+
|
21
22
|
# Class for a build. This class is built from an object resulting from YAML
|
22
23
|
# build file parsing.
|
23
24
|
class Build
|
24
|
-
|
25
|
+
|
25
26
|
include Bee::Util::BuildErrorMixin
|
26
27
|
include Bee::Util::HashCheckerMixin
|
27
28
|
|
29
|
+
# Build key.
|
30
|
+
KEY = 'build'
|
31
|
+
# Build entry description.
|
32
|
+
DESCRIPTION = {
|
33
|
+
'build' => :mandatory,
|
34
|
+
'default' => :optional,
|
35
|
+
'description' => :optional,
|
36
|
+
'context' => :optional,
|
37
|
+
'extends' => :optional}
|
38
|
+
|
28
39
|
# Build file.
|
29
40
|
attr_reader :file
|
30
|
-
# Base directory
|
31
|
-
# are relative to this directory.
|
41
|
+
# Base directory, that is directory where lives the build file.
|
32
42
|
attr_reader :base
|
43
|
+
# Current directory, where was started the script.
|
44
|
+
attr_reader :here
|
33
45
|
# Build name.
|
34
46
|
attr_reader :name
|
35
|
-
#
|
36
|
-
|
37
|
-
|
47
|
+
# Parent build.
|
48
|
+
attr_reader :extends
|
49
|
+
# Default target, specified with default entry or fist target in build file.
|
50
|
+
attr_accessor :default
|
38
51
|
# Build description.
|
39
52
|
attr_reader :description
|
53
|
+
# Build properties.
|
54
|
+
attr_reader :properties
|
40
55
|
# Hash for targets, indexed by target name.
|
41
56
|
attr_reader :targets
|
42
57
|
# Context for Ruby scripts and properties.
|
43
58
|
attr_reader :context
|
44
|
-
# Package manager
|
59
|
+
# Package manager, for task invocation.
|
45
60
|
attr_reader :package_manager
|
46
|
-
# Build listener
|
61
|
+
# Build listener, responsible for displaying build status.
|
47
62
|
attr_reader :listener
|
48
63
|
|
49
64
|
# Load a build from a YAML build file.
|
50
|
-
# - file: YAML build file.
|
65
|
+
# - file: YAML build file or URL.
|
51
66
|
# - recursive: tells if we look for build file recursively (defaults to
|
52
67
|
# nil).
|
53
|
-
|
68
|
+
# - properties: a hash of additional properties passed on command line.
|
69
|
+
def self.load(file, recursive=nil, properties={})
|
70
|
+
raise "Can't use recursive URL" if recursive and Bee::Util::url?(file)
|
54
71
|
if recursive
|
55
72
|
begin
|
56
73
|
file = Bee::Util::find(file)
|
@@ -59,140 +76,420 @@ module Bee
|
|
59
76
|
"not found recursively")
|
60
77
|
end
|
61
78
|
end
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
yaml = File.read(file)
|
79
|
+
begin
|
80
|
+
yaml = Bee::Util::get_file(file)
|
81
|
+
rescue
|
82
|
+
raise Bee::Util::BuildError.
|
83
|
+
new("Error loading build file '#{file}': #{$!}")
|
84
|
+
end
|
69
85
|
begin
|
70
86
|
object = YAML::load(yaml)
|
71
87
|
rescue
|
72
88
|
raise Bee::Util::BuildError.
|
73
|
-
new("YAML syntax error in build file: #{$!}")
|
89
|
+
new("YAML syntax error in build file '#{file}': #{$!}")
|
74
90
|
end
|
75
|
-
return Build.new(object, file)
|
91
|
+
return Build.new(object, file, properties)
|
76
92
|
end
|
77
|
-
|
93
|
+
|
78
94
|
# Constructor:
|
79
|
-
# - object:
|
95
|
+
# - object: object tree resulting from YAML build file parsing.
|
80
96
|
# - file: build file (nil if none).
|
81
|
-
|
82
|
-
|
97
|
+
# - properties: a hash of additional properties passed on command line.
|
98
|
+
# - here: current directory.
|
99
|
+
def initialize(object, file, properties={}, here=Dir.pwd)
|
83
100
|
@file = file
|
84
|
-
|
85
|
-
|
86
|
-
else
|
87
|
-
@base = File.expand_path(Dir.pwd)
|
88
|
-
end
|
89
|
-
error "Build must be a list" unless object.kind_of?(Array)
|
90
|
-
@properties = {}
|
91
|
-
@targets = {}
|
101
|
+
@base = get_base(@file)
|
102
|
+
@here = here
|
92
103
|
@context = Context.new
|
93
|
-
@
|
94
|
-
@properties
|
104
|
+
@properties = Properties.new(self)
|
105
|
+
@properties.evaluate(@context)
|
106
|
+
@targets = Targets.new(self)
|
107
|
+
parse(object)
|
108
|
+
@properties.overwrite(properties)
|
95
109
|
@package_manager = Bee::Task::PackageManager.new(self)
|
96
|
-
# parse object entries
|
97
|
-
for entry in object
|
98
|
-
if entry.key?('build')
|
99
|
-
# build info entry
|
100
|
-
begin
|
101
|
-
check_hash(entry,
|
102
|
-
{'build' => :mandatory,
|
103
|
-
'default' => :optional,
|
104
|
-
'description' => :optional,
|
105
|
-
'context' => :optional})
|
106
|
-
rescue
|
107
|
-
error "Error parsing build entry: #{$!}"
|
108
|
-
end
|
109
|
-
error "Duplicate build info" if @name
|
110
|
-
@name = entry['build']
|
111
|
-
@default = entry['default']
|
112
|
-
@description = entry['description']
|
113
|
-
# load context files if any
|
114
|
-
if entry['context']
|
115
|
-
for script in entry['context']
|
116
|
-
begin
|
117
|
-
based_script = File.join(@base, script)
|
118
|
-
evaluated_script = @context.evaluate_object(based_script)
|
119
|
-
source = File.read(evaluated_script)
|
120
|
-
@context.evaluate_script(source)
|
121
|
-
rescue Exception
|
122
|
-
error "Error loading context '#{script}': #{$!}"
|
123
|
-
end
|
124
|
-
end
|
125
|
-
end
|
126
|
-
elsif entry.key?('properties')
|
127
|
-
# properties entry
|
128
|
-
for property in entry['properties']
|
129
|
-
name = property.keys[0]
|
130
|
-
value = @context.evaluate_object(property[name])
|
131
|
-
@context.set_property(name, value, false)
|
132
|
-
end
|
133
|
-
elsif entry.key?('target')
|
134
|
-
# target entry
|
135
|
-
begin
|
136
|
-
target = Target.new(entry, self)
|
137
|
-
rescue
|
138
|
-
error "Error parsing target '#{entry['target']}': #{$!}"
|
139
|
-
end
|
140
|
-
@default = target.name if !@default and @targets.keys.empty?
|
141
|
-
error "Duplicate target definition: '#{target.name}'" if
|
142
|
-
@targets[target.name]
|
143
|
-
@targets[target.name] = target
|
144
|
-
else
|
145
|
-
# unknown entry
|
146
|
-
error "Unknown entry:\n#{YAML::dump(entry)}"
|
147
|
-
end
|
148
|
-
end
|
149
110
|
end
|
150
111
|
|
112
|
+
# Evaluate properties.
|
113
|
+
def evaluate_properties
|
114
|
+
@properties.evaluate(@context)
|
115
|
+
end
|
116
|
+
|
151
117
|
# Run build:
|
152
118
|
# - targets: list of targets to run.
|
153
119
|
# - listener: listener for the build.
|
154
|
-
def run(targets, listener=nil)
|
120
|
+
def run(targets, listener=nil, dry=false)
|
155
121
|
@listener = listener
|
156
122
|
working_directory = Dir.getwd
|
123
|
+
@listener.build_started(self, dry) if @listener
|
157
124
|
begin
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
targets = [@default] if targets.length == 0
|
162
|
-
for target in targets
|
163
|
-
run_target(target)
|
125
|
+
evaluate_properties
|
126
|
+
if not Bee::Util::url?(@base)
|
127
|
+
Dir.chdir(@base)
|
164
128
|
end
|
165
|
-
@
|
129
|
+
@targets.run(targets, dry)
|
130
|
+
@listener.build_finished(self, dry) if @listener
|
166
131
|
rescue Bee::Util::BuildError => e
|
167
|
-
if listener
|
132
|
+
if @listener
|
168
133
|
@listener.error(e)
|
169
134
|
else
|
170
135
|
raise e
|
171
136
|
end
|
172
137
|
ensure
|
173
|
-
@listener = nil
|
174
138
|
Dir.chdir(working_directory)
|
139
|
+
remove_instance_variable(:@listener)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
private
|
144
|
+
|
145
|
+
# Parse entries in build object.
|
146
|
+
# - object: object tree resulting from YAML build file parsing.
|
147
|
+
def parse(object)
|
148
|
+
error "Build must be a list" unless object.kind_of?(Array)
|
149
|
+
first = true
|
150
|
+
for entry in object
|
151
|
+
if entry.key?(Build::KEY)
|
152
|
+
parse_build(entry)
|
153
|
+
error "Build info entry must be first one in build file" if
|
154
|
+
not first
|
155
|
+
first = false
|
156
|
+
elsif entry.key?(Properties::KEY)
|
157
|
+
@properties.write(entry)
|
158
|
+
first = false
|
159
|
+
elsif entry.key?(Target::KEY)
|
160
|
+
@targets.add(entry)
|
161
|
+
first = false
|
162
|
+
else
|
163
|
+
error "Unknown entry:\n#{YAML::dump(entry)}"
|
164
|
+
end
|
165
|
+
end
|
166
|
+
# manage parent build
|
167
|
+
if @parent
|
168
|
+
@properties.extend(@parent.properties)
|
169
|
+
@targets.extend(@parent.targets)
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
# Parse a build entry.
|
174
|
+
# - entry: the build entry to parse.
|
175
|
+
def parse_build(entry)
|
176
|
+
begin
|
177
|
+
check_hash(entry, Build::DESCRIPTION)
|
178
|
+
rescue
|
179
|
+
error "Error parsing build info entry: #{$!}"
|
180
|
+
end
|
181
|
+
error "Duplicate build info" if @name
|
182
|
+
@name = entry['build']
|
183
|
+
@default = entry['default']
|
184
|
+
@targets.default = @default
|
185
|
+
@description = entry['description']
|
186
|
+
@extends = entry['extends']
|
187
|
+
# load parent build if any
|
188
|
+
if @extends
|
189
|
+
absolute_path = Bee::Util::absolute_path(@extends, @base)
|
190
|
+
begin
|
191
|
+
@parent = Bee::Build::load(absolute_path)
|
192
|
+
rescue Exception
|
193
|
+
error "Error loading parent build file '#{@extends}': #{$!}"
|
194
|
+
end
|
195
|
+
@default = @default || @parent.default
|
196
|
+
@targets.default = @default
|
197
|
+
@description = @description || @parent.description
|
198
|
+
end
|
199
|
+
# load context files if any
|
200
|
+
context = entry['context']
|
201
|
+
if context
|
202
|
+
context = Array(context)
|
203
|
+
for script in context
|
204
|
+
begin
|
205
|
+
evaluated = @context.evaluate_object(script)
|
206
|
+
source = Bee::Util::get_file(evaluated, @base)
|
207
|
+
@context.evaluate_script(source)
|
208
|
+
rescue Exception
|
209
|
+
error "Error loading context '#{script}': #{$!}"
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
# Get base for a given file.
|
216
|
+
# - file: build file.
|
217
|
+
def get_base(file)
|
218
|
+
if file
|
219
|
+
if Bee::Util::url?(file)
|
220
|
+
return File.dirname(file)
|
221
|
+
else
|
222
|
+
return File.expand_path(File.dirname(Bee::Util::absolute_path(file, Dir.pwd)))
|
223
|
+
end
|
224
|
+
else
|
225
|
+
return File.expand_path(Dir.pwd)
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
end
|
230
|
+
|
231
|
+
# Class to manage properties.
|
232
|
+
class Properties
|
233
|
+
|
234
|
+
include Bee::Util::BuildErrorMixin
|
235
|
+
|
236
|
+
# Key for properties entry.
|
237
|
+
KEY = 'properties'
|
238
|
+
|
239
|
+
# List of properties in order of evaluation.
|
240
|
+
attr_reader :list
|
241
|
+
# Hash of properties by name.
|
242
|
+
attr_reader :hash
|
243
|
+
|
244
|
+
# Constructor.
|
245
|
+
# - build: build object.
|
246
|
+
def initialize(build)
|
247
|
+
@list = []
|
248
|
+
@hash = {}
|
249
|
+
@build = build
|
250
|
+
defaults
|
251
|
+
end
|
252
|
+
|
253
|
+
# Write properties. Will raise an error on duplicate definitions.
|
254
|
+
# - object: object tree resulting from YAML build file parsing or string
|
255
|
+
# for a properties file to load.
|
256
|
+
def write(object)
|
257
|
+
properties = object[Properties::KEY]
|
258
|
+
if properties.kind_of?(String)
|
259
|
+
begin
|
260
|
+
source = Bee::Util::get_file(properties, @build.base)
|
261
|
+
list = YAML::load(source)
|
262
|
+
set_properties(list, false)
|
263
|
+
rescue Exception
|
264
|
+
error "Error loading properties file '#{properties}': #{$!}"
|
265
|
+
end
|
266
|
+
else
|
267
|
+
set_properties(properties, false)
|
175
268
|
end
|
176
269
|
end
|
177
270
|
|
271
|
+
# Overwrite properties. Will raise an error if properties don't already
|
272
|
+
# exist.
|
273
|
+
# - object: object tree resulting from YAML build file parsing.
|
274
|
+
def overwrite(object)
|
275
|
+
set_properties(object, true)
|
276
|
+
end
|
277
|
+
|
278
|
+
# Extend with properties of parent build.
|
279
|
+
# - properties: properties of parent build.
|
280
|
+
def extend(properties)
|
281
|
+
current_list = @list
|
282
|
+
current_hash = @hash
|
283
|
+
@list = properties.list
|
284
|
+
@hash = properties.hash
|
285
|
+
index = 0
|
286
|
+
0.upto(current_list.length - 1) do |current|
|
287
|
+
name = current_list[current]
|
288
|
+
pos = @list.index(name)
|
289
|
+
if pos
|
290
|
+
sub = current_list[index .. current]
|
291
|
+
@list[pos .. pos] = sub
|
292
|
+
for name in sub
|
293
|
+
@hash[name] = current_hash[name]
|
294
|
+
end
|
295
|
+
index = current + 1
|
296
|
+
end
|
297
|
+
end
|
298
|
+
tail = current_list[index .. current_list.length() - 1]
|
299
|
+
@list += tail
|
300
|
+
for name in tail
|
301
|
+
@hash[name] = current_hash[name]
|
302
|
+
end
|
303
|
+
end
|
304
|
+
|
305
|
+
# Evaluate properties in context.
|
306
|
+
# - context: build context where properties must be evaluated.
|
307
|
+
def evaluate(context)
|
308
|
+
for name in @list
|
309
|
+
begin
|
310
|
+
value = context.evaluate_object(@hash[name])
|
311
|
+
rescue Bee::Util::BuildError
|
312
|
+
error "Error evaluating property '#{name}': #{$!}"
|
313
|
+
end
|
314
|
+
context.set_property(name, value, true)
|
315
|
+
end
|
316
|
+
end
|
317
|
+
|
318
|
+
private
|
319
|
+
|
320
|
+
# Set default properties.
|
321
|
+
def defaults
|
322
|
+
set(:base, @build.base, false)
|
323
|
+
set(:here, @build.here, false)
|
324
|
+
end
|
325
|
+
|
326
|
+
# Set properties.
|
327
|
+
# - properties: properties as a list of hash if overwrite = false
|
328
|
+
# or a hash if overwrite = true.
|
329
|
+
# - overwrite: tells if we can overwrite existing properties.
|
330
|
+
def set_properties(properties, overwrite)
|
331
|
+
if overwrite
|
332
|
+
raise "Properties must be a hash" if not properties.kind_of?(Hash)
|
333
|
+
for name in properties.keys
|
334
|
+
expression = properties[name]
|
335
|
+
set(name, expression, overwrite)
|
336
|
+
end
|
337
|
+
else
|
338
|
+
raise "Properties must be a list" if not properties.kind_of?(Array)
|
339
|
+
for property in properties
|
340
|
+
name = property.keys[0]
|
341
|
+
expression = property[name]
|
342
|
+
set(name, expression, overwrite)
|
343
|
+
end
|
344
|
+
end
|
345
|
+
end
|
346
|
+
|
347
|
+
# Set a property.
|
348
|
+
# - name: property name (as a string or symbol).
|
349
|
+
# - expression: property expression (as a string) to be evaluated in
|
350
|
+
# context to get value.
|
351
|
+
# - overwrite: tells if we can overwrite existing properties.
|
352
|
+
def set(name, expression, overwrite)
|
353
|
+
name = name.to_sym
|
354
|
+
error "Duplicate property definition: '#{name}'" if
|
355
|
+
not overwrite and @hash.has_key?(name)
|
356
|
+
@list << name
|
357
|
+
@hash[name] = expression
|
358
|
+
end
|
359
|
+
|
360
|
+
end
|
361
|
+
|
362
|
+
# Class to manage targets in a build.
|
363
|
+
class Targets
|
364
|
+
|
365
|
+
include Bee::Util::BuildErrorMixin
|
366
|
+
|
367
|
+
# Parent build.
|
368
|
+
attr_reader :build
|
369
|
+
# Targets hash by name.
|
370
|
+
attr_reader :hash
|
371
|
+
# Targets already run.
|
372
|
+
attr_reader :already_run
|
373
|
+
# Default target.
|
374
|
+
attr_accessor :default
|
375
|
+
|
376
|
+
# Constructor.
|
377
|
+
# - build: build object.
|
378
|
+
def initialize(build)
|
379
|
+
@build = build
|
380
|
+
@hash = {}
|
381
|
+
@already_run = []
|
382
|
+
end
|
383
|
+
|
384
|
+
# Add a new target.
|
385
|
+
# - object: object tree resulting from YAML build file parsing.
|
386
|
+
def add(object)
|
387
|
+
begin
|
388
|
+
target = Target.new(object, self)
|
389
|
+
rescue
|
390
|
+
error "Error parsing target '#{object[Target::KEY]}': #{$!}"
|
391
|
+
end
|
392
|
+
error "Duplicate target definition: '#{target.name}'" if
|
393
|
+
@hash.has_key?(target.name)
|
394
|
+
@hash[target.name] = [target]
|
395
|
+
if !@default
|
396
|
+
@default = target.name
|
397
|
+
@build.default = target.name
|
398
|
+
end
|
399
|
+
end
|
400
|
+
|
401
|
+
# Extend parent targets.
|
402
|
+
# - parent: parent targets.
|
403
|
+
def extend(parent)
|
404
|
+
# set appropriate targets
|
405
|
+
for targets in parent.hash.values
|
406
|
+
for target in targets
|
407
|
+
target.targets = self
|
408
|
+
end
|
409
|
+
end
|
410
|
+
# insert parent targets before current ones
|
411
|
+
for name in parent.hash.keys
|
412
|
+
if @hash[name]
|
413
|
+
@hash[name] = parent.hash[name] + @hash[name]
|
414
|
+
else
|
415
|
+
@hash[name] = parent.hash[name]
|
416
|
+
end
|
417
|
+
end
|
418
|
+
# set default default target to parent one if none was set
|
419
|
+
@default = @default || parent.default
|
420
|
+
end
|
421
|
+
|
422
|
+
# Run targets.
|
423
|
+
# - targets: list of target names to run.
|
424
|
+
def run(targets, dry)
|
425
|
+
error "No default target given" if (!@default and targets.length == 0)
|
426
|
+
targets = [@default] if targets.length == 0
|
427
|
+
for target in targets
|
428
|
+
run_target(target, dry)
|
429
|
+
@already_run.clear
|
430
|
+
end
|
431
|
+
end
|
432
|
+
|
433
|
+
# Call super target.
|
434
|
+
# - target: target that calls super.
|
435
|
+
def call_super(target, dry=false)
|
436
|
+
index = @hash[target.name].index(target)
|
437
|
+
error "No super target to call for '#{target.name}'" if index == 0
|
438
|
+
index -= 1
|
439
|
+
@hash[target.name][index].run(dry)
|
440
|
+
end
|
441
|
+
|
442
|
+
# Tells if a given target is last in hierarchy.
|
443
|
+
# - target: given target.
|
444
|
+
def is_last(target)
|
445
|
+
index = @hash[target.name].index(target)
|
446
|
+
last = @hash[target.name].size - 1
|
447
|
+
return index == last
|
448
|
+
end
|
449
|
+
|
178
450
|
# Run a given target.
|
179
451
|
# - target: the target to run.
|
180
|
-
def run_target(target)
|
181
|
-
error "Target '#{target}' not found" if not @
|
182
|
-
@
|
452
|
+
def run_target(target, dry=false)
|
453
|
+
error "Target '#{target}' not found" if not @hash[target]
|
454
|
+
if not @already_run.include?(target)
|
455
|
+
@already_run << target
|
456
|
+
@hash[target].last.run(dry)
|
457
|
+
end
|
183
458
|
end
|
184
459
|
|
460
|
+
# Return targets description as a hash of descriptions indexed by
|
461
|
+
# target name. Dependencies are added after target description.
|
462
|
+
def description
|
463
|
+
description = {}
|
464
|
+
for name in @hash.keys
|
465
|
+
text = @hash[name].last.description
|
466
|
+
depends = ' [' + @hash[name].last.depends.join(', ') + ']' if
|
467
|
+
@hash[name].last.depends and @hash[name].last.depends.length > 0
|
468
|
+
description[name] = (text ? text : '') + (depends ? depends : '')
|
469
|
+
end
|
470
|
+
return description
|
471
|
+
end
|
472
|
+
|
185
473
|
end
|
186
|
-
|
474
|
+
|
187
475
|
# Class for a target. It is built from the YAML build file and manages a
|
188
476
|
# target, in particular, tasks execution.
|
189
477
|
class Target
|
190
|
-
|
478
|
+
|
191
479
|
include Bee::Util::BuildErrorMixin
|
192
480
|
include Bee::Util::HashCheckerMixin
|
193
481
|
|
194
|
-
#
|
195
|
-
|
482
|
+
# Target key.
|
483
|
+
KEY = 'target'
|
484
|
+
# Target entry description.
|
485
|
+
DESCRIPTION = {
|
486
|
+
'target' => :mandatory,
|
487
|
+
'depends' => :optional,
|
488
|
+
'description' => :optional,
|
489
|
+
'script' => :optional}
|
490
|
+
|
491
|
+
# Targets for build.
|
492
|
+
attr_accessor :targets
|
196
493
|
# Name of the target.
|
197
494
|
attr_reader :name
|
198
495
|
# Target dependencies.
|
@@ -201,116 +498,118 @@ module Bee
|
|
201
498
|
attr_reader :description
|
202
499
|
# Script that run in the target.
|
203
500
|
attr_reader :script
|
204
|
-
|
501
|
+
|
205
502
|
# Constructor.
|
206
503
|
# - object: object for target, resulting from YAML parsing.
|
207
|
-
# -
|
208
|
-
def initialize(object,
|
209
|
-
check_hash(object,
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
'script' => :optional})
|
214
|
-
@build = build
|
215
|
-
@name = object['target']
|
504
|
+
# - targets: build targets.
|
505
|
+
def initialize(object, targets)
|
506
|
+
check_hash(object, Target::DESCRIPTION)
|
507
|
+
@targets = targets
|
508
|
+
@name = object[Target::KEY]
|
509
|
+
error "Target name cannot be 'null'" if @name == nil
|
216
510
|
@depends = object['depends']||[]
|
511
|
+
@depends = Array(@depends)
|
217
512
|
@description = object['description']
|
218
513
|
@script = object['script']
|
514
|
+
@script = [@script] if @script.kind_of?(String)
|
515
|
+
@script = [] if not @script
|
219
516
|
end
|
220
|
-
|
517
|
+
|
221
518
|
# Run target.
|
222
|
-
|
519
|
+
# - dry: tells if we run in dry mode. Defaults to false.
|
520
|
+
def run(dry=false)
|
521
|
+
current_dir = Dir.pwd
|
223
522
|
begin
|
224
|
-
|
225
|
-
@
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
case @script
|
232
|
-
when String
|
233
|
-
run_task(@script)
|
234
|
-
when Array
|
235
|
-
for task in @script
|
236
|
-
run_task(task)
|
237
|
-
end
|
238
|
-
end
|
239
|
-
end
|
523
|
+
for depend in @depends
|
524
|
+
@targets.run_target(depend, dry)
|
525
|
+
end
|
526
|
+
@targets.build.listener.target(self) if
|
527
|
+
@targets.build.listener and @targets.is_last(self)
|
528
|
+
for task in @script
|
529
|
+
run_task(task, dry)
|
240
530
|
end
|
241
531
|
ensure
|
242
|
-
Dir.chdir(
|
532
|
+
Dir.chdir(current_dir)
|
243
533
|
end
|
244
534
|
end
|
245
|
-
|
535
|
+
|
246
536
|
private
|
247
|
-
|
537
|
+
|
248
538
|
# Run a task.
|
249
539
|
# - task: the task to run.
|
250
|
-
|
251
|
-
|
540
|
+
# - dry: whether to just print.
|
541
|
+
def run_task(task, dry=false)
|
542
|
+
@targets.build.listener.task(task) if @targets.build.listener
|
252
543
|
case task
|
253
544
|
when String
|
254
545
|
# shell script
|
255
|
-
run_shell(task)
|
546
|
+
run_shell(task, dry)
|
256
547
|
when Hash
|
257
548
|
error "A task entry must be a Hash with a single key" if
|
258
549
|
task.keys.length != 1
|
259
550
|
if task.key?('rb')
|
260
551
|
# ruby script
|
261
552
|
script = task['rb']
|
262
|
-
run_ruby(script)
|
553
|
+
run_ruby(script, dry)
|
554
|
+
elsif task.key?('super')
|
555
|
+
# call super target
|
556
|
+
targets.call_super(self, dry)
|
263
557
|
else
|
264
558
|
# must be a task
|
265
|
-
run_bee_task(task)
|
559
|
+
run_bee_task(task, dry)
|
266
560
|
end
|
267
561
|
end
|
268
562
|
end
|
269
|
-
|
563
|
+
|
270
564
|
# Run a given shell script.
|
271
565
|
# - script: the scrip to run.
|
272
|
-
def run_shell(script)
|
566
|
+
def run_shell(script, dry=false)
|
273
567
|
@listener.task(script) if @listener
|
274
|
-
|
275
|
-
|
276
|
-
|
568
|
+
return if dry
|
569
|
+
evaluated_script = @targets.build.context.evaluate_object(script)
|
570
|
+
if evaluated_script != ''
|
571
|
+
system(evaluated_script)
|
572
|
+
error "Script exited with value #{$?}" if $? != 0
|
573
|
+
end
|
277
574
|
end
|
278
|
-
|
575
|
+
|
279
576
|
# Run a given shell script.
|
280
577
|
# - script: the scrip to run.
|
281
|
-
|
578
|
+
# - dry: tells if we run in dry mode.
|
579
|
+
def run_ruby(script, dry=false)
|
282
580
|
@listener.task(script) if @listener
|
581
|
+
return if dry
|
283
582
|
begin
|
284
|
-
@build.context.evaluate_script(script)
|
583
|
+
@targets.build.context.evaluate_script(script)
|
285
584
|
rescue Exception
|
286
585
|
error "Error running Ruby script: #{$!}"
|
287
586
|
end
|
288
587
|
end
|
289
|
-
|
588
|
+
|
290
589
|
# Run a given bee task.
|
291
590
|
# - task: task to run as a Hash.
|
292
|
-
def run_bee_task(task)
|
293
|
-
require 'bee_task'
|
591
|
+
def run_bee_task(task, dry=false)
|
294
592
|
@listener.task(task) if @listener
|
295
|
-
|
593
|
+
return if dry
|
594
|
+
@targets.build.package_manager.run_task(task)
|
296
595
|
end
|
297
|
-
|
298
|
-
end
|
299
596
|
|
597
|
+
end
|
598
|
+
|
300
599
|
# Class for Ruby scripts context. All embedded Ruby scripts run in this
|
301
600
|
# context where build properties are defined as Ruby variables.
|
302
601
|
class Context
|
303
|
-
|
602
|
+
|
304
603
|
include Bee::Util::BuildErrorMixin
|
305
|
-
|
604
|
+
|
306
605
|
# The binding of this context.
|
307
606
|
attr_reader :context_binding
|
308
|
-
|
607
|
+
|
309
608
|
# Constructor.
|
310
609
|
def initialize
|
311
610
|
@context_binding = get_binding
|
312
611
|
end
|
313
|
-
|
612
|
+
|
314
613
|
# Set a given property in context.
|
315
614
|
# - name: the property name.
|
316
615
|
# - value: the property value.
|
@@ -324,7 +623,7 @@ module Bee
|
|
324
623
|
error "Error setting property '#{name} = #{value.inspect}': #{$!}"
|
325
624
|
end
|
326
625
|
end
|
327
|
-
|
626
|
+
|
328
627
|
# Get a given property in context.
|
329
628
|
# - name: the property name.
|
330
629
|
# - strict: raise an error if given property was not set.
|
@@ -333,6 +632,8 @@ module Bee
|
|
333
632
|
strict and !properties.include?(name.to_s)
|
334
633
|
begin
|
335
634
|
eval("#{name}", @context_binding)
|
635
|
+
rescue NameError
|
636
|
+
error "Property '#{name}' was not set"
|
336
637
|
rescue Exception
|
337
638
|
error "Error getting property '#{name}': #{$!}"
|
338
639
|
end
|
@@ -342,13 +643,13 @@ module Bee
|
|
342
643
|
def properties
|
343
644
|
return eval('local_variables', @context_binding)
|
344
645
|
end
|
345
|
-
|
646
|
+
|
346
647
|
# Evaluate a script in context.
|
347
|
-
# - script: script to evaluate.
|
648
|
+
# - script: source of the script to evaluate.
|
348
649
|
def evaluate_script(script)
|
349
650
|
eval(script, @context_binding)
|
350
651
|
end
|
351
|
-
|
652
|
+
|
352
653
|
# Process a given object, replacing properties references with their
|
353
654
|
# string value, symbol with their raw value. Property references have
|
354
655
|
# same form than variable references in ruby strings: '#{variable}'
|
@@ -387,14 +688,14 @@ module Bee
|
|
387
688
|
return object
|
388
689
|
end
|
389
690
|
end
|
390
|
-
|
691
|
+
|
391
692
|
private
|
392
|
-
|
693
|
+
|
393
694
|
# Get a binding as script context.
|
394
695
|
def get_binding
|
395
696
|
return binding
|
396
697
|
end
|
397
|
-
|
698
|
+
|
398
699
|
end
|
399
|
-
|
700
|
+
|
400
701
|
end
|