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.
- data/README +1 -1
- data/bin/bash_completion_bee +18 -0
- data/bin/bee +1 -1
- data/bin/bee.bat +1 -1
- data/egg/application/build.yml +2 -1
- data/egg/application/gem.spec.erb +1 -0
- data/egg/package/bee_task.erb +1 -1
- data/egg/package/build.erb +1 -0
- data/egg/package/gem_spec.erb +1 -0
- data/egg/package/test.erb +1 -1
- data/egg/package/test_build.rb +1 -1
- data/egg/package/test_build_listener.rb +62 -14
- data/egg/package/test_suite.rb +1 -1
- data/egg/script/build.yml +1 -1
- data/egg/sinatra/build.yml +1 -1
- data/egg/xmlrpc/build.yml +1 -1
- data/lib/{bee.rb → bee_build.rb} +41 -180
- data/lib/bee_console.rb +45 -466
- data/lib/bee_console_formatter.rb +314 -0
- data/lib/bee_console_style.rb +222 -0
- data/lib/bee_context.rb +108 -45
- data/lib/bee_listener.rb +114 -0
- data/lib/bee_properties.rb +47 -76
- data/lib/bee_target.rb +36 -19
- data/lib/bee_targets.rb +147 -0
- data/lib/bee_task_default.rb +78 -60
- data/lib/{bee_task.rb → bee_task_package.rb} +16 -87
- data/lib/bee_task_packagemanager.rb +135 -0
- data/lib/bee_util.rb +58 -56
- data/lib/bee_version.rb +1 -1
- metadata +56 -22
@@ -0,0 +1,314 @@
|
|
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_console_style'
|
17
|
+
|
18
|
+
module Bee
|
19
|
+
|
20
|
+
module Console
|
21
|
+
|
22
|
+
# Class to format build output on console.
|
23
|
+
class Formatter
|
24
|
+
|
25
|
+
include Bee::Util::BuildErrorMixin
|
26
|
+
|
27
|
+
# Minimum duration to print on console even if not verbose (in seconds)
|
28
|
+
AUTO_DURATION = 60
|
29
|
+
|
30
|
+
# Construct formatting order
|
31
|
+
CONSTRUCT_FORMATS = {
|
32
|
+
'if' => ['if', 'then', 'else'],
|
33
|
+
'while' => ['while', 'do'],
|
34
|
+
'for' => ['for', 'in', 'do'],
|
35
|
+
'try' => ['try', 'catch'],
|
36
|
+
}
|
37
|
+
|
38
|
+
# Verbosity indicator
|
39
|
+
attr_reader :verbose
|
40
|
+
|
41
|
+
# Constructor.
|
42
|
+
# - style: style as a Hash or a String.
|
43
|
+
# - color: tells if we use default color scheme. Defaults to false.
|
44
|
+
# - verbose: tells if build is verbose. Defaults to false.
|
45
|
+
# - outputer: object on which we call print and puts for outputs.
|
46
|
+
# Defaults to Kernel.
|
47
|
+
def initialize(style, color=false, verbose=false, outputer=Kernel)
|
48
|
+
@style = Bee::Console::Style.new(style, color)
|
49
|
+
@verbose = verbose
|
50
|
+
@outputer = outputer
|
51
|
+
end
|
52
|
+
|
53
|
+
##########################################################################
|
54
|
+
# LOW LEVEL OUTPUT METHODS #
|
55
|
+
##########################################################################
|
56
|
+
|
57
|
+
# Print a given message on console:
|
58
|
+
# - message: the message to print.
|
59
|
+
def print(message)
|
60
|
+
@outputer.print(message)
|
61
|
+
end
|
62
|
+
|
63
|
+
# Puts a given message on console:
|
64
|
+
# - message: the message to put.
|
65
|
+
def puts(message)
|
66
|
+
@outputer.puts(message)
|
67
|
+
end
|
68
|
+
|
69
|
+
##########################################################################
|
70
|
+
# METHODS CALLED BY LISTENER #
|
71
|
+
##########################################################################
|
72
|
+
|
73
|
+
# Print build start message:
|
74
|
+
# - build: the started build.
|
75
|
+
# - dry_run: tells if we are running in dry mode.
|
76
|
+
def print_build_started(build, dry_run)
|
77
|
+
if @verbose
|
78
|
+
build_type = dry_run ? "dry run of" : "build"
|
79
|
+
puts "Starting #{build_type} '#{build.file}'..."
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
# Print message when build finished:
|
84
|
+
# - duration: the build duration in seconds.
|
85
|
+
# - success: tells if build was a success.
|
86
|
+
# - exception : exception raised, if any.
|
87
|
+
# - last_target: last met target, if any.
|
88
|
+
# - last_task: last met task, if any.
|
89
|
+
def print_build_finished(duration)
|
90
|
+
puts "Built in #{duration} s" if @verbose or duration >= AUTO_DURATION
|
91
|
+
end
|
92
|
+
|
93
|
+
# Print target:
|
94
|
+
# - target: the target we are running.
|
95
|
+
def print_target(target)
|
96
|
+
puts format_target(target)
|
97
|
+
end
|
98
|
+
|
99
|
+
# Print task:
|
100
|
+
# - task: the task we are running.
|
101
|
+
def print_task(task)
|
102
|
+
puts format_task(task) if @verbose
|
103
|
+
end
|
104
|
+
|
105
|
+
##########################################################################
|
106
|
+
# FORMATTING METHODS #
|
107
|
+
##########################################################################
|
108
|
+
|
109
|
+
# Format a target.
|
110
|
+
# - target: target to format.
|
111
|
+
def format_target(target)
|
112
|
+
name = target.name
|
113
|
+
return format_title(name)
|
114
|
+
end
|
115
|
+
|
116
|
+
# Format a task.
|
117
|
+
# - task: task to format.
|
118
|
+
def format_task(task)
|
119
|
+
if task.kind_of?(String)
|
120
|
+
source = task
|
121
|
+
elsif task.kind_of?(Hash)
|
122
|
+
if task.key?('rb')
|
123
|
+
source = "rb: #{task['rb']}"
|
124
|
+
else
|
125
|
+
if task.keys.length == 1
|
126
|
+
source = format_entry(task)
|
127
|
+
else
|
128
|
+
source = format_construct(task)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
formatted = '- ' + source.strip.gsub(/\n/, "\n. ")
|
133
|
+
styled = @style.style(formatted, :task)
|
134
|
+
return styled
|
135
|
+
end
|
136
|
+
|
137
|
+
# Format a success string.
|
138
|
+
# - string: string to format.
|
139
|
+
def format_success(string)
|
140
|
+
string = @style.style(string, :success)
|
141
|
+
return string
|
142
|
+
end
|
143
|
+
|
144
|
+
# Format an error string.
|
145
|
+
# - string: string to format.
|
146
|
+
def format_error(string)
|
147
|
+
string = @style.style(string, :error)
|
148
|
+
return string
|
149
|
+
end
|
150
|
+
|
151
|
+
# Format error message:
|
152
|
+
# - exception: raised exception.
|
153
|
+
def format_error_message(exception)
|
154
|
+
message = format_error('ERROR')
|
155
|
+
message << ": "
|
156
|
+
message << exception.to_s
|
157
|
+
if exception.kind_of?(Bee::Util::BuildError)
|
158
|
+
message << "\nIn target '#{exception.target.name}'" if exception.target
|
159
|
+
message << ", in task:\n#{format_task(exception.task)}" if exception.task
|
160
|
+
end
|
161
|
+
return message
|
162
|
+
end
|
163
|
+
|
164
|
+
# Format a description.
|
165
|
+
# - title: description title (project, property or target name).
|
166
|
+
# - text: description text.
|
167
|
+
# - indent: indentation width.
|
168
|
+
# - bullet: tells if we must put a bullet.
|
169
|
+
def format_description(title, text=nil, indent=0, bullet=true)
|
170
|
+
string = ' '*indent
|
171
|
+
string << '- ' if bullet
|
172
|
+
string << title
|
173
|
+
if text and !text.empty?
|
174
|
+
string << ": "
|
175
|
+
if text.split("\n").length > 1
|
176
|
+
string << "\n"
|
177
|
+
text.split("\n").each do |line|
|
178
|
+
string << ' '*(indent+2) + line.strip + "\n"
|
179
|
+
end
|
180
|
+
else
|
181
|
+
string << text.strip + "\n"
|
182
|
+
end
|
183
|
+
else
|
184
|
+
string << "\n"
|
185
|
+
end
|
186
|
+
return string
|
187
|
+
end
|
188
|
+
|
189
|
+
# Format a title.
|
190
|
+
# - title: title to format.
|
191
|
+
def format_title(title)
|
192
|
+
length = @style.line_length || Bee::Util::term_width
|
193
|
+
right = ' ' + @style.line_character*2
|
194
|
+
size = length - (title.length + 4)
|
195
|
+
size = 2 if size <= 0
|
196
|
+
left = @style.line_character*size + ' '
|
197
|
+
line = left + title + right
|
198
|
+
# apply style
|
199
|
+
formatted = @style.style(line, :target)
|
200
|
+
return formatted
|
201
|
+
end
|
202
|
+
|
203
|
+
##########################################################################
|
204
|
+
# HELP FORMATTING METHODS #
|
205
|
+
##########################################################################
|
206
|
+
|
207
|
+
# Return help about build.
|
208
|
+
# - build: running build.
|
209
|
+
def help_build(build)
|
210
|
+
build.context.evaluate
|
211
|
+
help = ''
|
212
|
+
# print build name and description
|
213
|
+
if build.name
|
214
|
+
help << "build: #{build.name}\n"
|
215
|
+
end
|
216
|
+
if build.extends
|
217
|
+
help << "extends: #{build.extends.map{|b| b.name}.join(', ')}\n"
|
218
|
+
end
|
219
|
+
if build.description
|
220
|
+
help << format_description('description', build.description, 0, false)
|
221
|
+
end
|
222
|
+
# print build properties
|
223
|
+
if build.context.properties.length > 0
|
224
|
+
help << "properties:\n"
|
225
|
+
for property in build.context.properties.sort
|
226
|
+
help << "- #{property}: " +
|
227
|
+
"#{build.context.get_property(property).inspect}\n"
|
228
|
+
end
|
229
|
+
end
|
230
|
+
# print build targets
|
231
|
+
description = build.targets.description
|
232
|
+
if description.length > 0
|
233
|
+
help << "targets:\n"
|
234
|
+
for name in description.keys.sort
|
235
|
+
help << format_description(name, description[name], 0)
|
236
|
+
end
|
237
|
+
end
|
238
|
+
# print default target
|
239
|
+
help << "default: #{build.targets.default}\n"
|
240
|
+
return help.strip
|
241
|
+
end
|
242
|
+
|
243
|
+
# Return help about task(s).
|
244
|
+
# - task: task to print help about (all tasks if nil).
|
245
|
+
def help_task(task)
|
246
|
+
task = '?' if task == nil or task.length == 0
|
247
|
+
package_manager = Bee::Task::PackageManager.new(nil)
|
248
|
+
methods = package_manager.help_task(task)
|
249
|
+
help = ''
|
250
|
+
for method in methods.keys.sort
|
251
|
+
text = methods[method].strip
|
252
|
+
help << format_title(method)
|
253
|
+
help << "\n"
|
254
|
+
help << text
|
255
|
+
help << "\n"
|
256
|
+
if text =~ /Alias for \w+/
|
257
|
+
alias_method = text.scan(/Alias for (\w+)/).flatten[0]
|
258
|
+
help << "\n"
|
259
|
+
help << package_manager.help_task(alias_method)[alias_method].strip
|
260
|
+
help << "\n"
|
261
|
+
end
|
262
|
+
end
|
263
|
+
return help
|
264
|
+
end
|
265
|
+
|
266
|
+
# Return help about template(s).
|
267
|
+
# - template: template to print help about (all templates if nil).
|
268
|
+
def help_template(template)
|
269
|
+
templates = Bee::Util::search_templates(template)
|
270
|
+
help = ''
|
271
|
+
for name in templates.keys
|
272
|
+
build = YAML::load(File.read(templates[name]))
|
273
|
+
properties = nil
|
274
|
+
for entry in build
|
275
|
+
properties = entry['properties'] if entry['properties']
|
276
|
+
end
|
277
|
+
description = 'No description found'
|
278
|
+
if properties
|
279
|
+
if properties['description']
|
280
|
+
description = properties['description']
|
281
|
+
end
|
282
|
+
end
|
283
|
+
help << format_title(name)
|
284
|
+
help << "\n"
|
285
|
+
help << description
|
286
|
+
help << "\n"
|
287
|
+
end
|
288
|
+
return help
|
289
|
+
end
|
290
|
+
|
291
|
+
private
|
292
|
+
|
293
|
+
def format_entry(entry)
|
294
|
+
return YAML::dump(entry).sub(/---/, '').strip
|
295
|
+
end
|
296
|
+
|
297
|
+
def format_construct(construct)
|
298
|
+
for key in CONSTRUCT_FORMATS.keys
|
299
|
+
if construct.has_key?(key)
|
300
|
+
lines = []
|
301
|
+
for entry in CONSTRUCT_FORMATS[key]
|
302
|
+
lines << format_entry({entry => construct[entry]})
|
303
|
+
end
|
304
|
+
return lines.join("\n")
|
305
|
+
end
|
306
|
+
end
|
307
|
+
return "UNKNOWN CONSTRUCT"
|
308
|
+
end
|
309
|
+
|
310
|
+
end
|
311
|
+
|
312
|
+
end
|
313
|
+
|
314
|
+
end
|
@@ -0,0 +1,222 @@
|
|
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 Console
|
21
|
+
|
22
|
+
# Class to manage a style for console output.
|
23
|
+
class Style
|
24
|
+
|
25
|
+
include Bee::Util::BuildErrorMixin
|
26
|
+
|
27
|
+
# style attributes
|
28
|
+
attr_reader :line_character
|
29
|
+
attr_reader :line_length
|
30
|
+
attr_reader :target_style
|
31
|
+
attr_reader :target_foreground
|
32
|
+
attr_reader :target_background
|
33
|
+
attr_reader :task_style
|
34
|
+
attr_reader :task_foreground
|
35
|
+
attr_reader :task_background
|
36
|
+
attr_reader :success_style
|
37
|
+
attr_reader :success_foreground
|
38
|
+
attr_reader :success_background
|
39
|
+
attr_reader :error_style
|
40
|
+
attr_reader :error_foreground
|
41
|
+
attr_reader :error_background
|
42
|
+
|
43
|
+
# List of style types
|
44
|
+
TYPES = [:target, :task, :success, :error]
|
45
|
+
|
46
|
+
# List of colors.
|
47
|
+
COLORS = [:black, :red, :green, :yellow, :blue, :magenta, :cyan, :white]
|
48
|
+
|
49
|
+
# Foreground color codes.
|
50
|
+
FOREGROUND_COLOR_CODES = {
|
51
|
+
:black => 30,
|
52
|
+
:red => 31,
|
53
|
+
:green => 32,
|
54
|
+
:yellow => 33,
|
55
|
+
:blue => 34,
|
56
|
+
:magenta => 35,
|
57
|
+
:cyan => 36,
|
58
|
+
:white => 37
|
59
|
+
}
|
60
|
+
|
61
|
+
# Background color codes.
|
62
|
+
BACKGROUND_COLOR_CODES = {
|
63
|
+
:black => 40,
|
64
|
+
:red => 41,
|
65
|
+
:green => 42,
|
66
|
+
:yellow => 43,
|
67
|
+
:blue => 44,
|
68
|
+
:magenta => 45,
|
69
|
+
:cyan => 46,
|
70
|
+
:white => 47
|
71
|
+
}
|
72
|
+
|
73
|
+
# List of styles.
|
74
|
+
STYLES = [:reset, :bright, :dim, :underscore, :blink, :reverse, :hidden]
|
75
|
+
|
76
|
+
# Style codes.
|
77
|
+
STYLE_CODES = {
|
78
|
+
:reset => 0,
|
79
|
+
:bright => 1,
|
80
|
+
:dim => 2,
|
81
|
+
:underscore => 4,
|
82
|
+
:blink => 5,
|
83
|
+
:reverse => 7,
|
84
|
+
:hidden => 8
|
85
|
+
}
|
86
|
+
|
87
|
+
# Default style (supposed to work on any configuration).
|
88
|
+
DEFAULT_STYLE = {
|
89
|
+
:line_character => '-'
|
90
|
+
}
|
91
|
+
|
92
|
+
# Color style (supposed to work on color terminals).
|
93
|
+
COLOR_STYLE = {
|
94
|
+
:line_character => '-',
|
95
|
+
:target_foreground => :yellow,
|
96
|
+
:task_foreground => :blue,
|
97
|
+
:success_style => :bright,
|
98
|
+
:success_foreground => :green,
|
99
|
+
:error_style => :bright,
|
100
|
+
:error_foreground => :red
|
101
|
+
}
|
102
|
+
|
103
|
+
# Short style keys for command line
|
104
|
+
SHORT_STYLE_KEYS = {
|
105
|
+
'lc' => 'line_character',
|
106
|
+
'll' => 'line_length',
|
107
|
+
'ts' => 'target_style',
|
108
|
+
'tf' => 'target_foreground',
|
109
|
+
'tb' => 'target_background',
|
110
|
+
'ks' => 'task_style',
|
111
|
+
'kf' => 'task_foreground',
|
112
|
+
'kb' => 'task_background',
|
113
|
+
'ss' => 'success_style',
|
114
|
+
'sf' => 'success_foreground',
|
115
|
+
'sb' => 'success_background',
|
116
|
+
'es' => 'error_style',
|
117
|
+
'ef' => 'error_foreground',
|
118
|
+
'eb' => 'error_background'
|
119
|
+
}
|
120
|
+
|
121
|
+
# Build the style from command line arguments:
|
122
|
+
# - style: the style as a hash or a string (as passed on command line).
|
123
|
+
# Defaults to nil.
|
124
|
+
# - color: tells if we use color style. Defaults to nil.
|
125
|
+
def initialize(style=nil, color=nil)
|
126
|
+
@line_character = nil
|
127
|
+
@line_length = nil
|
128
|
+
@target_style = nil
|
129
|
+
@target_foreground = nil
|
130
|
+
@target_background = nil
|
131
|
+
@task_style = nil
|
132
|
+
@task_foreground = nil
|
133
|
+
@task_background = nil
|
134
|
+
@success_style = nil
|
135
|
+
@success_foreground = nil
|
136
|
+
@success_background = nil
|
137
|
+
@error_style = nil
|
138
|
+
@error_foreground = nil
|
139
|
+
@error_background = nil
|
140
|
+
apply(color ? COLOR_STYLE : DEFAULT_STYLE)
|
141
|
+
apply(style)
|
142
|
+
end
|
143
|
+
|
144
|
+
# Apply style to a string:
|
145
|
+
# - string: the string to apply style to.
|
146
|
+
# - type: the type of style to apply (one of :target, :task, :success or
|
147
|
+
# :error).
|
148
|
+
def style(string, type)
|
149
|
+
raise "Type '#{type}' unknown: must be one of " + TYPES.map{|e| ":#{e}"}.join(', ') if
|
150
|
+
not TYPES.include?(type)
|
151
|
+
style = eval("@#{type}_style")
|
152
|
+
foreground = eval("@#{type}_foreground")
|
153
|
+
background = eval("@#{type}_background")
|
154
|
+
# if no style nor colors, return raw string
|
155
|
+
return string if not foreground and not background and not style
|
156
|
+
# insert style and colors in string
|
157
|
+
colorized = "\e["
|
158
|
+
colorized << "#{STYLE_CODES[style]};" if style
|
159
|
+
colorized << "#{FOREGROUND_COLOR_CODES[foreground]};" if foreground
|
160
|
+
colorized << "#{BACKGROUND_COLOR_CODES[background]};" if background
|
161
|
+
colorized = colorized[0..-2]
|
162
|
+
colorized << "m#{string}\e[#{STYLE_CODES[:reset]}m"
|
163
|
+
return colorized
|
164
|
+
end
|
165
|
+
|
166
|
+
private
|
167
|
+
|
168
|
+
# Apply a given style:
|
169
|
+
# - style: the style as a hash or a string.
|
170
|
+
def apply(style)
|
171
|
+
if style.kind_of?(Hash)
|
172
|
+
for key, value in style
|
173
|
+
check_attribute_value(key, value)
|
174
|
+
eval("@#{key} = #{value.inspect}")
|
175
|
+
end
|
176
|
+
elsif style.kind_of?(String)
|
177
|
+
for pair in style.split(',')
|
178
|
+
key, value = pair.split(':')
|
179
|
+
key = SHORT_STYLE_KEYS[key] || key
|
180
|
+
key = key.to_sym
|
181
|
+
if key == :line_length
|
182
|
+
value = value.to_i
|
183
|
+
elsif key == :line_character
|
184
|
+
value = ' ' if not value or value.length == 0
|
185
|
+
else
|
186
|
+
value = value.to_sym if value
|
187
|
+
end
|
188
|
+
check_attribute_value(key, value)
|
189
|
+
eval("@#{key} = #{value.inspect}")
|
190
|
+
end
|
191
|
+
else
|
192
|
+
raise "Style must ne a Hash or a String" if style
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
def check_attribute_value(attribute, value)
|
197
|
+
raise "Attribute '#{attribute}' must be a symbol" unless
|
198
|
+
attribute.kind_of?(Symbol)
|
199
|
+
raise "Unknown attribute '#{attribute}'" unless
|
200
|
+
instance_variable_defined?("@#{attribute}".to_sym)
|
201
|
+
if attribute == :line_length
|
202
|
+
raise "'line_length' attribute must be an integer" unless
|
203
|
+
value.kind_of?(Integer)
|
204
|
+
elsif attribute == :line_character
|
205
|
+
raise "'line_character' must be a single character" unless
|
206
|
+
value.kind_of?(String) and value.length == 1
|
207
|
+
else
|
208
|
+
raise "Value '#{value}' should be a symbol" unless
|
209
|
+
value.kind_of?(Symbol)
|
210
|
+
if attribute.to_s[-6..-1] == '_style'
|
211
|
+
raise "Unkown style '#{value}'" if not STYLES.member?(value)
|
212
|
+
else
|
213
|
+
raise "Unkown color '#{value}'" if not COLORS.member?(value)
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
end
|
219
|
+
|
220
|
+
end
|
221
|
+
|
222
|
+
end
|