bee 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/README CHANGED
@@ -25,4 +25,4 @@ or go to URL http://www.apache.org/licenses/LICENSE-2.0).
25
25
 
26
26
  = Copyright
27
27
 
28
- bee version 0.2.0 (C) Michel Casabianca - 2006
28
+ bee version 0.3.0 (C) Michel Casabianca - 2006
data/lib/bee.rb CHANGED
@@ -95,7 +95,7 @@ module Bee
95
95
  for script in entry['context']
96
96
  begin
97
97
  based_script = File.join(@base, script)
98
- evaluated_script = @context.evaluate_string(based_script)
98
+ evaluated_script = @context.evaluate_object(based_script)
99
99
  source = File.read(evaluated_script)
100
100
  load_context(source)
101
101
  rescue
@@ -108,7 +108,7 @@ module Bee
108
108
  for property in entry['properties']
109
109
  begin
110
110
  name = property.keys[0]
111
- value = @context.evaluate_string(property[name])
111
+ value = @context.evaluate_object(property[name])
112
112
  error "Duplicate property '#{name}' definition" if
113
113
  @properties[name]
114
114
  @properties[name] = value
@@ -174,7 +174,7 @@ module Bee
174
174
  # extension tasks mapping.
175
175
  # - source: the context source.
176
176
  def load_context(source)
177
- new_tasks = @context.evaluate(source)
177
+ new_tasks = @context.evaluate_script(source)
178
178
  if new_tasks.kind_of?(Hash)
179
179
  for task in new_tasks.keys
180
180
  error "Duplicate definition for task '#{task}'" if @tasks[task]
@@ -218,22 +218,26 @@ module Bee
218
218
 
219
219
  # Run target.
220
220
  def run
221
- if not @evaluated
222
- @evaluated = true
223
- for depend in @depends
224
- @build.run_target(depend)
225
- end
226
- @build.listener.target(self) if @build.listener
227
- if @script
228
- case @script
229
- when String
230
- run_task(@script)
231
- when Array
232
- for task in @script
233
- run_task(task)
221
+ begin
222
+ if not @evaluated
223
+ @evaluated = true
224
+ for depend in @depends
225
+ @build.run_target(depend)
226
+ end
227
+ @build.listener.target(self) if @build.listener
228
+ if @script
229
+ case @script
230
+ when String
231
+ run_task(@script)
232
+ when Array
233
+ for task in @script
234
+ run_task(task)
235
+ end
234
236
  end
235
237
  end
236
238
  end
239
+ ensure
240
+ Dir.chdir(@build.base)
237
241
  end
238
242
  end
239
243
 
@@ -265,7 +269,7 @@ module Bee
265
269
  # - script: the scrip to run.
266
270
  def run_shell(script)
267
271
  @listener.task(script) if @listener
268
- evaluated_script = @build.context.evaluate_string(script)
272
+ evaluated_script = @build.context.evaluate_object(script)
269
273
  system(evaluated_script)
270
274
  error "Script exited with value #{$?}" if $? != 0
271
275
  end
@@ -275,7 +279,7 @@ module Bee
275
279
  def run_ruby(script)
276
280
  @listener.task(script) if @listener
277
281
  begin
278
- @build.context.evaluate(script)
282
+ @build.context.evaluate_script(script)
279
283
  rescue BuildError
280
284
  error "Error running Ruby script: #{$!}"
281
285
  end
@@ -291,7 +295,7 @@ module Bee
291
295
  parameters = task[name]
292
296
  script = "#{name}(#{parameters.inspect})"
293
297
  begin
294
- @build.context.evaluate(script)
298
+ @build.context.evaluate_script(script)
295
299
  rescue BuildError
296
300
  error "Error running task #{name}: #{$!}"
297
301
  end
@@ -339,24 +343,54 @@ module Bee
339
343
 
340
344
  # Evaluate a script in context.
341
345
  # - script: script to evaluate.
