sprout 0.5.29 → 0.7.153
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of sprout might be problematic. Click here for more details.
- data/{MIT-LICENSE.txt → MIT-LICENSE} +0 -0
- data/TODO +12 -0
- data/bin/sprout +83 -140
- 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 +2 -3
- data/lib/progress_bar.rb +39 -23
- 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/base_mixins.rb +132 -0
- data/lib/sprout/generator/named_base.rb +216 -0
- data/lib/sprout/generator.rb +6 -0
- data/lib/{log.rb → sprout/log.rb} +2 -2
- data/lib/sprout/process_runner.rb +46 -0
- data/lib/sprout/project_model.rb +114 -0
- data/lib/{remote_file_loader.rb → sprout/remote_file_loader.rb} +63 -36
- 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/{template_resolver.rb → sprout/template_resolver.rb} +10 -7
- data/lib/{user.rb → sprout/user.rb} +84 -37
- data/lib/sprout/version.rb +4 -3
- data/lib/sprout/zip_util.rb +61 -0
- data/lib/sprout.rb +377 -285
- data/rakefile.rb +93 -119
- data/samples/gem_wrap/rakefile.rb +17 -0
- metadata +131 -96
- data/Manifest.txt +0 -9
- data/lib/command.rb +0 -29
- data/lib/file_target.rb +0 -8
- data/lib/generate.rb +0 -37
- data/lib/library.rb +0 -18
- data/lib/process_runner.rb +0 -27
- data/lib/project.rb +0 -10
- data/lib/project_model.rb +0 -59
- data/lib/remote_file_target.rb +0 -62
- data/lib/task.rb +0 -20
- data/lib/template.rb +0 -37
- data/lib/tool.rb +0 -18
- data/setup.rb +0 -1585
@@ -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
|
@@ -0,0 +1,158 @@
|
|
1
|
+
=begin
|
2
|
+
Copyright (c) 2007 Pattern Park
|
3
|
+
|
4
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
a copy of this software and associated documentation files (the
|
6
|
+
"Software"), to deal in the Software without restriction, including
|
7
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be
|
13
|
+
included in all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
=end
|
23
|
+
|
24
|
+
require 'zip/zipfilesystem'
|
25
|
+
|
26
|
+
# TODO: Make this task more like a rake FileTask
|
27
|
+
# The output should be the task name and the input
|
28
|
+
# files should be added as prerequisites
|
29
|
+
|
30
|
+
module Sprout
|
31
|
+
class ZipError < StandardError #:nodoc:
|
32
|
+
end
|
33
|
+
|
34
|
+
# The ZipTask should accept any directory as input and either
|
35
|
+
# an expected zip file name or directory where one will be created
|
36
|
+
# for output.
|
37
|
+
# The resulting zip file will only be generated if a file in the
|
38
|
+
# input directory has a newer timestamp than the existing zip file
|
39
|
+
class ZipTask < Rake::FileTask
|
40
|
+
|
41
|
+
# Array of file names that should not be added to the zip archive.
|
42
|
+
# The default value of this property is:
|
43
|
+
# @excludes = ['.', '..', '.svn', '.cvs', '.DS_Store', '.git', 'CVS', 'Thumbs.db']
|
44
|
+
attr_writer :excludes
|
45
|
+
# The file or folder that should be archived.
|
46
|
+
#
|
47
|
+
# If input is a directory, all of it's contents
|
48
|
+
# will be recursively added to the archive (excluding any files that match +excludes+ of course).
|
49
|
+
#
|
50
|
+
# If input is a file, a new archive will be created with a similar file name and only that file
|
51
|
+
# will be added to the archive.
|
52
|
+
attr_writer :input
|
53
|
+
# Zip archive file to create. Usually, the name of the zip task will be used for this property,
|
54
|
+
# but in cases where you want a particular task name and a different output file, you can set
|
55
|
+
# this parameter.
|
56
|
+
attr_writer :output
|
57
|
+
|
58
|
+
def self.define_task(args, &block) # :nodoc:
|
59
|
+
t = super
|
60
|
+
yield t if block_given?
|
61
|
+
t.define
|
62
|
+
end
|
63
|
+
|
64
|
+
def define # :nodoc:
|
65
|
+
@input = define_input(input)
|
66
|
+
@output = define_output(output || name)
|
67
|
+
end
|
68
|
+
|
69
|
+
def output
|
70
|
+
@output ||= nil
|
71
|
+
end
|
72
|
+
|
73
|
+
def input
|
74
|
+
@input ||= nil
|
75
|
+
end
|
76
|
+
|
77
|
+
def execute(*args) # :nodoc:
|
78
|
+
create_archive
|
79
|
+
end
|
80
|
+
|
81
|
+
def excludes
|
82
|
+
@excludes ||= ['.', '..', '.svn', '.cvs', '.DS_Store', '.git', 'CVS', 'Thumbs.db']
|
83
|
+
end
|
84
|
+
|
85
|
+
private
|
86
|
+
|
87
|
+
def create_archive(force=false) # :nodoc:
|
88
|
+
return unless (force || name == output)
|
89
|
+
|
90
|
+
start = Dir.pwd
|
91
|
+
begin
|
92
|
+
full_output = File.expand_path(output)
|
93
|
+
full_input = File.expand_path(input)
|
94
|
+
Dir.chdir(File.dirname(full_input))
|
95
|
+
masked_input = full_input.gsub("#{Dir.pwd}/", '')
|
96
|
+
|
97
|
+
# Create the containing folder for output
|
98
|
+
if(!File.directory?(File.dirname(full_output)))
|
99
|
+
FileUtils.mkdir_p(File.dirname(full_output))
|
100
|
+
end
|
101
|
+
|
102
|
+
ZipUtil.pack(masked_input, full_output, excludes)
|
103
|
+
|
104
|
+
ensure
|
105
|
+
Dir.chdir(start)
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
|
110
|
+
def define_input(input)
|
111
|
+
file input do |t|
|
112
|
+
raise ZipError.new("ZipTask '#{name}' could not find valid input at: #{input}") unless (File.exists?(input))
|
113
|
+
end
|
114
|
+
|
115
|
+
input_files = FileList["#{input}/**/**/*"]
|
116
|
+
input_files.each do |f|
|
117
|
+
prerequisites << f
|
118
|
+
end
|
119
|
+
prerequisites << input
|
120
|
+
return input
|
121
|
+
end
|
122
|
+
|
123
|
+
def define_output(out)
|
124
|
+
|
125
|
+
# If the provided parent dir doesn't
|
126
|
+
# exist, create it
|
127
|
+
if(!File.exists?(File.dirname(out)))
|
128
|
+
FileUtils.mkdir_p(File.dirname(out))
|
129
|
+
end
|
130
|
+
|
131
|
+
# If the provided output is just a directory
|
132
|
+
# and it's parent doesn't yet exist, create the
|
133
|
+
# provided output directory before appending
|
134
|
+
# the real zip file name
|
135
|
+
if(!File.basename(out).index('.'))
|
136
|
+
FileUtils.mkdir_p(out)
|
137
|
+
end
|
138
|
+
|
139
|
+
# If out is just a directory, append input's basename
|
140
|
+
# to create the zip file
|
141
|
+
if(File.directory?(out))
|
142
|
+
out = File.join(out, File.basename(input) + '.zip')
|
143
|
+
end
|
144
|
+
|
145
|
+
if(out != name)
|
146
|
+
file out do
|
147
|
+
create_archive(true)
|
148
|
+
end
|
149
|
+
prerequisites << out
|
150
|
+
end
|
151
|
+
return out
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
def zip(args, &block)
|
157
|
+
Sprout::ZipTask.define_task(args, &block)
|
158
|
+
end
|