bee 0.3.1 → 0.4.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 +16 -0
- data/bin/bee.bat +32 -0
- data/lib/bee.rb +165 -170
- data/lib/bee_console.rb +90 -87
- data/lib/bee_task.rb +149 -0
- data/lib/bee_task_default.rb +525 -0
- data/lib/bee_util.rb +230 -0
- data/test/tc_bee_build.rb +216 -0
- data/test/tc_bee_console.rb +106 -0
- data/test/tc_bee_console_formatter.rb +38 -3
- data/test/tc_bee_context.rb +84 -0
- data/test/tc_bee_task_default.rb +467 -0
- data/test/tc_bee_util.rb +85 -0
- data/test/test_build.rb +26 -0
- data/test/test_build_listener.rb +60 -0
- data/test/tmp_test_case.rb +58 -0
- data/test/ts_bee.rb +1 -1
- metadata +35 -8
- data/lib/bee_default_context.rb +0 -475
- data/test/tc_bee_default_tasks.rb +0 -298
data/README
CHANGED
data/bin/bee
CHANGED
@@ -1,5 +1,21 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
+
# Copyright 2006-2007 Michel Casabianca <michel.casabianca@gmail.com>
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
|
17
|
+
# Launching script for bee.
|
18
|
+
|
3
19
|
$:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
4
20
|
require 'bee_console'
|
5
21
|
|
data/bin/bee.bat
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
@echo off
|
2
|
+
if not "%~f0" == "~f0" goto WinNT
|
3
|
+
ruby -Sx "%0" %1 %2 %3 %4 %5 %6 %7 %8 %9
|
4
|
+
goto endofruby
|
5
|
+
:WinNT
|
6
|
+
"%~d0%~p0ruby" -x "%~f0" %*
|
7
|
+
goto endofruby
|
8
|
+
#!/usr/bin/env ruby
|
9
|
+
|
10
|
+
# Copyright 2006-2007 Michel Casabianca <michel.casabianca@gmail.com>
|
11
|
+
#
|
12
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
13
|
+
# you may not use this file except in compliance with the License.
|
14
|
+
# You may obtain a copy of the License at
|
15
|
+
#
|
16
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
17
|
+
#
|
18
|
+
# Unless required by applicable law or agreed to in writing, software
|
19
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
20
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
21
|
+
# See the License for the specific language governing permissions and
|
22
|
+
# limitations under the License.
|
23
|
+
|
24
|
+
# Launching script for bee.
|
25
|
+
|
26
|
+
$:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
27
|
+
require 'bee_console'
|
28
|
+
|
29
|
+
Bee::Console.start_command_line
|
30
|
+
|
31
|
+
__END__
|
32
|
+
:endofruby
|
data/lib/bee.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright 2006 Michel Casabianca <
|
1
|
+
# Copyright 2006-2007 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.
|
@@ -12,125 +12,139 @@
|
|
12
12
|
# See the License for the specific language governing permissions and
|
13
13
|
# limitations under the License.
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
require 'yaml'
|
19
|
-
|
20
|
-
#########################################################################
|
21
|
-
# BUILD ERROR #
|
22
|
-
#########################################################################
|
23
|
-
|
24
|
-
class BuildError < RuntimeError; end
|
25
|
-
|
26
|
-
module BuildErrorMixin
|
27
|
-
|
28
|
-
# Convenient method to raise a BuildError.
|
29
|
-
# - message: error message.
|
30
|
-
def error(message)
|
31
|
-
raise BuildError.new(message)
|
32
|
-
end
|
15
|
+
require 'yaml'
|
16
|
+
require 'bee_util'
|
33
17
|
|
34
|
-
|
35
|
-
|
36
|
-
#########################################################################
|
37
|
-
# BUILD CLASS #
|
38
|
-
#########################################################################
|
18
|
+
# Module for Bee core classes.
|
19
|
+
module Bee
|
39
20
|
|
40
|
-
# Class for a
|
21
|
+
# Class for a build. This class is built from an object resulting from YAML
|
22
|
+
# build file parsing.
|
41
23
|
class Build
|
42
24
|
|
43
|
-
include BuildErrorMixin
|
25
|
+
include Bee::Util::BuildErrorMixin
|
26
|
+
include Bee::Util::HashCheckerMixin
|
44
27
|
|
45
28
|
# Build file.
|
46
29
|
attr_reader :file
|
47
|
-
# Base directory.
|
30
|
+
# Base directory (directory where lives the build file). All file paths
|
31
|
+
# are relative to this directory.
|
48
32
|
attr_reader :base
|
49
33
|
# Build name.
|
50
34
|
attr_reader :name
|
51
|
-
# Default target
|
35
|
+
# Default target (bee runs target passed on the command line, default
|
36
|
+
# target or first one in build file).
|
52
37
|
attr_reader :default
|
53
38
|
# Build description.
|
54
39
|
attr_reader :description
|
55
|
-
# Properties hash (used for project help).
|
56
|
-
attr_reader :properties
|
57
40
|
# Hash for targets, indexed by target name.
|
58
41
|
attr_reader :targets
|
59
42
|
# Context for Ruby scripts and properties.
|
60
43
|
attr_reader :context
|
61
|
-
#
|
62
|
-
attr_reader :
|
63
|
-
# Build listener.
|
44
|
+
# Package manager (for task invocation).
|
45
|
+
attr_reader :package_manager
|
46
|
+
# Build listener (responsible for displaying build status).
|
64
47
|
attr_reader :listener
|
48
|
+
|
49
|
+
# Load a build from a YAML build file.
|
50
|
+
# - file: YAML build file.
|
51
|
+
# - recursive: tells if we look for build file recursively (defaults to
|
52
|
+
# nil).
|
53
|
+
def self.load(file, recursive=nil)
|
54
|
+
if recursive
|
55
|
+
begin
|
56
|
+
file = Bee::Util::find(file)
|
57
|
+
rescue
|
58
|
+
raise Bee::Util::BuildError.new("Build file '#{file}' " +
|
59
|
+
"not found recursively")
|
60
|
+
end
|
61
|
+
end
|
62
|
+
raise Bee::Util::BuildError.new("Build file '#{file}' not found") if
|
63
|
+
not File.exists?(file)
|
64
|
+
raise Bee::Util::BuildError.new("Build file '#{file}' is not a file") if
|
65
|
+
not File.file?(file)
|
66
|
+
raise Bee::Util::BuildError.new("Build file '#{file}' is not readable") if
|
67
|
+
not File.readable?(file)
|
68
|
+
yaml = File.read(file)
|
69
|
+
begin
|
70
|
+
object = YAML::load(yaml)
|
71
|
+
rescue
|
72
|
+
raise Bee::Util::BuildError.
|
73
|
+
new("YAML syntax error in build file: #{$!}")
|
74
|
+
end
|
75
|
+
return Build.new(object, file)
|
76
|
+
end
|
65
77
|
|
66
78
|
# Constructor:
|
67
|
-
# -
|
68
|
-
|
79
|
+
# - object: build description as an object (resulting from YAML loading).
|
80
|
+
# - file: build file (nil if none).
|
81
|
+
def initialize(object, file)
|
82
|
+
require 'bee_task'
|
69
83
|
@file = file
|
84
|
+
if file
|
85
|
+
@base = File.expand_path(File.dirname(file))
|
86
|
+
else
|
87
|
+
@base = File.expand_path(Dir.pwd)
|
88
|
+
end
|
89
|
+
error "Build must be a list" unless object.kind_of?(Array)
|
70
90
|
@properties = {}
|
71
91
|
@targets = {}
|
72
|
-
@tasks = {}
|
73
92
|
@context = Context.new
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
based_script = File.join(@base, script)
|
98
|
-
evaluated_script = @context.evaluate_object(based_script)
|
99
|
-
source = File.read(evaluated_script)
|
100
|
-
load_context(source)
|
101
|
-
rescue
|
102
|
-
error "Error loading context '#{script}': #{$!}"
|
103
|
-
end
|
104
|
-
end
|
105
|
-
end
|
106
|
-
elsif entry.key?('properties')
|
107
|
-
# properties entry
|
108
|
-
for property in entry['properties']
|
93
|
+
@context.set_property(:base, @base)
|
94
|
+
@properties[:base] = @base
|
95
|
+
@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']
|
109
116
|
begin
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
rescue
|
117
|
-
error "Error evaluating property '#{name}': #{$!}"
|
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}': #{$!}"
|
118
123
|
end
|
119
124
|
end
|
120
|
-
|
121
|
-
|
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
|
122
136
|
target = Target.new(entry, self)
|
123
|
-
|
124
|
-
error "
|
125
|
-
@targets[target.name]
|
126
|
-
@targets[target.name] = target
|
127
|
-
else
|
128
|
-
# unknown entry
|
129
|
-
error "Unknown entry:\n#{YAML::dump(entry)}"
|
137
|
+
rescue
|
138
|
+
error "Error parsing target '#{entry['target']}': #{$!}"
|
130
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)}"
|
131
147
|
end
|
132
|
-
rescue
|
133
|
-
error "Error loading build file '#{@file}': #{$!}"
|
134
148
|
end
|
135
149
|
end
|
136
150
|
|
@@ -148,8 +162,8 @@ module Bee
|
|
148
162
|
for target in targets
|
149
163
|
run_target(target)
|
150
164
|
end
|
151
|
-
@listener.build_finished(self)
|
152
|
-
rescue BuildError => e
|
165
|
+
@listener.build_finished(self) if @listener
|
166
|
+
rescue Bee::Util::BuildError => e
|
153
167
|
if listener
|
154
168
|
@listener.error(e)
|
155
169
|
else
|
@@ -168,31 +182,14 @@ module Bee
|
|
168
182
|
@targets[target].run
|
169
183
|
end
|
170
184
|
|
171
|
-
private
|
172
|
-
|
173
|
-
# Load a given context and add last expression evaluated in context to
|
174
|
-
# extension tasks mapping.
|
175
|
-
# - source: the context source.
|
176
|
-
def load_context(source)
|
177
|
-
new_tasks = @context.evaluate_script(source)
|
178
|
-
if new_tasks.kind_of?(Hash)
|
179
|
-
for task in new_tasks.keys
|
180
|
-
error "Duplicate definition for task '#{task}'" if @tasks[task]
|
181
|
-
end
|
182
|
-
@tasks.merge!(new_tasks)
|
183
|
-
end
|
184
|
-
end
|
185
|
-
|
186
185
|
end
|
187
186
|
|
188
|
-
|
189
|
-
#
|
190
|
-
#########################################################################
|
191
|
-
|
192
|
-
# Class for a given target.
|
187
|
+
# Class for a target. It is built from the YAML build file and manages a
|
188
|
+
# target, in particular, tasks execution.
|
193
189
|
class Target
|
194
190
|
|
195
|
-
include BuildErrorMixin
|
191
|
+
include Bee::Util::BuildErrorMixin
|
192
|
+
include Bee::Util::HashCheckerMixin
|
196
193
|
|
197
194
|
# Build that encapsulates target.
|
198
195
|
attr_reader :build
|
@@ -206,14 +203,19 @@ module Bee
|
|
206
203
|
attr_reader :script
|
207
204
|
|
208
205
|
# Constructor.
|
209
|
-
# -
|
206
|
+
# - object: object for target, resulting from YAML parsing.
|
210
207
|
# - build: build that encapsulate this target.
|
211
|
-
def initialize(
|
208
|
+
def initialize(object, build)
|
209
|
+
check_hash(object,
|
210
|
+
{'target' => :mandatory,
|
211
|
+
'depends' => :optional,
|
212
|
+
'description' => :optional,
|
213
|
+
'script' => :optional})
|
212
214
|
@build = build
|
213
|
-
@name =
|
214
|
-
@depends =
|
215
|
-
@description =
|
216
|
-
@script =
|
215
|
+
@name = object['target']
|
216
|
+
@depends = object['depends']||[]
|
217
|
+
@description = object['description']
|
218
|
+
@script = object['script']
|
217
219
|
end
|
218
220
|
|
219
221
|
# Run target.
|
@@ -260,7 +262,7 @@ module Bee
|
|
260
262
|
run_ruby(script)
|
261
263
|
else
|
262
264
|
# must be a task
|
263
|
-
|
265
|
+
run_bee_task(task)
|
264
266
|
end
|
265
267
|
end
|
266
268
|
end
|
@@ -280,37 +282,26 @@ module Bee
|
|
280
282
|
@listener.task(script) if @listener
|
281
283
|
begin
|
282
284
|
@build.context.evaluate_script(script)
|
283
|
-
rescue
|
285
|
+
rescue Exception
|
284
286
|
error "Error running Ruby script: #{$!}"
|
285
287
|
end
|
286
288
|
end
|
287
289
|
|
288
|
-
# Run a given task.
|
290
|
+
# Run a given bee task.
|
289
291
|
# - task: task to run as a Hash.
|
290
|
-
def
|
292
|
+
def run_bee_task(task)
|
293
|
+
require 'bee_task'
|
291
294
|
@listener.task(task) if @listener
|
292
|
-
|
293
|
-
error "Unknown task '#{name}'" if
|
294
|
-
not @build.tasks.key?(name)
|
295
|
-
parameters = task[name]
|
296
|
-
script = "#{name}(#{parameters.inspect})"
|
297
|
-
begin
|
298
|
-
@build.context.evaluate_script(script)
|
299
|
-
rescue BuildError
|
300
|
-
error "Error running task #{name}: #{$!}"
|
301
|
-
end
|
295
|
+
@build.package_manager.run_task(task)
|
302
296
|
end
|
303
|
-
|
297
|
+
|
304
298
|
end
|
305
299
|
|
306
|
-
|
307
|
-
#
|
308
|
-
#########################################################################
|
309
|
-
|
310
|
-
# Class for Ruby scripts context.
|
300
|
+
# Class for Ruby scripts context. All embedded Ruby scripts run in this
|
301
|
+
# context where build properties are defined as Ruby variables.
|
311
302
|
class Context
|
312
303
|
|
313
|
-
include BuildErrorMixin
|
304
|
+
include Bee::Util::BuildErrorMixin
|
314
305
|
|
315
306
|
# The binding of this context.
|
316
307
|
attr_reader :context_binding
|
@@ -320,26 +311,37 @@ module Bee
|
|
320
311
|
@context_binding = get_binding
|
321
312
|
end
|
322
313
|
|
323
|
-
# Set a given
|
324
|
-
# - name: the
|
325
|
-
# - value: the
|
326
|
-
|
314
|
+
# Set a given property in context.
|
315
|
+
# - name: the property name.
|
316
|
+
# - value: the property value.
|
317
|
+
# - override: tells if we can overwrite an existing value.
|
318
|
+
def set_property(name, value, overwrite=true)
|
319
|
+
error "Property '#{name}' was already defined" if
|
320
|
+
!overwrite and properties.include?(name.to_s)
|
327
321
|
begin
|
328
322
|
eval("#{name} = #{value.inspect}", @context_binding)
|
329
|
-
rescue
|
323
|
+
rescue Exception
|
330
324
|
error "Error setting property '#{name} = #{value.inspect}': #{$!}"
|
331
325
|
end
|
332
326
|
end
|
333
327
|
|
334
|
-
# Get a given
|
335
|
-
# - name: the
|
336
|
-
|
328
|
+
# Get a given property in context.
|
329
|
+
# - name: the property name.
|
330
|
+
# - strict: raise an error if given property was not set.
|
331
|
+
def get_property(name, strict=false)
|
332
|
+
error "Property '#{name}' was not set" if
|
333
|
+
strict and !properties.include?(name.to_s)
|
337
334
|
begin
|
338
335
|
eval("#{name}", @context_binding)
|
339
|
-
rescue
|
336
|
+
rescue Exception
|
340
337
|
error "Error getting property '#{name}': #{$!}"
|
341
338
|
end
|
342
339
|
end
|
340
|
+
|
341
|
+
# Return list of properties (as local variables of binding).
|
342
|
+
def properties
|
343
|
+
return eval('local_variables', @context_binding)
|
344
|
+
end
|
343
345
|
|
344
346
|
# Evaluate a script in context.
|
345
347
|
# - script: script to evaluate.
|
@@ -361,38 +363,31 @@ module Bee
|
|
361
363
|
# string: replace property references
|
362
364
|
object = object.gsub(/#\{.+?\}/) do |match|
|
363
365
|
property = match[2..-2]
|
364
|
-
value =
|
365
|
-
error
|
366
|
+
value = get_property(property)
|
367
|
+
error "Property '#{property}' was not defined" unless value
|
366
368
|
value
|
367
369
|
end
|
368
370
|
return object
|
369
371
|
when Symbol
|
370
372
|
# symbol: return property object
|
371
373
|
property = object.to_s
|
372
|
-
value =
|
373
|
-
|
374
|
-
|
374
|
+
value = get_property(property, true)
|
375
|
+
return evaluate_object(value)
|
376
|
+
when Array
|
377
|
+
# array: evaluate each element
|
378
|
+
return object.collect { |element| evaluate_object(element) }
|
379
|
+
when Hash
|
380
|
+
# hash: evaluate all keys and values
|
381
|
+
evaluated = {}
|
382
|
+
object.each_pair do |key, value|
|
383
|
+
evaluated[evaluate_object(key)] = evaluate_object(value)
|
384
|
+
end
|
385
|
+
return evaluated
|
375
386
|
else
|
376
387
|
return object
|
377
388
|
end
|
378
389
|
end
|
379
390
|
|
380
|
-
# Check a task parameters. Raise a RuntimeError with explanation message if
|
381
|
-
# a mandatory parameter is missing or an unknown parameter was found.
|
382
|
-
# - params: task parameters as a Hash.
|
383
|
-
# - description: parameters description as a Hash associating a parameter
|
384
|
-
# name with symbol :mandatory or :optional.
|
385
|
-
def check_task_parameters(params, description)
|
386
|
-
error "Parameters must be a Hash" unless params.kind_of?(Hash)
|
387
|
-
for param in description.keys
|
388
|
-
error "Missing mandatory parameter '#{param}'" unless
|
389
|
-
params[param] or description[param] == :optional
|
390
|
-
end
|
391
|
-
for param in params.keys
|
392
|
-
error "Unknown parameter '#{param}'" if not description.key?(param)
|
393
|
-
end
|
394
|
-
end
|
395
|
-
|
396
391
|
private
|
397
392
|
|
398
393
|
# Get a binding as script context.
|