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.
@@ -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-2007 Michel Casabianca <michel.casabianca@gmail.com>
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-2007 Michel Casabianca <michel.casabianca@gmail.com>
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-2007 Michel Casabianca <michel.casabianca@gmail.com>
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-2007 Michel Casabianca <michel.casabianca@gmail.com>
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 (directory where lives the build file). All file paths
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
- # Default target (bee runs target passed on the command line, default
36
- # target or first one in build file).
37
- attr_reader :default
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 (for task invocation).
59
+ # Package manager, for task invocation.
45
60
  attr_reader :package_manager
46
- # Build listener (responsible for displaying build status).
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
- def self.load(file, recursive=nil)
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
- 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)
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: build description as an object (resulting from YAML loading).
95
+ # - object: object tree resulting from YAML build file parsing.
80
96
  # - file: build file (nil if none).
81
- def initialize(object, file)
82
- require 'bee_task'
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
- 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)
90
- @properties = {}
91
- @targets = {}
101
+ @base = get_base(@file)
102
+ @here = here
92
103
  @context = Context.new
93
- @context.set_property(:base, @base)
94
- @properties[:base] = @base
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
- @listener.build_started(self) if @listener
159
- Dir.chdir(base)
160
- error "No default target given" if (!@default and targets.length == 0)
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
- @listener.build_finished(self) if @listener
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 @targets[target]
182
- @targets[target].run
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
- # Build that encapsulates target.
195
- attr_reader :build
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
- # - build: build that encapsulate this target.
208
- def initialize(object, build)
209
- check_hash(object,
210
- {'target' => :mandatory,
211
- 'depends' => :optional,
212
- 'description' => :optional,
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
- def run
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
- if not @evaluated
225
- @evaluated = true
226
- for depend in @depends
227
- @build.run_target(depend)
228
- end
229
- @build.listener.target(self) if @build.listener
230
- if @script
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(@build.base)
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
- def run_task(task)
251
- @build.listener.task(task) if @build.listener
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
- evaluated_script = @build.context.evaluate_object(script)
275
- system(evaluated_script)
276
- error "Script exited with value #{$?}" if $? != 0
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
- def run_ruby(script)
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
- @build.package_manager.run_task(task)
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