bee 0.10.2 → 0.11.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.
@@ -1,4 +1,4 @@
1
- # Copyright 2006-2010 Michel Casabianca <michel.casabianca@gmail.com>
1
+ # Copyright 2006-2011 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,12 +13,11 @@
13
13
  # limitations under the License.
14
14
 
15
15
  require 'rubygems'
16
- require 'bee'
16
+ require 'bee_build'
17
17
  require 'bee_util'
18
18
 
19
19
  module Bee
20
20
 
21
- # Module for bee tasks.
22
21
  module Task
23
22
 
24
23
  # Base class for task package. Provides methods to print output using
@@ -28,11 +27,19 @@ module Bee
28
27
  class Package < Bee::Util::MethodInfoBase
29
28
 
30
29
  include Bee::Util::BuildErrorMixin
30
+
31
+ # Verbosity indicator
32
+ attr_reader :verbose
31
33
 
32
34
  # Constructor.
33
35
  # - build: the build we are running.
34
36
  def initialize(build)
35
37
  @build = build
38
+ if @build and @build.listener
39
+ @verbose = @build.listener.formatter.verbose
40
+ else
41
+ @verbose = false
42
+ end
36
43
  end
37
44
 
38
45
  protected
@@ -50,7 +57,7 @@ module Bee
50
57
  for param in description.keys
51
58
  error "#{task} '#{param}' parameter is mandatory" unless
52
59
  params[param.to_s] or description[param][:mandatory] == false
53
- if params[param.to_s]
60
+ if params[param.to_s] != nil
54
61
  case description[param][:type]
55
62
  when :string
56
63
  error "#{task} '#{param}' parameter must be a string" unless
@@ -66,7 +73,7 @@ module Bee
66
73
  params[param.to_s].kind_of?(Numeric)
67
74
  when :boolean
68
75
  error "#{task} '#{param}' parameter must be a boolean" unless
69
- params[param.to_s] == true or params[param] == false
76
+ params[param.to_s] == true or params[param.to_s] == false
70
77
  when :array
71
78
  error "#{task} '#{param}' parameter must be an array" unless
72
79
  params[param.to_s].kind_of?(Array)
@@ -152,8 +159,8 @@ module Bee
152
159
  # Print text on the console.
153
160
  # - text: text to print.
154
161
  def print(text)
155
- if @build.listener
156
- @build.listener.print(text)
162
+ if @build and @build.listener
163
+ @build.listener.formatter.print(text)
157
164
  else
158
165
  Kernel.print(text)
159
166
  end
@@ -162,93 +169,15 @@ module Bee
162
169
  # Puts text on the console.
163
170
  # - text: text to puts.
164
171
  def puts(text)
165
- if @build.listener
166
- @build.listener.puts(text)
172
+ if @build and @build.listener
173
+ @build.listener.formatter.puts(text)
167
174
  else
168
175
  Kernel.puts(text)
169
176
  end
170
177
  end
171
178
 
172
- # Prompts the user for a string.
173
- # Return the user input string.
174
- def gets
175
- if @build.listener
176
- return @build.listener.gets
177
- else
178
- return Kernel::STDIN.gets
179
- end
180
- end
181
-
182
179
  end
183
180
 
184
- # Package manager is responsible for loading packages and calling tasks.
185
- class PackageManager
186
-
187
- include Bee::Util::BuildErrorMixin
188
-
189
- # Constructor.
190
- # - build: the build we are running.
191
- def initialize(build)
192
- @build = build
193
- @packages = {}
194
- end
195
-
196
- # Run a given task.
197
- # - task: YAML object for the task to run.
198
- def run_task(task)
199
- packaged = task.keys[0]
200
- package, name = Bee::Util::get_package_name(packaged)
201
- parameters = @build.context.evaluate_object(task[packaged])
202
- if not @packages[package]
203
- load_package(package)
204
- end
205
- error "Task '#{name}' not found in package '#{package}'" if
206
- not @packages[package].respond_to?(name)
207
- @packages[package].send(name, parameters)
208
- end
209
-
210
- # Get help for a given task.
211
- # - task: YAML object for the task to run.
212
- def help_task(task)
213
- package, name = Bee::Util::get_package_name(task)
214
- if not @packages[package]
215
- load_package(package)
216
- end
217
- help = {}
218
- if name == '?'
219
- methods = @packages[package].class.public_instance_methods(false)
220
- for method in methods
221
- help[method] = @packages[package].class.method_info(method).comment
222
- end
223
- return help
224
- else
225
- error "Task '#{name}' not found in package '#{package}'" if
226
- not @packages[package].respond_to?(name)
227
- help[task] = @packages[package].class.method_info(name).comment
228
- end
229
- return help
230
- end
231
-
232
- private
233
-
234
- # Load a given package using introspection: we try to instantiate class
235
- # named after the package capitalized, in module Bee::Task.
236
- # - package: the package name.
237
- def load_package(package)
238
- package = 'default' if not package
239
- package.downcase!
240
- script = "bee_task_#{package}"
241
- clazz = package.capitalize
242
- begin
243
- require script
244
- @packages[package] = Bee::Task.const_get(clazz).new(@build)
245
- rescue Exception
246
- error "Task package '#{package}' not found"
247
- end
248
- end
249
-
250
- end
251
-
252
181
  end
