bee 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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