sprout 0.7.153-darwin
Sign up to get free protection for your applications and to get access to all the features.
- data/MIT-LICENSE +20 -0
- data/TODO +12 -0
- data/bin/sprout +128 -0
- data/doc/Bundle +14 -0
- data/doc/Generator +35 -0
- data/doc/Library +63 -0
- data/doc/Task +21 -0
- data/doc/Tool +20 -0
- data/lib/platform.rb +109 -0
- data/lib/progress_bar.rb +330 -0
- data/lib/sprout.rb +456 -0
- data/lib/sprout/builder.rb +35 -0
- data/lib/sprout/commands/generate.rb +14 -0
- data/lib/sprout/general_tasks.rb +5 -0
- data/lib/sprout/generator.rb +6 -0
- data/lib/sprout/generator/base_mixins.rb +132 -0
- data/lib/sprout/generator/named_base.rb +216 -0
- data/lib/sprout/log.rb +46 -0
- data/lib/sprout/process_runner.rb +46 -0
- data/lib/sprout/project_model.rb +114 -0
- data/lib/sprout/remote_file_loader.rb +233 -0
- data/lib/sprout/remote_file_target.rb +96 -0
- data/lib/sprout/simple_resolver.rb +88 -0
- data/lib/sprout/tasks/gem_wrap_task.rb +192 -0
- data/lib/sprout/tasks/library_task.rb +103 -0
- data/lib/sprout/tasks/sftp_task.rb +245 -0
- data/lib/sprout/tasks/tool_task.rb +541 -0
- data/lib/sprout/tasks/zip_task.rb +158 -0
- data/lib/sprout/template_resolver.rb +207 -0
- data/lib/sprout/user.rb +359 -0
- data/lib/sprout/version.rb +10 -0
- data/lib/sprout/zip_util.rb +61 -0
- data/rakefile.rb +129 -0
- data/samples/gem_wrap/rakefile.rb +17 -0
- metadata +159 -0
@@ -0,0 +1,541 @@
|
|
1
|
+
|
2
|
+
module Sprout
|
3
|
+
|
4
|
+
class ToolTaskError < StandardError #:nodoc:
|
5
|
+
end
|
6
|
+
|
7
|
+
# The ToolTask provides some base functionality for any Command Line Interface (CLI) tool.
|
8
|
+
# It also provides support for GUI tools that you would like to expose from the
|
9
|
+
# Command Line (Like the Flash Player for example).
|
10
|
+
#
|
11
|
+
# ToolTask extends Rake::FileTask, and should be thought of in the same way.
|
12
|
+
# Martin Fowler did a much better job of describing Rake and specifically FileTasks than
|
13
|
+
# I can in his (now classic) Rake article[http://martinfowler.com/articles/rake.html#FileTasks] from 2005.
|
14
|
+
#
|
15
|
+
# What this means is that most tool task instances should be named for the file that they will create.
|
16
|
+
# For example, an Sprout::MXMLCTask instance should be named for the SWF that it will generate.
|
17
|
+
#
|
18
|
+
# mxmlc 'bin/SomeProject.swf' => :corelib do |t|
|
19
|
+
# t.input = 'src/SomeProject.as'
|
20
|
+
# t.default_size = '800 600'
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# In general, a tool task will only be executed if it's output file (name) does not exist or
|
24
|
+
# if the output file is older than any file identified as a prerequisite.
|
25
|
+
#
|
26
|
+
# Many of the compiler tasks take advantage of this feature by opting out of unnecessary compilation.
|
27
|
+
#
|
28
|
+
# Subclasses can add and configure command line parameters by calling the protected add_param method
|
29
|
+
# that is implemented on this class.
|
30
|
+
#
|
31
|
+
class ToolTask < Rake::FileTask
|
32
|
+
|
33
|
+
def initialize(name, app) # :nodoc:
|
34
|
+
super
|
35
|
+
@default_gem_name = nil
|
36
|
+
@default_gem_path = nil
|
37
|
+
initialize_task
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.define_task(args, &block)
|
41
|
+
t = super
|
42
|
+
if(t.is_a?(ToolTask))
|
43
|
+
yield t if block_given?
|
44
|
+
t.define
|
45
|
+
t.prepare
|
46
|
+
end
|
47
|
+
return t
|
48
|
+
end
|
49
|
+
|
50
|
+
# Full name of the sprout tool gem that this tool task will use. For example, the MXMLCTask
|
51
|
+
# uses the sprout-flex2sdk-tool at the time of this writing, but will at some point
|
52
|
+
# change to use the sprout-flex3sdk-tool. You can combine this value with gem_version
|
53
|
+
# in order to specify exactly which gem your tool task is executing.
|
54
|
+
def gem_name
|
55
|
+
return @gem_name ||= @default_gem_name
|
56
|
+
end
|
57
|
+
|
58
|
+
def gem_name=(name)
|
59
|
+
@gem_name = name
|
60
|
+
end
|
61
|
+
|
62
|
+
# The exact gem version that you would like the ToolTask to execute. By default this value
|
63
|
+
# should be nil and will download the latest version of the gem that is available unless
|
64
|
+
# there is a version already installed on your system.
|
65
|
+
#
|
66
|
+
# This attribute could be an easy
|
67
|
+
# way to update your local gem to the latest version without leaving your build file,
|
68
|
+
# but it's primary purpose is to allow you to specify very specific versions of the tools
|
69
|
+
# that your project depends on. This way your team can rest assured that they are all
|
70
|
+
# working with the same tools.
|
71
|
+
def gem_version
|
72
|
+
return @gem_version ||= nil
|
73
|
+
end
|
74
|
+
|
75
|
+
def gem_version=(version)
|
76
|
+
@gem_version = version
|
77
|
+
end
|
78
|
+
|
79
|
+
# The path inside the installed gem where an executable can be found. For the MXMLCTask, this
|
80
|
+
# value is 'bin/mxmlc'.
|
81
|
+
def gem_path
|
82
|
+
return @gem_path ||= @default_gem_path
|
83
|
+
end
|
84
|
+
|
85
|
+
# Create a string that can be turned into a file
|
86
|
+
# that rdoc can parse to describe the customized
|
87
|
+
# or generated task using param name, type and
|
88
|
+
# description
|
89
|
+
def to_rdoc
|
90
|
+
result = ''
|
91
|
+
parts = self.class.to_s.split('::')
|
92
|
+
class_name = parts.pop
|
93
|
+
module_count = 0
|
94
|
+
while(module_name = parts.shift)
|
95
|
+
result << "module #{module_name}\n"
|
96
|
+
module_count += 1
|
97
|
+
end
|
98
|
+
|
99
|
+
result << "class #{class_name} < ToolTask\n"
|
100
|
+
|
101
|
+
params.each do |param|
|
102
|
+
result << param.to_rdoc
|
103
|
+
end
|
104
|
+
|
105
|
+
while((module_count -= 1) >= 0)
|
106
|
+
result << "end\nend\n"
|
107
|
+
end
|
108
|
+
|
109
|
+
return result
|
110
|
+
end
|
111
|
+
|
112
|
+
def execute(*args)
|
113
|
+
#puts ">> Executing #{File.basename(exe)} #{to_shell}"
|
114
|
+
exe = Sprout.get_executable(gem_name, gem_path, gem_version)
|
115
|
+
User.execute(exe, to_shell)
|
116
|
+
end
|
117
|
+
|
118
|
+
# Create a string that represents this configured tool for shell execution
|
119
|
+
def to_shell
|
120
|
+
result = []
|
121
|
+
params.each do |param|
|
122
|
+
if(param.visible?)
|
123
|
+
result << param.to_shell
|
124
|
+
end
|
125
|
+
end
|
126
|
+
return result.join(' ')
|
127
|
+
end
|
128
|
+
|
129
|
+
# An Array of all parameters that have been added to this Tool.
|
130
|
+
def params
|
131
|
+
@params ||= []
|
132
|
+
end
|
133
|
+
|
134
|
+
# Called after initialize and define, usually subclasses should
|
135
|
+
# only override define.
|
136
|
+
def prepare
|
137
|
+
# Get each added param to inject prerequisites as necessary
|
138
|
+
params.each do |param|
|
139
|
+
param.prepare_prerequisites
|
140
|
+
end
|
141
|
+
# Ensure there are no duplicates in the prerequisite collection
|
142
|
+
@prerequisites = prerequisites.uniq
|
143
|
+
end
|
144
|
+
|
145
|
+
def define
|
146
|
+
resolve_libraries(prerequisites)
|
147
|
+
end
|
148
|
+
|
149
|
+
# The default file expression to append to each PathParam
|
150
|
+
# in order to build file change prerequisites.
|
151
|
+
#
|
152
|
+
# Defaults to '/**/**/*'
|
153
|
+
#
|
154
|
+
def default_file_expression
|
155
|
+
@default_file_expression ||= '/**/**/*'
|
156
|
+
end
|
157
|
+
|
158
|
+
protected
|
159
|
+
|
160
|
+
def initialize_task
|
161
|
+
end
|
162
|
+
|
163
|
+
def validate
|
164
|
+
params.each do |param|
|
165
|
+
param.validate
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
# +add_param+ is the workhorse of the ToolTask.
|
170
|
+
# This method is used to add new shell parameters to the task.
|
171
|
+
# +name+ is a symbol or string that represents the parameter that you would like to add
|
172
|
+
# such as :debug or :source_path.
|
173
|
+
# +type+ is usually sent as a Ruby symbol and can be one of the following:
|
174
|
+
#
|
175
|
+
# [:string] Any string value
|
176
|
+
# [:boolean] true or false
|
177
|
+
# [:number] Any number
|
178
|
+
# [:file] Path to a file
|
179
|
+
# [:url] Basic URL
|
180
|
+
# [:path] Path to a directory
|
181
|
+
# [:files] Collection of files
|
182
|
+
# [:paths] Collection of directories
|
183
|
+
# [:strings] Collection of arbitrary strings
|
184
|
+
# [:urls] Collection of URLs
|
185
|
+
#
|
186
|
+
# Be sure to check out the Sprout::TaskParam class to learn more about
|
187
|
+
# block editing the parameters.
|
188
|
+
#
|
189
|
+
# Once parameters have been added using the +add_param+ method, clients
|
190
|
+
# can set and get those parameters from the newly created task.
|
191
|
+
#
|
192
|
+
def add_param(name, type, &block) # :yields: Sprout::TaskParam
|
193
|
+
name = name.to_s
|
194
|
+
|
195
|
+
# First ensure the named accessor doesn't yet exist...
|
196
|
+
if(param_hash[name])
|
197
|
+
raise TaskBaseError.new("TaskBase.add_param called with existing parameter name: #{name}")
|
198
|
+
end
|
199
|
+
|
200
|
+
param = create_param(type)
|
201
|
+
param.init do |p|
|
202
|
+
p.belongs_to = self
|
203
|
+
p.name = name
|
204
|
+
p.type = type
|
205
|
+
yield p if block_given?
|
206
|
+
end
|
207
|
+
|
208
|
+
param_hash[name] = param
|
209
|
+
params << param
|
210
|
+
end
|
211
|
+
|
212
|
+
# Alias an existing parameter with another name. For example, the
|
213
|
+
# existing parameter :source_path might be given an alias '-sp' as follows:
|
214
|
+
#
|
215
|
+
# add_param_alias(:sp, :source_path)
|
216
|
+
#
|
217
|
+
# Alias parameters cannot be configured differently from the parameter
|
218
|
+
# that they alias
|
219
|
+
#
|
220
|
+
def add_param_alias(name, other_param)
|
221
|
+
if(param_hash.has_key? other_param.to_s)
|
222
|
+
param_hash[name.to_s] = param_hash[other_param.to_s]
|
223
|
+
else
|
224
|
+
raise TaskBaseError.new("TaskBase.add_param_alis called with")
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
protected
|
229
|
+
|
230
|
+
def create_param(type)
|
231
|
+
return eval("#{type.to_s.capitalize}Param.new")
|
232
|
+
end
|
233
|
+
|
234
|
+
def param_hash
|
235
|
+
@param_hash ||= {}
|
236
|
+
end
|
237
|
+
|
238
|
+
def respond_to?(name)
|
239
|
+
result = super
|
240
|
+
if(!result)
|
241
|
+
result = param_hash.has_key? name
|
242
|
+
end
|
243
|
+
return result
|
244
|
+
end
|
245
|
+
|
246
|
+
def clean_name(name)
|
247
|
+
name.gsub(/=$/, '')
|
248
|
+
end
|
249
|
+
|
250
|
+
def method_missing(name,*args)
|
251
|
+
name = name.to_s
|
252
|
+
cleaned = clean_name(name)
|
253
|
+
if(!respond_to?(cleaned))
|
254
|
+
raise NoMethodError.new("undefined method '#{name}' for #{self.class}")
|
255
|
+
end
|
256
|
+
param = param_hash[cleaned]
|
257
|
+
|
258
|
+
if(name =~ /=$/)
|
259
|
+
param.value = args.shift
|
260
|
+
elsif(param)
|
261
|
+
param.value
|
262
|
+
else
|
263
|
+
raise ToolTaskError.new("method_missing called with undefined parameter [#{name}]")
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
# Iterate over all prerequisites looking for any
|
268
|
+
# that are a LibraryTask.
|
269
|
+
# Concrete ToolTask implementations should
|
270
|
+
# override resolve_library in order to add
|
271
|
+
# the library sources or binaries appropriately.
|
272
|
+
def resolve_libraries(prerequisites)
|
273
|
+
prerequisites.each do |prereq|
|
274
|
+
instance = Rake::application[prereq]
|
275
|
+
if(instance.is_a?(LibraryTask))
|
276
|
+
resolve_library(instance)
|
277
|
+
end
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
281
|
+
# Concrete ToolTasks should override this method
|
282
|
+
# and add any dependent libraries appropriately
|
283
|
+
def resolve_library(library_task)
|
284
|
+
end
|
285
|
+
|
286
|
+
# If the provided path contains spaces, wrap it in quotes so that
|
287
|
+
# shell tools won't choke on the spaces
|
288
|
+
def clean_path(path)
|
289
|
+
if(path.index(' '))
|
290
|
+
path = %{"#{path}"}
|
291
|
+
end
|
292
|
+
return path
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
296
|
+
#######################################################
|
297
|
+
# Parameter Implementations
|
298
|
+
|
299
|
+
# The base class for all ToolTask parameters. This class is extended by a variety
|
300
|
+
# of concrete implementations.
|
301
|
+
#
|
302
|
+
# At the time of this writing, only the :boolean TaskParam modifies the interface by
|
303
|
+
# adding the +show_on_false+ attribute.
|
304
|
+
#
|
305
|
+
# Some other helpful features are as follows:
|
306
|
+
#
|
307
|
+
# :file, :files, :path and :paths will all add any items that have been added to
|
308
|
+
# their values as file task prerequisites. This is especially helpful when writing
|
309
|
+
# rake tasks for Command Line Interface (CLI) compilers.
|
310
|
+
#
|
311
|
+
class TaskParam
|
312
|
+
attr_accessor :name
|
313
|
+
attr_accessor :type
|
314
|
+
attr_accessor :validator
|
315
|
+
attr_accessor :description
|
316
|
+
attr_accessor :visible
|
317
|
+
attr_accessor :hidden_name
|
318
|
+
attr_accessor :hidden_value
|
319
|
+
attr_accessor :required
|
320
|
+
attr_accessor :belongs_to
|
321
|
+
|
322
|
+
attr_writer :prefix
|
323
|
+
attr_writer :value
|
324
|
+
attr_writer :delimiter
|
325
|
+
|
326
|
+
# Set the file_expression (blob) to append to each path
|
327
|
+
# in order to build the prerequisites FileList.
|
328
|
+
#
|
329
|
+
# Defaults to parent ToolTask.default_file_expression
|
330
|
+
attr_writer :file_expression
|
331
|
+
|
332
|
+
def init
|
333
|
+
yield self if block_given?
|
334
|
+
end
|
335
|
+
|
336
|
+
# By default, ToolParams only appear in the shell
|
337
|
+
# output when they are not nil
|
338
|
+
def visible?
|
339
|
+
@visible ||= value
|
340
|
+
end
|
341
|
+
|
342
|
+
def required?
|
343
|
+
(required == true)
|
344
|
+
end
|
345
|
+
|
346
|
+
def validate
|
347
|
+
if(required? && !visible?)
|
348
|
+
raise TaskBaseError.new("#{name} is required and must not be nil")
|
349
|
+
end
|
350
|
+
end
|
351
|
+
|
352
|
+
def prepare_prerequisites
|
353
|
+
end
|
354
|
+
|
355
|
+
# Should the param name be hidden from the shell?
|
356
|
+
# Used for params like 'input' on mxmlc
|
357
|
+
def hidden_name?
|
358
|
+
@hidden_name ||= false
|
359
|
+
end
|
360
|
+
|
361
|
+
# Should the param value be hidden from the shell?
|
362
|
+
# Usually used for Boolean toggles like '-debug'
|
363
|
+
def hidden_value?
|
364
|
+
@hidden_value ||= false
|
365
|
+
end
|
366
|
+
|
367
|
+
# Leading character for each parameter
|
368
|
+
# Can sometimes be an empty string,
|
369
|
+
# other times it's a double dash '--'
|
370
|
+
# but usually it's just a single dash '-'
|
371
|
+
def prefix
|
372
|
+
@prefix ||= '-'
|
373
|
+
end
|
374
|
+
|
375
|
+
def value
|
376
|
+
@value ||= nil
|
377
|
+
end
|
378
|
+
|
379
|
+
def shell_value
|
380
|
+
value.to_s
|
381
|
+
end
|
382
|
+
|
383
|
+
def file_expression # :nodoc:
|
384
|
+
@file_expression ||= belongs_to.default_file_expression
|
385
|
+
end
|
386
|
+
|
387
|
+
# ToolParams join their name/value pair with an
|
388
|
+
# equals sign by default, this can be modified
|
389
|
+
# To a space or whatever you wish
|
390
|
+
def delimiter
|
391
|
+
@delimiter ||= '='
|
392
|
+
end
|
393
|
+
|
394
|
+
# Return the name with a single leading dash
|
395
|
+
# and underscores replaced with dashes
|
396
|
+
def shell_name
|
397
|
+
@shell_name ||= prefix + name.split('_').join('-')
|
398
|
+
end
|
399
|
+
|
400
|
+
def to_shell
|
401
|
+
if(hidden_name?)
|
402
|
+
return shell_value
|
403
|
+
elsif(hidden_value?)
|
404
|
+
return shell_name
|
405
|
+
else
|
406
|
+
return "#{shell_name}#{delimiter}#{shell_value}"
|
407
|
+
end
|
408
|
+
end
|
409
|
+
|
410
|
+
# Create a string that can be turned into a file
|
411
|
+
# that rdoc can parse to describe the customized
|
412
|
+
# or generated task using param name, type and
|
413
|
+
# description
|
414
|
+
def to_rdoc
|
415
|
+
result = ''
|
416
|
+
parts = description.split("\n") unless description.nil?
|
417
|
+
result << "# #{parts.join("\n# ")}\n" unless description.nil?
|
418
|
+
result << "def #{name}=(#{type})\n @#{name} = #{type}\nend\n\n"
|
419
|
+
return result
|
420
|
+
end
|
421
|
+
|
422
|
+
end
|
423
|
+
|
424
|
+
# Concrete param object for :string values
|
425
|
+
class StringParam < TaskParam # :nodoc:
|
426
|
+
end
|
427
|
+
|
428
|
+
# Concrete param object for :symbol values
|
429
|
+
class SymbolParam < TaskParam # :nodoc:
|
430
|
+
end
|
431
|
+
|
432
|
+
# Concrete param object for :url values
|
433
|
+
class UrlParam < TaskParam # :nodoc:
|
434
|
+
end
|
435
|
+
|
436
|
+
# Concrete param object for :number values
|
437
|
+
class NumberParam < TaskParam # :nodoc:
|
438
|
+
end
|
439
|
+
|
440
|
+
# Concrete param object for :file values
|
441
|
+
class FileParam < TaskParam # :nodoc:
|
442
|
+
def prepare_prerequisites
|
443
|
+
if(value && value != belongs_to.name.to_s)
|
444
|
+
file value
|
445
|
+
belongs_to.prerequisites << value
|
446
|
+
end
|
447
|
+
end
|
448
|
+
end
|
449
|
+
|
450
|
+
# Concrete param object for :path values
|
451
|
+
class PathParam < FileParam # :nodoc:
|
452
|
+
end
|
453
|
+
|
454
|
+
# Concrete param object for :boolean values
|
455
|
+
class BooleanParam < TaskParam # :nodoc:
|
456
|
+
attr_writer :show_on_false
|
457
|
+
|
458
|
+
def visible?
|
459
|
+
@visible ||= value
|
460
|
+
if(show_on_false)
|
461
|
+
return true unless value
|
462
|
+
else
|
463
|
+
return @visible
|
464
|
+
end
|
465
|
+
end
|
466
|
+
|
467
|
+
def show_on_false
|
468
|
+
@show_on_false ||= false
|
469
|
+
end
|
470
|
+
|
471
|
+
def value
|
472
|
+
@value ||= false
|
473
|
+
end
|
474
|
+
|
475
|
+
end
|
476
|
+
|
477
|
+
# Concrete param object for collections of strings
|
478
|
+
class StringsParam < TaskParam # :nodoc:
|
479
|
+
|
480
|
+
# Files lists are initialized to an empty array by default
|
481
|
+
def value
|
482
|
+
@value ||= []
|
483
|
+
end
|
484
|
+
|
485
|
+
# By default, the FilesParams will not appear in the shell
|
486
|
+
# output if there are zero items in the collection
|
487
|
+
def visible?
|
488
|
+
@visible ||= (value && value.size > 0)
|
489
|
+
end
|
490
|
+
|
491
|
+
# Default delimiter is +=
|
492
|
+
# This is what will appear between each name/value pair as in:
|
493
|
+
# "source_path+=src source_path+=test source_path+=lib"
|
494
|
+
def delimiter
|
495
|
+
@delimiter ||= "+="
|
496
|
+
end
|
497
|
+
|
498
|
+
# Returns a shell formatted string of the collection
|
499
|
+
def to_shell
|
500
|
+
result = []
|
501
|
+
value.each do |str|
|
502
|
+
result << "#{shell_name}#{delimiter}#{str}"
|
503
|
+
end
|
504
|
+
return result.join(' ')
|
505
|
+
end
|
506
|
+
end
|
507
|
+
|
508
|
+
# Concrete param object for collections of symbols (like class names)
|
509
|
+
class SymbolsParam < StringsParam # :nodoc:
|
510
|
+
end
|
511
|
+
|
512
|
+
# Concrete param object for collections of files
|
513
|
+
class FilesParam < StringsParam # :nodoc:
|
514
|
+
|
515
|
+
def prepare_prerequisites
|
516
|
+
value.each do |f|
|
517
|
+
file f
|
518
|
+
belongs_to.prerequisites << f
|
519
|
+
end
|
520
|
+
end
|
521
|
+
end
|
522
|
+
|
523
|
+
# Concrete param object for collections of paths
|
524
|
+
class PathsParam < StringsParam # :nodoc:
|
525
|
+
|
526
|
+
def prepare_prerequisites
|
527
|
+
value.each do |f|
|
528
|
+
files = FileList[f + file_expression]
|
529
|
+
files.each do |req_file|
|
530
|
+
file req_file
|
531
|
+
belongs_to.prerequisites << req_file
|
532
|
+
end
|
533
|
+
end
|
534
|
+
end
|
535
|
+
end
|
536
|
+
|
537
|
+
# Concrete param object for collections of files
|
538
|
+
class UrlsParam < StringsParam # :nodoc:
|
539
|
+
end
|
540
|
+
|
541
|
+
end
|