bee 0.10.2 → 0.11.0

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