253
182
 
254
183
  end
@@ -0,0 +1,135 @@
1
+ # Copyright 2006-2011 Michel Casabianca <michel.casabianca@gmail.com>
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require 'rubygems'
16
+ require 'bee_util'
17
+
18
+ module Bee
19
+
20
+ module Task
21
+
22
+ # Package manager is responsible for loading packages and calling tasks.
23
+ class PackageManager
24
+
25
+ include Bee::Util::BuildErrorMixin
26
+
27
+ # Constructor.
28
+ # - build: the build we are running.
29
+ def initialize(build)
30
+ @build = build
31
+ @packages = {}
32
+ end
33
+
34
+ # Run a given task.
35
+ # - task: YAML object for the task to run.
36
+ def run_task(task)
37
+ packaged = task.keys[0]
38
+ package, name = Bee::Util::get_package_name(packaged)
39
+ parameters = @build.context.evaluate_object(task[packaged])
40
+ if not @packages[package]
41
+ @packages[package] = Bee::Task::PackageManager.load_package(package, @build)
42
+ end
43
+ error "Task '#{name}' not found in package '#{package}'" if
44
+ not @packages[package].respond_to?(name)
45
+ @packages[package].send(name, parameters)
46
+ end
47
+
48
+ # Get help for a given task.
49
+ # - task: YAML object for the task to run.
50
+ def help_task(task)
51
+ package, name = Bee::Util::get_package_name(task)
52
+ if not @packages[package]
53
+ @packages[package] = Bee::Task::PackageManager.load_package(package, @build)
54
+ end
55
+ help = {}
56
+ if name == '?'
57
+ methods = @packages[package].class.public_instance_methods(false)
58
+ for method in methods
59
+ help[method] = @packages[package].class.method_info(method).comment
60
+ end
61
+ return help
62
+ else
63
+ error "Task '#{name}' not found in package '#{package}'" if
64
+ not @packages[package].respond_to?(name)
65
+ help[task] = @packages[package].class.method_info(name).comment
66
+ end
67
+ return help
68
+ end
69
+
70
+ # List all available tasks.
71
+ def self.list_tasks
72
+ names = [nil] + self.find_gems(/^bee_/).map {|gem| gem.name[4..-1]}
73
+ tasks = []
74
+ for name in names
75
+ package = self.load_package(name)
76
+ methods = package.class.public_instance_methods(false)
77
+ if name
78
+ methods.map! {|method| "#{name}.#{method}"}
79
+ end
80
+ tasks += methods
81
+ end
82
+ return tasks.sort
83
+ end
84
+
85
+ # List all available templates.
86
+ def self.list_templates
87
+ gems = self.find_gems(/^bee$/, /^bee_/)
88
+ templates = []
89
+ for gem in gems
90
+ package = gem.name == 'bee' ? nil : gem.name[4..-1]
91
+ for file in gem.files
92
+ if file =~ /egg\/(\w+?).yml/
93
+ if package
94
+ templates << "#{package}.#{$1}"
95
+ else
96
+ templates << $1
97
+ end
98
+ end
99
+ end
100
+ end
101
+ return templates.sort
102
+ end
103
+
104
+ private
105
+
106
+ # Load a given package using introspection: we try to instantiate class
107
+ # named after the package capitalized, in module Bee::Task.
108
+ # - package: the package name.
109
+ def self.load_package(package, build=nil)
110
+ package = 'default' if not package
111
+ package.downcase!
112
+ script = "bee_task_#{package}"
113
+ clazz = package.capitalize
114
+ begin
115
+ require script
116
+ return Bee::Task.const_get(clazz).new(build)
117
+ rescue Exception
118
+ raise Bee::Util::BuildError.new("Task package '#{package}' not found")
119
+ end
120
+ end
121
+
122
+ def self.find_gems(*patterns)
123
+ gems = []
124
+ index = Gem::SourceIndex.from_installed_gems()
125
+ for pattern in patterns
126
+ gems += index.find_name(pattern)
127
+ end
128
+ return gems
129
+ end
130
+
131
+ end
132
+
133
+ end
134
+
135
+ end
@@ -1,4 +1,4 @@
1
- # Copyright 2006-2010 Michel Casabianca <michel.casabianca@gmail.com>
1
+ # Copyright 2006-2011 Michel Casabianca <michel.casabianca@gmail.com>
2
2
  # 2006 Avi Bryant
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -22,13 +22,11 @@ module Bee
22
22
 
