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/README
CHANGED
data/egg/application.yml
CHANGED
@@ -3,8 +3,8 @@
|
|
3
3
|
description: "Generate a sample Ruby application project"
|
4
4
|
|
5
5
|
- properties:
|
6
|
-
|
7
|
-
|
6
|
+
name: application
|
7
|
+
description: |
|
8
8
|
This script will create a sample Ruby application project. Build file
|
9
9
|
can run unit tests, generate API documentation, generate GEM archive
|
10
10
|
and build a ZIP distribution file.
|
data/egg/application/build.yml
CHANGED
@@ -5,30 +5,30 @@
|
|
5
5
|
|
6
6
|
# Build properties
|
7
7
|
- properties:
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
8
|
+
name: "<%= name %>"
|
9
|
+
version: ~
|
10
|
+
author: ~
|
11
|
+
years: ~
|
12
|
+
platform: "Gem::Platform::RUBY"
|
13
|
+
summary: ~
|
14
|
+
email: ~
|
15
|
+
homepage: ~
|
16
|
+
rubyforge: ~
|
17
|
+
dependencies:
|
18
18
|
bee: [">= 0.7.0"]
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
19
|
+
lib_dir: "lib"
|
20
|
+
test_dir: "test"
|
21
|
+
build_dir: "build"
|
22
|
+
api_dir: "#{build_dir}/api"
|
23
|
+
gem_spec: "gem.spec"
|
24
|
+
gem_spec_erb: "gem.spec.erb"
|
25
|
+
gem_package: "#{name}-#{version}.gem"
|
26
|
+
rdoc_files: ["#{lib_dir}/*.rb"]
|
27
|
+
zip_excludes: ["**/CVS", "**/.DS_Store", "**/*~"]
|
28
|
+
zip_prefix: "#{name}-#{version}"
|
29
|
+
zip_archive: "#{build_dir}/#{name}-#{version}.zip"
|
30
|
+
clean_dirs: [:build_dir]
|
31
|
+
clean_files: ["**/*~", "**/.#*", "**/.DS_Store", :gem_spec]
|
32
32
|
|
33
33
|
# Build targets
|
34
34
|
- target: test
|
data/egg/package.yml
CHANGED
@@ -3,8 +3,8 @@
|
|
3
3
|
description: "Generate a bee package project"
|
4
4
|
|
5
5
|
- properties:
|
6
|
-
|
7
|
-
|
6
|
+
project_name: bee_hello
|
7
|
+
description: |
|
8
8
|
This script will create a project for a bee package with sample task (in
|
9
9
|
'lib' directory) and template (in 'egg' directory). A unit test for the
|
10
10
|
task is generated in 'test' directory. Generated build file has a target
|
data/egg/package/build.erb
CHANGED
@@ -6,28 +6,28 @@
|
|
6
6
|
|
7
7
|
# Build properties
|
8
8
|
- properties:
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
9
|
+
name: <%= project_name %>
|
10
|
+
version: 0.0.1
|
11
|
+
author: ~
|
12
|
+
years: ~
|
13
|
+
platform: "Gem::Platform::RUBY"
|
14
|
+
summary: ~
|
15
|
+
email: ~
|
16
|
+
homepage: "http://<%= project_name %>.rubyforge.org"
|
17
|
+
rubyforge: ~
|
18
|
+
dependencies:
|
19
19
|
"bee": [">= 0.5.0"]
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
20
|
+
lib_dir: "lib"
|
21
|
+
test_dir: "test"
|
22
|
+
build_dir: "build"
|
23
|
+
readme_erb: "readme.erb"
|
24
|
+
readme_file: "#{build_dir}/README"
|
25
|
+
license_file: "LICENSE"
|
26
|
+
gem_spec_erb: "gem.spec.erb"
|
27
|
+
gem_spec: "#{build_dir}/gem.spec"
|
28
|
+
gem_package: "#{name}-#{version}.gem"
|
29
|
+
clean_dirs: :build_dir
|
30
|
+
clean_files: ""
|
31
31
|
|
32
32
|
# Build targets
|
33
33
|
- target: test
|
data/egg/package/egg.yml
CHANGED
@@ -3,8 +3,8 @@
|
|
3
3
|
description: "Generate a project for a Ruby script"
|
4
4
|
|
5
5
|
- properties:
|
6
|
-
|
7
|
-
|
6
|
+
project_name: hello
|
7
|
+
description: |
|
8
8
|
This script will create a project for a Ruby script that might be
|
9
9
|
distributed as a gem. Generated build file has a single target gem
|
10
10
|
to generate the distribution gem.
|
data/egg/package/egg_build.erb
CHANGED
@@ -3,11 +3,11 @@
|
|
3
3
|
default: all
|
4
4
|
|
5
5
|
- properties:
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
6
|
+
name: <%= project_name %>
|
7
|
+
version: 0.0.1
|
8
|
+
build: build
|
9
|
+
gem_spec: "#{build}/gem_spec"
|
10
|
+
gem_erb: |
|
11
11
|
require 'rubygems'
|
12
12
|
SPEC = Gem::Specification.new do |spec|
|
13
13
|
spec.name = '<%= name %>'
|
data/egg/script.yml
CHANGED
@@ -3,8 +3,8 @@
|
|
3
3
|
description: "Generate a sample Ruby script project"
|
4
4
|
|
5
5
|
- properties:
|
6
|
-
|
7
|
-
|
6
|
+
name: script
|
7
|
+
description: This script will generate a sample Ruby script project.
|
8
8
|
|
9
9
|
- target: welcome
|
10
10
|
description: "Print information message"
|
data/egg/script/build.yml
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
# Build properties
|
7
7
|
- properties:
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
8
|
+
name: "<%= name %>"
|
9
|
+
version: "0.0.0"
|
10
|
+
build: "build"
|
11
|
+
clean_dirs: [:build]
|
12
|
+
clean_files: ["**/*~", "**/.#*", "**/.DS_Store"]
|
13
13
|
|
14
14
|
# Build targets
|
15
15
|
- target: zip
|
data/egg/sinatra.yml
CHANGED
@@ -3,8 +3,8 @@
|
|
3
3
|
description: "Generate a Sinatra project"
|
4
4
|
|
5
5
|
- properties:
|
6
|
-
|
7
|
-
|
6
|
+
name: sinatra
|
7
|
+
description: |
|
8
8
|
This script will create a Sinatra project. Generated build file has a
|
9
9
|
target 'run' to run the server, 'zip' to generate a distribution archive
|
10
10
|
and 'clean' to delete generated files.
|
data/egg/sinatra/build.yml
CHANGED
@@ -3,14 +3,14 @@
|
|
3
3
|
default: all
|
4
4
|
|
5
5
|
- properties:
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
6
|
+
name: "<%= name %>"
|
7
|
+
version: "0.0.0"
|
8
|
+
build: "build"
|
9
|
+
zip_prefix: "#{name}-#{version}"
|
10
|
+
zip_file: "#{build}/#{zip_prefix}.zip"
|
11
|
+
url: "http://localhost:4567/hello"
|
12
|
+
clean_dirs: [:build]
|
13
|
+
clean_files: ["**/*~", "**/.#*", "**/.DS_Store"]
|
14
14
|
|
15
15
|
- target: run
|
16
16
|
description: Run server
|
data/egg/source.yml
CHANGED
@@ -3,8 +3,8 @@
|
|
3
3
|
description: Generate a sample Ruby source file
|
4
4
|
|
5
5
|
- properties:
|
6
|
-
|
7
|
-
|
6
|
+
name: source.rb
|
7
|
+
description: This script will generate a sample Ruby source file.
|
8
8
|
|
9
9
|
- target: welcome
|
10
10
|
description: Print information message
|
data/egg/xmlrpc.yml
CHANGED
data/egg/xmlrpc/build.yml
CHANGED
@@ -5,12 +5,12 @@
|
|
5
5
|
|
6
6
|
# Build properties
|
7
7
|
- properties:
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
8
|
+
name: <%= project_name %>
|
9
|
+
version: "0.0.0"
|
10
|
+
build: "build"
|
11
|
+
zip: "#{build}/#{name}-#{version}.zip"
|
12
|
+
clean_dirs: [:build]
|
13
|
+
clean_files: ["**/*~", "**/.#*", "**/.DS_Store"]
|
14
14
|
|
15
15
|
# Build targets
|
16
16
|
- target: server
|
data/lib/bee.rb
CHANGED
@@ -15,7 +15,10 @@
|
|
15
15
|
require 'rubygems'
|
16
16
|
require 'yaml'
|
17
17
|
require 'bee_task'
|
18
|
+
require 'bee_target'
|
18
19
|
require 'bee_util'
|
20
|
+
require 'bee_context'
|
21
|
+
require 'bee_properties'
|
19
22
|
|
20
23
|
# Module for Bee core classes.
|
21
24
|
module Bee
|
@@ -36,7 +39,6 @@ module Bee
|
|
36
39
|
'description' => :optional,
|
37
40
|
'context' => :optional,
|
38
41
|
'extends' => :optional,
|
39
|
-
'includes' => :optional,
|
40
42
|
'abstract' => :optional
|
41
43
|
}
|
42
44
|
|
@@ -50,8 +52,6 @@ module Bee
|
|
50
52
|
attr_reader :name
|
51
53
|
# Parent build.
|
52
54
|
attr_reader :extends
|
53
|
-
# Included builds
|
54
|
-
attr_reader :includes
|
55
55
|
# Abstractness.
|
56
56
|
attr_reader :abstract
|
57
57
|
# Default target, specified with default entry or fist target in build file.
|
@@ -108,8 +108,8 @@ module Bee
|
|
108
108
|
@file = file
|
109
109
|
@base = get_base(@file)
|
110
110
|
@here = here
|
111
|
-
@context = Context.new
|
112
111
|
@properties = Properties.new(self)
|
112
|
+
@context = Context.new(@properties)
|
113
113
|
@properties.evaluate(@context)
|
114
114
|
@targets = Targets.new(self)
|
115
115
|
parse(object)
|
@@ -172,16 +172,11 @@ module Bee
|
|
172
172
|
error "Unknown entry:\n#{YAML::dump(entry)}"
|
173
173
|
end
|
174
174
|
end
|
175
|
-
# manage
|
176
|
-
if @
|
177
|
-
@
|
178
|
-
|
179
|
-
|
180
|
-
# manage included builds
|
181
|
-
if @included
|
182
|
-
for include in @included.reverse
|
183
|
-
@properties.include(include.properties)
|
184
|
-
@targets.include(include.targets)
|
175
|
+
# manage extended builds
|
176
|
+
if @extends
|
177
|
+
for parent in @extends
|
178
|
+
@properties.extend(parent.properties)
|
179
|
+
@targets.extend(parent.targets)
|
185
180
|
end
|
186
181
|
end
|
187
182
|
end
|
@@ -199,33 +194,46 @@ module Bee
|
|
199
194
|
@default = entry['default']
|
200
195
|
@targets.default = @default
|
201
196
|
@description = entry['description']
|
202
|
-
@extends = entry['extends']
|
203
|
-
@includes = Array(entry['includes'])
|
204
197
|
@abstract = entry['abstract']
|
205
|
-
# load
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
error "Error loading parent build file '#{@extends}': #{$!}"
|
212
|
-
end
|
213
|
-
@default = @default || @parent.default
|
214
|
-
@targets.default = @default
|
215
|
-
@description = @description || @parent.description
|
216
|
-
end
|
217
|
-
# load included build files if any
|
218
|
-
if @includes
|
219
|
-
@included = []
|
220
|
-
for include in @includes
|
221
|
-
absolute_path = Bee::Util::absolute_path(include, @base)
|
198
|
+
# load parents build if any
|
199
|
+
parents = Array(entry['extends'])
|
200
|
+
if parents.length > 0
|
201
|
+
@extends = []
|
202
|
+
for extended in parents
|
203
|
+
absolute_path = Bee::Util::absolute_path(extended, @base)
|
222
204
|
begin
|
223
|
-
@
|
205
|
+
@extends << Bee::Build::load(absolute_path)
|
224
206
|
rescue Exception
|
225
|
-
error "Error loading
|
207
|
+
error "Error loading parent build file '#{extended}': #{$!}"
|
226
208
|
end
|
227
209
|
end
|
228
210
|
end
|
211
|
+
# check that there are no property and target collisions in parents
|
212
|
+
if @extends
|
213
|
+
properties = []
|
214
|
+
collisions = []
|
215
|
+
for parent in @extends
|
216
|
+
parent_properties = parent.properties.expressions.keys
|
217
|
+
collisions += properties & parent_properties
|
218
|
+
properties += parent_properties
|
219
|
+
end
|
220
|
+
collisions = collisions - Properties::SYSTEM_PROPERTIES
|
221
|
+
collisions = collisions.uniq.map { |e| e.to_s }.sort
|
222
|
+
if collisions.length > 0
|
223
|
+
error "Properties in parents are colliding: #{collisions.join(', ')}"
|
224
|
+
end
|
225
|
+
targets = []
|
226
|
+
collisions = []
|
227
|
+
for parent in @extends
|
228
|
+
parent_targets = parent.targets.hash.keys
|
229
|
+
collisions += targets & parent_targets
|
230
|
+
targets += parent_targets
|
231
|
+
end
|
232
|
+
collisions = collisions.uniq.map { |e| e.to_s }.sort
|
233
|
+
if collisions.length > 0
|
234
|
+
error "Targets in parents are colliding: #{collisions.join(', ')}"
|
235
|
+
end
|
236
|
+
end
|
229
237
|
# load context files if any
|
230
238
|
context = entry['context']
|
231
239
|
if context
|
@@ -258,146 +266,6 @@ module Bee
|
|
258
266
|
|
259
267
|
end
|
260
268
|
|
261
|
-
# Class to manage properties.
|
262
|
-
class Properties
|
263
|
-
|
264
|
-
include Bee::Util::BuildErrorMixin
|
265
|
-
|
266
|
-
# Key for properties entry.
|
267
|
-
KEY = 'properties'
|
268
|
-
|
269
|
-
# List of system properties
|
270
|
-
SYSTEM_PROPERTIES = [:base, :here]
|
271
|
-
|
272
|
-
# List of properties in order of evaluation.
|
273
|
-
attr_reader :list
|
274
|
-
# Hash of properties by name.
|
275
|
-
attr_reader :hash
|
276
|
-
|
277
|
-
# Constructor.
|
278
|
-
# - build: build object.
|
279
|
-
def initialize(build)
|
280
|
-
@list = []
|
281
|
-
@hash = {}
|
282
|
-
@build = build
|
283
|
-
defaults
|
284
|
-
end
|
285
|
-
|
286
|
-
# Write properties. Will raise an error on duplicate definitions.
|
287
|
-
# - object: object tree resulting from YAML build file parsing or string
|
288
|
-
# for a properties file to load.
|
289
|
-
def write(object)
|
290
|
-
properties = object[Properties::KEY]
|
291
|
-
if properties.kind_of?(String)
|
292
|
-
begin
|
293
|
-
source = Bee::Util::get_file(properties, @build.base)
|
294
|
-
list = YAML::load(source)
|
295
|
-
set_properties(list, false)
|
296
|
-
rescue Exception
|
297
|
-
error "Error loading properties file '#{properties}': #{$!}"
|
298
|
-
end
|
299
|
-
else
|
300
|
-
set_properties(properties, false)
|
301
|
-
end
|
302
|
-
end
|
303
|
-
|
304
|
-
# Overwrite properties. Will raise an error if properties don't already
|
305
|
-
# exist.
|
306
|
-
# - object: object tree resulting from YAML build file parsing.
|
307
|
-
def overwrite(object)
|
308
|
-
set_properties(object, true)
|
309
|
-
end
|
310
|
-
|
311
|
-
# Extend with properties of parent build.
|
312
|
-
# - properties: properties of parent build.
|
313
|
-
def extend(properties)
|
314
|
-
current_list = @list
|
315
|
-
current_hash = @hash
|
316
|
-
@list = properties.list
|
317
|
-
@hash = properties.hash
|
318
|
-
index = 0
|
319
|
-
0.upto(current_list.length - 1) do |current|
|
320
|
-
name = current_list[current]
|
321
|
-
pos = @list.index(name)
|
322
|
-
if pos
|
323
|
-
sub = current_list[index .. current]
|
324
|
-
@list[pos .. pos] = sub
|
325
|
-
for name in sub
|
326
|
-
@hash[name] = current_hash[name]
|
327
|
-
end
|
328
|
-
index = current + 1
|
329
|
-
end
|
330
|
-
end
|
331
|
-
tail = current_list[index .. current_list.length() - 1]
|
332
|
-
@list += tail
|
333
|
-
for name in tail
|
334
|
-
@hash[name] = current_hash[name]
|
335
|
-
end
|
336
|
-
end
|
337
|
-
|
338
|
-
# Include properties of included build.
|
339
|
-
# - properties: properties of parent build.
|
340
|
-
def include(properties)
|
341
|
-
extend(properties)
|
342
|
-
end
|
343
|
-
|
344
|
-
# Evaluate properties in context.
|
345
|
-
# - context: build context where properties must be evaluated.
|
346
|
-
def evaluate(context)
|
347
|
-
for name in @list
|
348
|
-
begin
|
349
|
-
value = context.evaluate_object(@hash[name])
|
350
|
-
rescue Bee::Util::BuildError
|
351
|
-
error "Error evaluating property '#{name}': #{$!}"
|
352
|
-
end
|
353
|
-
context.set_property(name, value, true)
|
354
|
-
end
|
355
|
-
end
|
356
|
-
|
357
|
-
private
|
358
|
-
|
359
|
-
# Set default properties.
|
360
|
-
def defaults
|
361
|
-
set(:base, @build.base, false)
|
362
|
-
set(:here, @build.here, false)
|
363
|
-
end
|
364
|
-
|
365
|
-
# Set properties.
|
366
|
-
# - properties: properties as a list of hash if overwrite = false
|
367
|
-
# or a hash if overwrite = true.
|
368
|
-
# - overwrite: tells if we can overwrite existing properties.
|
369
|
-
def set_properties(properties, overwrite)
|
370
|
-
if overwrite
|
371
|
-
raise "Properties must be a hash" if not properties.kind_of?(Hash)
|
372
|
-
for name in properties.keys
|
373
|
-
expression = properties[name]
|
374
|
-
set(name, expression, overwrite)
|
375
|
-
end
|
376
|
-
else
|
377
|
-
raise "Properties must be a list" if not properties.kind_of?(Array)
|
378
|
-
for property in properties
|
379
|
-
name = property.keys[0]
|
380
|
-
expression = property[name]
|
381
|
-
set(name, expression, overwrite)
|
382
|
-
end
|
383
|
-
end
|
384
|
-
end
|
385
|
-
|
386
|
-
# Set a property.
|
387
|
-
# - name: property name (as a string or symbol).
|
388
|
-
# - expression: property expression (as a string) to be evaluated in
|
389
|
-
# context to get value.
|
390
|
-
# - overwrite: tells if we can overwrite existing properties.
|
391
|
-
def set(name, expression, overwrite)
|
392
|
-
name = name.to_sym
|
393
|
-
error "Duplicate property definition: '#{name}'" if
|
394
|
-
not overwrite and @hash.has_key?(name)
|
395
|
-
@list << name
|
396
|
-
@hash[name] = expression
|
397
|
-
end
|
398
|
-
|
399
|
-
end
|
400
|
-
|
401
269
|
# Class to manage targets in a build.
|
402
270
|
class Targets
|
403
271
|
|
@@ -470,25 +338,6 @@ module Bee
|
|
470
338
|
@default = @default || parent.default
|
471
339
|
end
|
472
340
|
|
473
|
-
# Include included build file targets.
|
474
|
-
# - included: included build file targets.
|
475
|
-
def include(included)
|
476
|
-
# set appropriate targets for targets of parent
|
477
|
-
for targets in included.hash.values
|
478
|
-
for target in targets
|
479
|
-
target.targets = self
|
480
|
-
end
|
481
|
-
end
|
482
|
-
# look for targets already defined
|
483
|
-
duplicates = @hash.keys & included.hash.keys
|
484
|
-
error "Included target(s) '#{duplicates.join('\', \'')}' already defined" if
|
485
|
-
duplicates.length > 0
|
486
|
-
# insert included targets
|
487
|
-
for name in included.hash.keys
|
488
|
-
@hash[name] = included.hash[name]
|
489
|
-
end
|
490
|
-
end
|
491
|
-
|
492
341
|
# Run targets.
|
493
342
|
# - targets: list of target names to run.
|
494
343
|
def run(targets, dry)
|
@@ -543,380 +392,6 @@ module Bee
|
|
543
392
|
return description
|
544
393
|
end
|
545
394
|
|
546
|
-
end
|
547
|
-
|
548
|
-
# Class for a target. It is built from the YAML build file and manages a
|
549
|
-
# target, in particular, tasks execution.
|
550
|
-
class Target
|
551
|
-
|
552
|
-
include Bee::Util::BuildErrorMixin
|
553
|
-
include Bee::Util::HashCheckerMixin
|
554
|
-
|
555
|
-
# Target key.
|
556
|
-
KEY = 'target'
|
557
|
-
# Target entry description.
|
558
|
-
DESCRIPTION = {
|
559
|
-
'target' => :mandatory,
|
560
|
-
'depends' => :optional,
|
561
|
-
'description' => :optional,
|
562
|
-
'script' => :optional}
|
563
|
-
|
564
|
-
# Targets for build.
|
565
|
-
attr_accessor :targets
|
566
|
-
# Name of the target.
|
567
|
-
attr_reader :name
|
568
|
-
# Target dependencies.
|
569
|
-
attr_accessor :depends
|
570
|
-
# Target description.
|
571
|
-
attr_accessor :description
|
572
|
-
# Script that run in the target.
|
573
|
-
attr_reader :script
|
574
|
-
|
575
|
-
# Constructor.
|
576
|
-
# - object: object for target, resulting from YAML parsing.
|
577
|
-
# - targets: build targets.
|
578
|
-
def initialize(object, targets)
|
579
|
-
check_hash(object, Target::DESCRIPTION)
|
580
|
-
@targets = targets
|
581
|
-
@name = object[Target::KEY]
|
582
|
-
error "Target name cannot be 'null'" if @name == nil
|
583
|
-
@depends = object['depends']||[]
|
584
|
-
@depends = Array(@depends)
|
585
|
-
@description = object['description']
|
586
|
-
@script = object['script']
|
587
|
-
@script = [@script] if @script.kind_of?(String)
|
588
|
-
@script = [] if not @script
|
589
|
-
end
|
590
|
-
|
591
|
-
# Run target.
|
592
|
-
# - dry: tells if we run in dry mode. Defaults to false.
|
593
|
-
def run(dry=false)
|
594
|
-
current_dir = Dir.pwd
|
595
|
-
begin
|
596
|
-
for depend in @depends
|
597
|
-
@targets.run_target(depend, dry)
|
598
|
-
end
|
599
|
-
@targets.build.listener.target(self) if
|
600
|
-
@targets.build.listener and @targets.is_last(self)
|
601
|
-
run_block(@script, dry)
|
602
|
-
ensure
|
603
|
-
Dir.chdir(current_dir)
|
604
|
-
end
|
605
|
-
end
|
606
|
-
|
607
|
-
private
|
608
|
-
|
609
|
-
# Run a task.
|
610
|
-
# - task: the task to run.
|
611
|
-
# - dry: whether to just print.
|
612
|
-
def run_task(task, dry=false)
|
613
|
-
@targets.build.listener.task(task) if @targets.build.listener
|
614
|
-
case task
|
615
|
-
when String
|
616
|
-
# shell script
|
617
|
-
run_shell(task, dry)
|
618
|
-
when Hash
|
619
|
-
if task.keys.length > 1
|
620
|
-
# construct
|
621
|
-
run_construct(task, dry)
|
622
|
-
else
|
623
|
-
if task.key?('rb')
|
624
|
-
# ruby script
|
625
|
-
script = task['rb']
|
626
|
-
run_ruby(script, dry)
|
627
|
-
elsif task.key?('sh')
|
628
|
-
# shell script
|
629
|
-
script = task['sh']
|
630
|
-
run_shell(script, dry)
|
631
|
-
elsif task.key?('super')
|
632
|
-
# call super target
|
633
|
-
targets.call_super(self, dry)
|
634
|
-
else
|
635
|
-
# must be a task
|
636
|
-
run_bee_task(task, dry)
|
637
|
-
end
|
638
|
-
end
|
639
|
-
end
|
640
|
-
end
|
641
|
-
|
642
|
-
# Run a given shell script.
|
643
|
-
# - script: the scrip to run.
|
644
|
-
def run_shell(script, dry=false)
|
645
|
-
@listener.task(script) if @listener
|
646
|
-
return if dry
|
647
|
-
evaluated_script = @targets.build.context.evaluate_object(script)
|
648
|
-
if evaluated_script != ''
|
649
|
-
system(evaluated_script)
|
650
|
-
error "Script exited with value #{$?}" if $? != 0
|
651
|
-
end
|
652
|
-
end
|
653
|
-
|
654
|
-
# Run a given shell script.
|
655
|
-
# - script: the scrip to run.
|
656
|
-
# - dry: tells if we run in dry mode.
|
657
|
-
def run_ruby(script, dry=false)
|
658
|
-
@listener.task(script) if @listener
|
659
|
-
return if dry
|
660
|
-
begin
|
661
|
-
@targets.build.context.evaluate_script(script)
|
662
|
-
rescue Exception
|
663
|
-
error "Error running Ruby script: #{$!}"
|
664
|
-
end
|
665
|
-
end
|
666
|
-
|
667
|
-
# Run a given bee task.
|
668
|
-
# - task: task to run as a Hash.
|
669
|
-
def run_bee_task(task, dry=false)
|
670
|
-
@listener.task(task) if @listener
|
671
|
-
return if dry
|
672
|
-
@targets.build.package_manager.run_task(task)
|
673
|
-
end
|
674
|
-
|
675
|
-
# Run a given construct.
|
676
|
-
# - construct: construct to run as a Hash.
|
677
|
-
def run_construct(construct, dry=false)
|
678
|
-
@listener.task(construct) if @listener
|
679
|
-
return if dry
|
680
|
-
# if construct
|
681
|
-
if construct.keys.include?('if')
|
682
|
-
construct_if(construct, dry)
|
683
|
-
# while construct
|
684
|
-
elsif construct.keys.include?('while')
|
685
|
-
construct_while(construct, dry)
|
686
|
-
# for construct
|
687
|
-
elsif construct.keys.include?('for')
|
688
|
-
construct_for(construct, dry)
|
689
|
-
# try construct
|
690
|
-
elsif construct.keys.include?('try')
|
691
|
-
construct_try(construct, dry)
|
692
|
-
else
|
693
|
-
error "Unknown construct '#{construct.keys.join('-')}'"
|
694
|
-
end
|
695
|
-
end
|
696
|
-
|
697
|
-
# Run if construct.
|
698
|
-
# - task: the construct as a hash.
|
699
|
-
# - dry: tells if we run in dry mode.
|
700
|
-
def construct_if(task, dry)
|
701
|
-
# test entries
|
702
|
-
error "If-then-else construct must include 'then' entry" if
|
703
|
-
not task.keys.include?('then')
|
704
|
-
unknown_keys = task.keys - ['if', 'then', 'else']
|
705
|
-
error "If-then-else construct may only include 'if', 'then' and 'else' entries" if
|
706
|
-
unknown_keys.length > 0
|
707
|
-
error "If entry in if-then-else construct must be a string" if
|
708
|
-
not task['if'].kind_of?(String)
|
709
|
-
error "Then entry in if-then-else construct must be a list" if
|
710
|
-
not task['then'].kind_of?(Array)
|
711
|
-
error "Else entry in if-then-else construct must be a list" if
|
712
|
-
task['else'] and not task['else'].kind_of?(Array)
|
713
|
-
# evaluate condition in the build context
|
714
|
-
if evaluate(task['if'])
|
715
|
-
run_block(task['then'], dry)
|
716
|
-
else
|
717
|
-
run_block(task['else'], dry) if task['else']
|
718
|
-
end
|
719
|
-
end
|
720
|
-
|
721
|
-
# Run while construct.
|
722
|
-
# - task: the construct as a hash.
|
723
|
-
# - dry: tells if we run in dry mode.
|
724
|
-
def construct_while(task, dry)
|
725
|
-
# test entries
|
726
|
-
error "While-do construct must include 'do' entry" if
|
727
|
-
not task.keys.include?('do')
|
728
|
-
unknown_keys = task.keys - ['while', 'do']
|
729
|
-
error "While-do construct may only include 'while' and 'do' entries" if
|
730
|
-
unknown_keys.length > 0
|
731
|
-
error "While entry in while-do construct must be a string" if
|
732
|
-
not task['while'].kind_of?(String)
|
733
|
-
error "Do entry in while-do construct must be a list" if
|
734
|
-
not task['do'].kind_of?(Array)
|
735
|
-
# evaluate condition in the build context
|
736
|
-
while evaluate(task['while'])
|
737
|
-
run_block(task['do'], dry)
|
738
|
-
end
|
739
|
-
end
|
740
|
-
|
741
|
-
# Run for construct.
|
742
|
-
# - task: the construct as a hash.
|
743
|
-
# - dry: tells if we run in dry mode.
|
744
|
-
def construct_for(task, dry)
|
745
|
-
# test entries
|
746
|
-
error "For-in-do construct must include 'in' and 'do' entries" if
|
747
|
-
not task.keys.include?('in') or not task.keys.include?('do')
|
748
|
-
unknown_keys = task.keys - ['for', 'in', 'do']
|
749
|
-
error "For-in-do construct may only include 'for', 'in' and 'do' entries" if
|
750
|
-
unknown_keys.length > 0
|
751
|
-
error "For entry in for-in-do construct must be a string" if
|
752
|
-
not task['for'].kind_of?(String)
|
753
|
-
error "In entry in for-in-do construct must be a list or a string" if
|
754
|
-
not task['in'].kind_of?(Enumerable) and not task['in'].kind_of?(String)
|
755
|
-
error "Do entry in for-in-do construct must be a list" if
|
756
|
-
not task['do'].kind_of?(Array)
|
757
|
-
# iterate over list
|
758
|
-
if task['in'].kind_of?(String)
|
759
|
-
enumerable = evaluate(@targets.build.context.
|
760
|
-
evaluate_object(task['in']))
|
761
|
-
else
|
762
|
-
enumerable = task['in']
|
763
|
-
end
|
764
|
-
for element in enumerable
|
765
|
-
begin
|
766
|
-
@targets.build.context.set_property(task['for'], element)
|
767
|
-
rescue
|
768
|
-
error "Error setting property '#{task['for']}'"
|
769
|
-
end
|
770
|
-
run_block(task['do'], dry)
|
771
|
-
end
|
772
|
-
end
|
773
|
-
|
774
|
-
# Run try-catch construct.
|
775
|
-
# - task: the construct as a hash.
|
776
|
-
# - dry: tells if we run in dry mode.
|
777
|
-
def construct_try(task, dry)
|
778
|
-
# test entries
|
779
|
-
error "Try-catch construct must include 'catch' entry" if
|
780
|
-
not task.keys.include?('catch')
|
781
|
-
unknown_keys = task.keys - ['try', 'catch']
|
782
|
-
error "Try-catch construct may only include 'try' and 'catch' entries" if
|
783
|
-
unknown_keys.length > 0
|
784
|
-
error "Try entry in try-catch construct must be a list" if
|
785
|
-
not task['try'].kind_of?(Array)
|
786
|
-
error "Catch entry in try-catch construct must be a list" if
|
787
|
-
not task['catch'].kind_of?(Array)
|
788
|
-
# try and catch errors
|
789
|
-
begin
|
790
|
-
run_block(task['try'], dry)
|
791
|
-
rescue
|
792
|
-
@targets.build.listener.recover if @targets.build.listener
|
793
|
-
run_block(task['catch'], dry)
|
794
|
-
end
|
795
|
-
end
|
796
|
-
|
797
|
-
# Run a block, that is a list of tasks.
|
798
|
-
# - block: the block to run as a list of tasks.
|
799
|
-
# - dry: tells if we run in dry mode.
|
800
|
-
def run_block(block, dry)
|
801
|
-
for task in block
|
802
|
-
run_task(task, dry)
|
803
|
-
end
|
804
|
-
end
|
805
|
-
|
806
|
-
# Evaluate a given expression and raise a BuildError if an error happens.
|
807
|
-
def evaluate(expression)
|
808
|
-
begin
|
809
|
-
return @targets.build.context.evaluate_script(expression)
|
810
|
-
rescue
|
811
|
-
error "Error evaluating expression: #{$!}"
|
812
|
-
end
|
813
|
-
end
|
814
|
-
|
815
|
-
end
|
816
|
-
|
817
|
-
# Class for Ruby scripts context. All embedded Ruby scripts run in this
|
818
|
-
# context where build properties are defined as Ruby variables.
|
819
|
-
class Context
|
820
|
-
|
821
|
-
include Bee::Util::BuildErrorMixin
|
822
|
-
|
823
|
-
# The binding of this context.
|
824
|
-
attr_reader :context_binding
|
825
|
-
|
826
|
-
# Constructor.
|
827
|
-
def initialize
|
828
|
-
@context_binding = get_binding
|
829
|
-
end
|
830
|
-
|
831
|
-
# Set a given property in context.
|
832
|
-
# - name: the property name.
|
833
|
-
# - value: the property value.
|
834
|
-
# - override: tells if we can overwrite an existing value.
|
835
|
-
def set_property(name, value, overwrite=true)
|
836
|
-
error "Property '#{name}' was already defined" if
|
837
|
-
!overwrite and properties.include?(name.to_s)
|
838
|
-
begin
|
839
|
-
eval("#{name} = #{value.inspect}", @context_binding)
|
840
|
-
rescue Exception
|
841
|
-
error "Error setting property '#{name} = #{value.inspect}': #{$!}"
|
842
|
-
end
|
843
|
-
end
|
844
|
-
|
845
|
-
# Get a given property in context.
|
846
|
-
# - name: the property name.
|
847
|
-
# - strict: raise an error if given property was not set.
|
848
|
-
def get_property(name, strict=false)
|
849
|
-
error "Property '#{name}' was not set" if
|
850
|
-
strict and !properties.include?(name.to_s)
|
851
|
-
begin
|
852
|
-
eval("#{name}", @context_binding)
|
853
|
-
rescue NameError
|
854
|
-
error "Property '#{name}' was not set"
|
855
|
-
rescue Exception
|
856
|
-
error "Error getting property '#{name}': #{$!}"
|
857
|
-
end
|
858
|
-
end
|
859
|
-
|
860
|
-
# Return list of properties (as local variables of binding).
|
861
|
-
def properties
|
862
|
-
return eval('local_variables', @context_binding).map{ |var| var.to_s }
|
863
|
-
end
|
864
|
-
|
865
|
-
# Evaluate a script in context.
|
866
|
-
# - script: source of the script to evaluate.
|
867
|
-
def evaluate_script(script)
|
868
|
-
eval(script, @context_binding)
|
869
|
-
end
|
870
|
-
|
871
|
-
# Process a given object, replacing properties references with their
|
872
|
-
# string value, symbol with their raw value. Property references have
|
873
|
-
# same form than variable references in ruby strings: '#{variable}'
|
874
|
-
# will be replaced with variable string value.
|
875
|
-
# - object: object to process.
|
876
|
-
def evaluate_object(object)
|
877
|
-
case object
|
878
|
-
when NilClass
|
879
|
-
# nil: return nil
|
880
|
-
return nil
|
881
|
-
when String
|
882
|
-
# string: replace embedded Ruby expressions
|
883
|
-
object = object.gsub(/#\{.+?\}/) do |match|
|
884
|
-
expression = match[2..-2]
|
885
|
-
begin
|
886
|
-
value = evaluate_script(expression)
|
887
|
-
rescue
|
888
|
-
error "Error evaluating expression '#{expression}': #{$!}"
|
889
|
-
end
|
890
|
-
value
|
891
|
-
end
|
892
|
-
return object
|
893
|
-
when Symbol
|
894
|
-
# symbol: return property object
|
895
|
-
property = object.to_s
|
896
|
-
value = get_property(property, true)
|
897
|
-
return evaluate_object(value)
|
898
|
-
when Array
|
899
|
-
# array: evaluate each element
|
900
|
-
return object.collect { |element| evaluate_object(element) }
|
901
|
-
when Hash
|
902
|
-
# hash: evaluate all keys and values
|
903
|
-
evaluated = {}
|
904
|
-
object.each_pair do |key, value|
|
905
|
-
evaluated[evaluate_object(key)] = evaluate_object(value)
|
906
|
-
end
|
907
|
-
return evaluated
|
908
|
-
else
|
909
|
-
return object
|
910
|
-
end
|
911
|
-
end
|
912
|
-
|
913
|
-
private
|
914
|
-
|
915
|
-
# Get a binding as script context.
|
916
|
-
def get_binding
|
917
|
-
return binding
|
918
|
-
end
|
919
|
-
|
920
|
-
end
|
395
|
+
end
|
921
396
|
|
922
397
|
end
|