342
- def evaluate(script)
346
+ def evaluate_script(script)
343
347
  eval(script, @context_binding)
344
348
  end
345
349
 
346
- # Process a given string, replacing properties references with their
347
- # value. Property references have same form than variable references
348
- # in ruby strings: '#{variable}' will be replaced with variable value.
349
- # - string: string to process.
350
- def evaluate_string(string)
351
- return nil if string == nil
352
- return string if not string.kind_of?(String)
353
- string = string.gsub(/#\{.+?\}/) do |match|
354
- property = match[2..-2]
350
+ # Process a given object, replacing properties references with their
351
+ # string value, symbol with their raw value. Property references have
352
+ # same form than variable references in ruby strings: '#{variable}'
353
+ # will be replaced with variable string value.
354
+ # - object: object to process.
355
+ def evaluate_object(object)
356
+ case object
357
+ when NilClass
358
+ # nil: return nil
359
+ return nil
360
+ when String
361
+ # string: replace property references
362
+ object = object.gsub(/#\{.+?\}/) do |match|
363
+ property = match[2..-2]
364
+ value = get(property)
365
+ error ("Property '#{property}' was not defined") unless value
366
+ value
367
+ end
368
+ return object
369
+ when Symbol
370
+ # symbol: return property object
371
+ property = object.to_s
355
372
  value = get(property)
356
373
  error ("Property '#{property}' was not defined") unless value
357
- value
374
+ return value
375
+ else
376
+ return object
377
+ end
378
+ end
379
+
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)
358
393
  end
359
- return string
360
394
  end
361
395
 
362
396
  private
data/lib/bee_console.rb CHANGED
@@ -317,9 +317,11 @@ targets Targets to run (default target if omitted).'
317
317
  error "Task '#{task}' not loaded" if not build.tasks[task]
318
318
  help << build.tasks[task]
319
319
  else
320
+ help << "Loaded tasks: "
320
321
  for task in build.tasks.keys.sort
321
- help << format_description(task, build.tasks[task], 0, true)
322
+ help << "#{task}, "
322
323
  end
324
+ help = help[0..-3]
323
325
  end
324
326
  return help
325
327
  end
@@ -19,67 +19,174 @@
19
19
 
20
20
  ############################ UTILITY FUNCTIONS ############################
21
21
 
22
- # Convenient method to raise a BuildError.
22
+ # Convenient method to raise a BuildError. This is necessary to interrupt
23
+ # build with an error message but without a stack trace (which would
24
+ # indicate an internal error).
23
25
  # - message: error message.
24
26
  def error(message)
25
27
  raise BuildError.new(message)
26
28
  end
27
29
 
28
- # Check a task parameters. Raise a RuntimeError with explanation message if
29
- # a mandatory parameter is missing or an unknown parameter was found.
30
- # - params: task parameters as a Hash.
31
- # - description: parameters description as a Hash associating a parameter
32
- # name with symbol :mandatory or :optional.
33
- def check_parameters(params, description)
34
- error "Parameters must be a Hash" unless params.kind_of?(Hash)
35
- for param in description.keys
36
- error "Missing mandatory parameter '#{param}'" unless
37
- params[param] or description[param] == :optional
38
- end
39
- for param in params.keys
40
- error "Unknown parameter '#{param}'" if not description.key?(param)
41
- end
42
- end
43
-
44
- # Run a shell script and raise an exception if script returned a value
30
+ # Run a shell script and raise a build error if script returned a value
45
31
  # different of 0.
46
32
  # - script: script to run.
47
33
  def sh(script)
48
34
  system(script) or error "Script '#{script}' exited with value '#{$?}'"
49
35
  end
50
36
 
51
- # Find files that match a given pattern.
52
- # - pattern: pattern to select files.
53
- # - base: base directory for search.
54
- # - dir: tells if we must include directories.
55
- # Return: a file list.
56
- def find(pattern=//, base='.', dir=true)
57
- require 'find'
58
- files = []
59
- Find.find(base) do |path|
60
- if path =~ pattern and (File.file?(path) or (File.directory?(path) and dir))
61
- files << path
62
- end
37
+ ############################ TASK DEFINITIONS #############################
38
+
39
+ # Prints a message. This message may be a String (standard output) or any
40
+ # Ruby object. In this latter case, print its inspected value.
41
+ # - message: message to print.
42
+ def print(message)
43
+ case message
44
+ when String
45
+ puts evaluate_object(message)
46
+ else
47
+ puts message.inspect
63
48
  end
64
- return files
65
49
  end
66
50
 
67
- ############################ TASK DEFINITIONS #############################
51
+ # Print a file contents.
52
+ # - file: file to print out.
53
+ def cat(file)
54
+ file = evaluate_object(file)
55
+ error "Parameter must be a String" unless file.kind_of?(String)
56
+ error "File '#{file}' not found" unless
57
+ File.exists?(file) or File.directory?(file)
58
+ puts File.read(file).strip
59
+ end
68
60
 
69
- # Prints a message.
70
- def print(message)
71
- error "Parameter must be a String" unless message.kind_of?(String)
72
- puts evaluate_string(message)
61
+ # Change working directory. This change will persist for all tasks run in
62
+ # the target. Parameter is a string with directory to change to.
63
+ def cd(dir)
64
+ dir = evaluate_object(dir)
65
+ error "cd parameter is a String" unless dir.kind_of?(String)
66
+ Dir.chdir(dir)
73
67
  end
74
68
 
75
- # Make a directory and parent directories if necessary.
69
+ # Make a directory and parent directories if necessary. Doesn't complain if
70
+ # directory already exists.
71
+ # - dir: directory to create.
76
72
  def mkdir(dir)
73
+ dir = evaluate_object(dir)
77
74
  error "Parameter must be a String" unless dir.kind_of?(String)
78
75
  require "fileutils"
79
76
  FileUtils.makedirs(dir)
80
77
  end
81
78
 
82
- # Run an ERB file or source and store result in a file or property.
79
+ # Copy a files or directoris to destination file or directory. Parameter is a
80
+ # Hash with following entries:
81
+ # - src: glob for source files or directories.
82
+ # - dest: destination file or directory.
83
+ def cp(params)
84
+ require 'fileutils'
85
+ params_desc = {
86
+ 'src' => :mandatory,
87
+ 'dest' => :mandatory
88
+ }
89
+ check_task_parameters(params, params_desc)
90
+ src = evaluate_object(params['src'])
91
+ dest = evaluate_object(params['dest'])
92
+ files = []
93
+ for element in src
94
+ files += Dir.glob(element)
95
+ end
96
+ for file in files
97
+ FileUtils.cp_r(file, dest)
98
+ end
99
+ end
100
+
101
+ # Move source file(s) or directories to dest file or directory. Parameter is
102
+ # a Hahs with following keys:
103
+ # - src: glob for files and directories to move.
104
+ # - dest: file or directory to move file(s) to.
105
+ def mv(params)
106
+ require 'fileutils'
107
+ params_desc = {
108
+ 'src' => :mandatory,
109
+ 'dest' => :mandatory
110
+ }
111
+ check_task_parameters(params, params_desc)
112
+ src = evaluate_object(params['src'])
113
+ dest = evaluate_object(params['dest'])
114
+ files = []
115
+ for element in src
116
+ files += Dir.glob(element)
117
+ end
118
+ for file in files
119
+ FileUtils.mv(file, dest)
120
+ end
121
+ end
122
+
123
+ # Delete files for a given glob. Parameter is a string for glob of files
124
+ # to delete.
125
+ def rm(glob)
126
+ require 'fileutils'
127
+ glob = evaluate_object(glob)
128
+ error "rm parameter is a String" unless glob.kind_of?(String)
129
+ files = Dir.glob(glob)
130
+ for file in files
131
+ FileUtils.rm_f(file)
132
+ end
133
+ end
134
+
135
+ # Delete directories recursively. Parameter is a string for glob of directories
136
+ # to delete.
137
+ def rmdir(glob)
138
+ require 'fileutils'
139
+ glob = evaluate_object(glob)
140
+ error "rm parameter is a String" unless glob.kind_of?(String)
141
+ dirs = Dir.glob(glob)
142
+ for dir in dirs
143
+ FileUtils.rm_rf(dir)
144
+ end
145
+ end
146
+
147
+ # Find files for a given glob and store list in a property. Parameter is
148
+ # a Hash with entries:
149
+ # - files: glob or list of globs for files to look for.
150
+ # - toprop: name of the property to set.
151
+ def find(parameters)
152
+ params_desc = {
153
+ 'files' => :mandatory,
154
+ 'toprop' => :mandatory
155
+ }
156
+ check_task_parameters(parameters, params_desc)
157
+ files = []
158
+ globs = parameters['files']
159
+ toprop = evaluate_object(parameters['toprop'])
160
+ for glob in globs
161
+ files += Dir.glob(evaluate_object(glob))
162
+ end
163
+ set(toprop, files)
164
+ end
165
+
166
+ # Run a set of tests selected using globs. Parameter is a glob or list of
167
+ # globs for files or directories to run.
168
+ # FIXME: if tasks runs twice, it will run twice loaded tests...
169
+ def test(globs)
170
+ require 'test/unit'
171
+ require 'test/unit/testresult'
172
+ files = []
173
+ for glob in globs
174
+ error "Parameter must be a String or a list of Strings" unless
175
+ glob.kind_of?(String)
176
+ files += Dir.glob(evaluate_object(glob))
177
+ end
178
+ for file in files
179
+ load file
180
+ end
181
+ Test::Unit::AutoRunner.run
182
+ end
183
+
184
+ # Run an ERB file or source and store result in a file or property. Parameter
185
+ # is a Hash with following keys:
186
+ # - source: ERB source text (if no 'file').
187
+ # - file: ERB file name (if no 'source').
188
+ # - tofile: file where to store result (if no 'toprop').
189
+ # - toprop: property name where to store result (if no 'tofile').
83
190
  def erb(params)
84
191
  require 'erb'
85
192
  # check parameters
@@ -89,11 +196,11 @@ def erb(params)
89
196
  'tofile' => :optional,
90
197
  'toprop' => :optional
91
198
  }
92
- check_parameters(params, params_desc)
199
+ check_task_parameters(params, params_desc)
93
200
  source = params['source']
94
- file = evaluate_string(params['file'])
95
- tofile = evaluate_string(params['tofile'])
96
- toprop = evaluate_string(params['toprop'])
201
+ file = evaluate_object(params['file'])
202
+ tofile = evaluate_object(params['tofile'])
203
+ toprop = evaluate_object(params['toprop'])
97
204
  error "Must pass one of 'source' or 'file' parameters to erb task" if
98
205
  not source and not file
99
206
  error "Must pass one of 'tofile' or 'toprop' parameters to erb task" if
@@ -114,18 +221,224 @@ def erb(params)
114
221
  end
115
222
  end
116
223
 
224
+ # Generate RDoc documentation for a given list of globs and an output directory.
225
+ # Parameter is a Hash with following keys:
226
+ # - input: input files as a glob (or list of globs). File mays be directories.
227
+ # - output: output directory for generated documentation.
228
+ def rdoc(params)
229
+ require 'rdoc/rdoc'
230
+ params_desc = {
231
+ 'input' => :mandatory,
232
+ 'output' => :mandatory
233
+ }
234
+ check_task_parameters(params, params_desc)
235
+ files = []
236
+ input = params['input']
237
+ for glob in input
238
+ files += Dir.glob(evaluate_object(glob))
239
+ end
240
+ output = evaluate_object(params['output'])
241
+ command_line = ['-S', '-o', output] + files
242
+ rdoc = RDoc::RDoc.new
243
+ rdoc.document(command_line)
244
+ end
245
+
246
+ # Generate a Gem package. Parameter is the name of the Gem description file.
247
+ # Resulting Gem package is generated in current directory (as with command
248
+ # line tool).
249
+ def gembuild(description)
250
+ require 'rubygems'
251
+ description = evaluate_object(description)
252
+ arguments = ['build', description]
253
+ Gem.manage_gems
254
+ Gem::GemRunner.new.run(arguments)
255
+ end
256
+
257
+ # Generate a ZIP archive. Parameter is a Hash with following entries:
258
+ # - files: glob or list of globs for files to select for the archive.
259
+ # - archive: the archive name.
260
+ # - prefix: prefix for archive entries (default to nil).
261
+ # Note: if archive exists, files are added to the archive.
262
+ def zip(parameters)
263
+ require 'zip/zip'
264
+ # parse parameters
265
+ params_desc = {
266
+ 'files' => :mandatory,
267
+ 'archive' => :mandatory,
268
+ 'prefix' => :optional
269
+ }
270
+ check_task_parameters(parameters, params_desc)
271
+ globs = evaluate_object(parameters['files'])
272
+ files = []
273
+ for glob in globs
274
+ files += Dir.glob(evaluate_object(glob))
275
+ end
276
+ archive = evaluate_object(parameters['archive'])
277
+ prefix = evaluate_object(parameters['prefix'])
278
+ # build the archive
279
+ zipfile = Zip::ZipFile.open(archive, Zip::ZipFile::CREATE) do |zip|
280
+ for file in files
281
+ entry = prefix ? File.join(prefix, file) : file
282
+ puts "Adding '#{entry}'"
283
+ zip.add(entry, file)
284
+ end
285
+ zip.close
286
+ end
287
+ end
288
+
117
289
  ############################## TASKS MAPPING ##############################
118
290
 
119
291
  {
120
- "print" =>
121
- "Print a message passed as parameter.",
122
- "mkdir" =>
123
- "Create a directory and all parent directories if necessary. Do nothing if
124
- directory already exists. Parameter is a String for directory to create.",
125
- "erb" =>
126
- "Run an ERB:
127
- - source: ERB source to run (if no 'file').
128
- - file: ERB file to run (if no 'source').
129
- - tofile: file where to write ERB result (if no 'toprop').
130
- - toprop: bee property where to put result (if no 'tofile')."
292
+ "print" =>
293
+ "Print a message on console. This message may be a String (standard output)
294
+ or any Ruby object. In this latter case, print its inspected value. Parameter
295
+ is the message to output as a String.
296
+
297
+ - message: message to print.
298
+
299
+ Example:
300
+
301
+ - print: \"Hello World!\"",
302
+
303
+ "cat" =>
304
+ "Print contents of a given file on the console. Parameter is file to output
305
+ as a String.
306
+
307
+ - file: file to print out.
308
+
309
+ Example:
310
+
311
+ - cat: \"doc/welcome-message.txt\"",
312
+
313
+ "cd" =>
314
+ "Change working directory. This change will persist for all tasks in the
315
+ target but not in other targets. Parameter is a String with directory to
316
+ change to.
317
+
318
+ Example:
319
+
320
+ - cd: \"build\"",
321
+
322
+ "mkdir" =>
323
+ "Make a directory and parent directories if necessary. Doesn't complain if
324
+ directory already exists. Parameter is directory to create as a String.
325
+
326
+ Example:
327
+
328
+ - mkdir \"foo/bar\"",
329
+
330
+ "cp" =>
331
+ "Copy files or directories to destination file or directory. Parameter is a
332
+ Hash with following entries:
333
+
334
+ - src: glob for source files or directories.
335
+ - dest: destination file or directory.
336
+
337
+ Example:
338
+
339
+ - cp:
340
+ src: \"doc/png/*.png\"
341
+ dest: :doc",
342
+
343
+ "mv" =>
344
+ "Move source file(s) or directories to dest file or directory. Parameter is
345
+ a Hahs with following entries:
346
+
347
+ - src: glob for files and directories to move.
348
+ - dest: file or directory to move file(s) to.
349
+
350
+ Example:
351
+
352
+ - mv: { src: :gem_package, dest: :build }",
353
+
354
+ "rm" =>
355
+ "Delete files for a given glob. Parameter is a String or list of Strings for
356
+ glob(s) of files to delete.
357
+
358
+ Example:
359
+
360
+ - rm: \"**/*~\"",
361
+
362
+ "rmdir" =>
363
+ "Delete directories recursively. Parameter is a string for glob of directories
364
+ to delete.
365
+
366
+ Example:
367
+
368
+ - rmdir: :build",
369
+
370
+ "find" =>
371
+ "Find files for a given glob and store list in a property. Parameter is
372
+ a Hash with entries:
373
+
374
+ - files: glob or list of globs for files to look for.
375
+ - toprop: name of the property to set.
376
+
377
+ Example:
378
+
379
+ - find: { files: \"**/*.rb\", toprop: \"rb_files_to_check\" }",
380
+
381
+ "test" =>
382
+ "Run a set of tests selected using globs. Parameter is a glob or list of
383
+ globs for files or directories to run.
384
+
385
+ Example:
386
+
387
+ - test: \"**/tc_*.rb\"
388
+
389
+ *FIXME*: if tasks runs twice, it will run twice loaded tests...",
390
+
391
+ "erb" =>
392
+ "Run an ERB file or source in bee context and store result in a file or
393
+ property. Parameter is a Hash with following entries:
394
+
395
+ - source: ERB source text (if no 'file').
396
+ - file: ERB file name (if no 'source').
397
+ - tofile: file where to store result (if no 'toprop').
398
+ - toprop: property name where to store result (if no 'tofile').
399
+
400
+ Example:
401
+
402
+ - erb: { file: \"gem.spec.erb\", tofile: \"gem.spec\" }
403
+
404
+ Notes: In these ERB files, you can access a property _foo_ writing:
405
+
406
+ <p>Hello <%= foo %>!</p>",
407
+
408
+ "rdoc" =>
409
+ "Generate RDoc documentation for a given list of globs and an output directory.
410
+ Parameter is a Hash with following entries:
411
+
412
+ - input: input files as a glob (or list of globs). File mays be directories.
413
+ - output: output directory for generated documentation.
414
+
415
+ Example:
416
+
417
+ - rdoc:
418
+ input: [\"README\", \"LICENSE\", :src]
419
+ output: :api",
420
+
421
+ "gembuild" =>
422
+ "Generate a Gem package. Parameter is the name of the Gem description file.
423
+ Resulting Gem package is generated in current directory (as with command
424
+ line tool).
425
+
426
+ Example:
427
+
428
+ - gembuild: :gem_spec",
429
+
430
+ "zip" =>
431
+ "Generate a ZIP archive. Parameter is a Hash with following entries:
432
+
433
+ - files: glob or list of globs for files to select for the archive.
434
+ - archive: the archive name.
435
+ - prefix: prefix for archive entries (default to nil).
436
+
437
+ Example:
438
+
439
+ - zip:
440
+ files: :zip_files
441
+ archive: :zip_archive
442
+
443
+ Note: if archive already exists, files are added to the archive."
131
444
  }
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.0
3
3
  specification_version: 1
4
4
  name: bee
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.2.0
7
- date: 2006-11-06 00:00:00 +01:00
6
+ version: 0.3.0
7
+ date: 2006-11-08 00:00:00 +01:00
8
8
  summary: bee is a build tool
9
9
  require_paths:
10
10
  - lib