23
23
  # Limit of number of HTTP redirections to follow.
24
24
  HTTP_REDIRECTIONS_LIMIT = 10
25
- # README file where copyright is extracted.
26
- README_FILE = 'README'
27
25
  # Default package name.
28
26
  DEFAULT_PACKAGE = 'default'
29
- # Compact pattern for resource
27
+ # Compact pattern for resource (':gem.file[version]')
30
28
  COMPACT_PATTERN = /^:(.*?)\.(.*?)(\[(.*)\])?$/
31
- # Expanded pattern for resource
29
+ # Expanded pattern for resource ('ruby://gem:version/file')
32
30
  EXPANDED_PATTERN = /^ruby:\/\/(.*?)(:(.*?))?\/(.*)$/
33
31
  # Default terminal width
34
32
  DEFAULT_TERM_WIDTH = (RUBY_PLATFORM =~ /win32/ ? 79 : 80)
@@ -50,18 +48,11 @@ module Bee
50
48
  end
51
49
  end
52
50
 
53
- # Return copyright parsing README file. Returns nil if COPYRIGHT file
54
- # was not found.
55
- def self.copyright
56
- readme = File.join(File.dirname(__FILE__), '..', README_FILE)
57
- begin
58
- copyright = File.read(readme).strip!.split("\n")[-1]
59
- rescue
60
- copyright = nil
61
- end
62
- return copyright
51
+ # Tells if we are running under Windows.
52
+ def self.windows?
53
+ return RUBY_PLATFORM =~ /(mswin|ming)/
63
54
  end
64
-
55
+
65
56
  # Parse packaged name and return package and name.
66
57
  # - packaged: packaged name (such as 'foo.bar').
67
58
  # Return: package ('foo') and name ('bar').
@@ -76,7 +67,7 @@ module Bee
76
67
 
77
68
  # Get a given file or URL. Manages HTTP redirections.
78
69
  # - location: file path, resource or URL of the file to get.
79
- # - base: base for relative files (defaults to nil).
70
+ # - base: base for relative files (defaults to nil, which is current dir).
80
71
  def self.get_file(location, base=nil)
81
72
  base = base || Dir.pwd
82
73
  abs = absolute_path(location, base)
@@ -101,68 +92,70 @@ module Bee
101
92
  find(file)
102
93
  end
103
94
 
104
- # Function to tell if a file name is a URL.
105
- # - file: file name to consider.
106
- def self.url?(file)
107
- return file =~ /^http:/
95
+ # Tells is a given location is a URL (starting with 'http://').
96
+ # - location: location to consider as a string.
97
+ def self.url?(location)
98
+ return false if not location.kind_of?(String)
99
+ return location =~ /^http:\/\//
100
+ end
101
+
102
+ # Tells is a given location is a resource (starting with 'ruby://' or ':').
103
+ # - location: location to consider as a string.
104
+ def self.resource?(location)
105
+ return false if not location.kind_of?(String)
106
+ return location =~ /^ruby:\/\// || location =~ /^:/
108
107
  end
109
108
 
110
109
  # Tells if a given path is absolute.
111
- # - location: file to consider.
112
- def self.absolute_path?(location)
113
- if url?(location) or resource?(location)
110
+ # - path: path to consider.
111
+ def self.absolute_path?(path)
112
+ if url?(path) or resource?(path)
114
113
  return true
115
114
  else
116
- case RUBY_PLATFORM
117
- when /mswin/
118
- return location =~ /^(([a-z]|[A-Z]):)?\//
115
+ if windows?
116
+ return path =~ /^(([a-zA-Z]):)?\//
119
117
  else
120
- return location =~ /^\//
118
+ return path =~ /^\//
121
119
  end
122
120
  end
123
121
  end
124
122
 
125
- # Utility method that returns absolute path for a given file relative
126
- # to base.
127
- # - location: location to get absolute path for.
128
- # - base: base for relative paths (may be an URL).
129
- def self.absolute_path(location, base)
130
- if absolute_path?(location)
131
- if resource?(location)
132
- location = resource_path(location)
123
+ # Return absolute path for a given path and optional base:
124
+ # - path: relative path to get absolute path for.
125
+ # - base: optional base for path (defaults to current directory).
126
+ def self.absolute_path(path, base=nil)
127
+ if absolute_path?(path)
128
+ if resource?(path)
129
+ path = resource_path(path)
133
130
  end
134
- return location
131
+ return path
135
132
  else
136
- return File.join(base, location)
133
+ base = Dir.pwd if not base
134
+ return File.join(base, path)
137
135
  end
138
136
  end
139
137
 
140
138
  # Get a given URL.
141
139
  # - url: URL to get.
142
140
  # - limit: redirectrion limit (defaults to HTTP_REDIRECTIONS_LIMIT).
143
- def self.fetch(url, limit = HTTP_REDIRECTIONS_LIMIT)
141
+ def self.fetch(url, limit=HTTP_REDIRECTIONS_LIMIT)
144
142
  raise 'HTTP redirect too deep' if limit == 0
145
143
  response = Net::HTTP.get_response(URI.parse(url))
146
144
  case response
147
145
  when Net::HTTPSuccess
148
146
  response.body
149
147
  when Net::HTTPRedirection
150
- fetch(response['location'], limit - 1)
148
+ fetch(response['location'], limit-1)
151
149
  else
152
150
  response.error!
153
151
  end
154
152
  end
155
153
 
156
- # Tells is a given location is a resource.
157
- # - location: location to examine.
158
- def self.resource?(location)
159
- return location.to_s =~ /^ruby:\/\// || location.to_s =~ /^:/
160
- end
161
-
162
- # Return the path to a given resoure and test that file exists.
163
- # - resource: the resource (expanded or compact pattern).
154
+ # Return absolute path to a given resoure:
155
+ # - resource: the resource (expanded patterns are like ':gem.file[version]'
156
+ # and compact ones like 'ruby://gem:version/file').
164
157
  def self.resource_path(resource)
165
- # get gem, version and path from resource
158
+ # get gem, version and path from resource or interrupt build with an error
166
159
  case resource
167
160
  when COMPACT_PATTERN
168
161
  gem, version, path = $1, $4, $2
@@ -178,8 +171,7 @@ module Bee
178
171
  not gem_descriptor
179
172
  else
180
173
  gem_descriptor = Gem.source_index.find_name(gem)[0]
181
- raise "Gem '#{gem}' was not found" if
182
- not gem_descriptor
174
+ raise "Gem '#{gem}' was not found" if not gem_descriptor
183
175
  end
184
176
  # get resource path
185
177
  gem_path = gem_descriptor.full_gem_path
@@ -188,7 +180,7 @@ module Bee
188
180
  end
189
181
 
190
182
  # Find a given template and return associated file.
191
- # - template: template to look for.
183
+ # - template: template to look for (like 'foo.bar').
192
184
  # return: found associated file.
193
185
  def self.find_template(template)
194
186
  raise Bee::Util::BuildError.
@@ -212,7 +204,7 @@ module Bee
212
204
  end
213
205
 
214
206
  # Search files for a given templates that might contain a joker (*).
215
- # - template: template to look for.
207
+ # - template: template to look for ('foo.bar' or 'foo.*' or '*.bar').
216
208
  # return: a hash associating template and corresponding file.
217
209
  def self.search_templates(template)
218
210
  raise Bee::Util::BuildError.
@@ -257,8 +249,12 @@ module Bee
257
249
  lines = file_cache(file)
258
250
  @source = match_tabs(lines, lineno, "def")
259
251
  @comment = preceding_comment(lines, lineno)
260
- @defn = lines[lineno].strip.gsub(/^def\W+(.*?\W*\((.*?)\))/){$1}
261
- @params = $2 ? $2.split(',') : nil
252
+ @defn = lines[lineno].strip.gsub(/^def\W+(.*)/){$1}
253
+ if @defn =~ /.*?\(.*?\)/
254
+ @params = @defn.gsub(/.*?\((.*?)\)/){$1}.split(',').map{|p| p.strip}
255
+ else
256
+ @params = []
257
+ end
262
258
  end
263
259
 
264
260
  private
@@ -333,6 +329,12 @@ module Bee
333
329
  # be displayed on an internal error only). Include BuildErrorMixin to get
334
330
  # a convenient way to raise such an error.
335
331
  class BuildError < RuntimeError
332
+
333
+ # Last met target.
334
+ attr_accessor :target
335
+ # Last met task.
336
+ attr_accessor :task
337
+
336
338
  end
337
339
 
338
340
  # Build error mixin provides error() function to raise a BuildError.
@@ -344,7 +346,7 @@ module Bee
344
346
  # Convenient method to raise a BuildError.
345
347
  # - message: error message.
346
348
  def error(message)
347
- raise BuildError.new(message)
349
+ Kernel.raise BuildError.new(message)
348
350
  end
349
351
 
350
352
  end