sprout 0.7.219-i686-darwin10

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.

@@ -0,0 +1,153 @@
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
+
23
+ This class has been commented out because the termios feature
24
+ that allows users to more securely enter passwords does not
25
+ work in a DOS shell.
26
+
27
+ It would be greatly appreciate if someone refactored this to either:
28
+ a) Get the same functionality in a cross-platform manner
29
+ b) Only require and use termios on systems that allow it
30
+ =end
31
+
32
+ #gem 'net-ssh', '1.1.4'
33
+ #gem 'net-sftp', '1.1.1'
34
+
35
+ require 'net/ssh'
36
+ require 'net/sftp'
37
+ #require 'termios'
38
+
39
+ module Sprout
40
+ class SSHError < StandardError #:nodoc:
41
+ end
42
+
43
+ # The SSHTask allows you to execute arbitrary commands on a remote host.
44
+ #
45
+ # ssh :update_gem_index do |t|
46
+ # t.host = 'dev.projectsprouts.com'
47
+ # t.username = 'someUser'
48
+ # t.commands << 'cd /var/www/projectsprouts/current/gems'
49
+ # t.commands << 'gem generate_index -d .'
50
+ # end
51
+ #
52
+ class SSHTask < Rake::Task
53
+
54
+ # Host name of the server to connect to with no protocol prefix, like: sub.yourhost.com
55
+ attr_accessor :host
56
+ # Array of commands that will be executed on the remote machine
57
+ attr_accessor :commands
58
+ # Username to send to the remote host. You will be prompted for this value if it is left null.
59
+ attr_accessor :username
60
+ # Password to send to the remote host. You will be prompted for this value if it is left null.
61
+ #
62
+ # NOTE: You should never check a file into version control with this field filled in, it is
63
+ # provided here as a convenience for getting set up.
64
+ attr_accessor :password
65
+
66
+ def initialize(task_name, app)
67
+ super(task_name, app)
68
+ @name = name
69
+ @host = nil
70
+ @queue = []
71
+ @commands = []
72
+ end
73
+
74
+ def self.define_task(args, &block) # :nodoc:
75
+ t = super
76
+ yield t if block_given?
77
+ end
78
+
79
+ def execute(*args) # :nodoc:
80
+ if(@host.nil?)
81
+ throw SSHError.new('SSH requires a valid host parameter')
82
+ end
83
+
84
+ if(@username.nil?)
85
+ print "Username: "
86
+ @username = $stdin.gets.chomp!
87
+ raise SFTPError.new('SFTP requires username parameter') unless @username
88
+ end
89
+
90
+ if(@password.nil?)
91
+ print "Password: "
92
+ @password = $stdin.gets.chomp!
93
+ # @password = Password.get
94
+ raise SFTPError.new('SFTP requires password parameter') unless @password
95
+ end
96
+
97
+ puts ">> Connecting to Remote Server: #{@username}@#{@host}:#{@remote_path}"
98
+ Net::SSH.start(@host, @username, @password) do |session|
99
+ session.open_channel do |channel|
100
+ commands.each do |command|
101
+ puts ">> #{command}"
102
+ channel.exec command
103
+ end
104
+ channel.close
105
+ end
106
+ session.loop
107
+ end
108
+ end
109
+
110
+ end
111
+
112
+ =begin
113
+ # The following implementation does not work at all on DOS machines,
114
+ # is there a cross-platform way to solve the secure password prompt problem?
115
+ # Password handling snippet found at: http://www.caliban.org/ruby/ruby-password.shtml
116
+ class Password
117
+
118
+ def Password.get(message="Password: ")
119
+ begin
120
+ if $stdin.tty?
121
+ Password.echo false
122
+ print message if message
123
+ end
124
+
125
+ return $stdin.gets.chomp
126
+ ensure
127
+ if $stdin.tty?
128
+ Password.echo true
129
+ print "\n"
130
+ end
131
+ end
132
+ end
133
+
134
+ def Password.echo(on=true, masked=false)
135
+ term = Termios::getattr( $stdin )
136
+
137
+ if on
138
+ term.c_lflag |= ( Termios::ECHO | Termios::ICANON )
139
+ else # off
140
+ term.c_lflag &= ~Termios::ECHO
141
+ term.c_lflag &= ~Termios::ICANON if masked
142
+ end
143
+
144
+ Termios::setattr( $stdin, Termios::TCSANOW, term )
145
+ end
146
+ end
147
+ =end
148
+ end
149
+
150
+
151
+ def ssh(args, &block)
152
+ Sprout::SSHTask.define_task(args, &block)
153
+ end
@@ -0,0 +1,793 @@
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
+ @@preprocessed_tasks = Hash.new
33
+
34
+ def self.add_preprocessed_task(name)
35
+ @@preprocessed_tasks[name] = true
36
+ end
37
+
38
+ def self.has_preprocessed_task?(name)
39
+ !@@preprocessed_tasks[name].nil?
40
+ end
41
+
42
+ def self.clear_preprocessed_tasks
43
+ @@preprocessed_tasks.clear
44
+ end
45
+
46
+ def initialize(name, app) # :nodoc:
47
+ super
48
+ @preprocessed_path = nil
49
+ @prepended_args = nil
50
+ @appended_args = nil
51
+ @default_gem_name = nil
52
+ @default_gem_path = nil
53
+ initialize_task
54
+ end
55
+
56
+ def self.define_task(args, &block)
57
+ t = super
58
+ if(t.is_a?(ToolTask))
59
+ yield t if block_given?
60
+ t.define
61
+ t.prepare
62
+ end
63
+ return t
64
+ end
65
+
66
+ # Full name of the sprout tool gem that this tool task will use. For example, the MXMLCTask
67
+ # uses the sprout-flex3sdk-tool at the time of this writing, but will at some point
68
+ # change to use the sprout-flex3sdk-tool. You can combine this value with gem_version
69
+ # in order to specify exactly which gem your tool task is executing.
70
+ def gem_name
71
+ return @gem_name ||= @default_gem_name
72
+ end
73
+
74
+ def gem_name=(name)
75
+ @gem_name = name
76
+ end
77
+
78
+ # The exact gem version that you would like the ToolTask to execute. By default this value
79
+ # should be nil and will download the latest version of the gem that is available unless
80
+ # there is a version already installed on your system.
81
+ #
82
+ # This attribute could be an easy
83
+ # way to update your local gem to the latest version without leaving your build file,
84
+ # but it's primary purpose is to allow you to specify very specific versions of the tools
85
+ # that your project depends on. This way your team can rest assured that they are all
86
+ # working with the same tools.
87
+ def gem_version
88
+ return @gem_version ||= nil
89
+ end
90
+
91
+ def gem_version=(version)
92
+ @gem_version = version
93
+ end
94
+
95
+ # The path inside the installed gem where an executable can be found. For the MXMLCTask, this
96
+ # value is 'bin/mxmlc'.
97
+ def gem_path
98
+ return @gem_path ||= @default_gem_path
99
+ end
100
+
101
+ # Create a string that can be turned into a file
102
+ # that rdoc can parse to describe the customized
103
+ # or generated task using param name, type and
104
+ # description
105
+ def to_rdoc
106
+ result = ''
107
+ parts = self.class.to_s.split('::')
108
+ class_name = parts.pop
109
+ module_count = 0
110
+ while(module_name = parts.shift)
111
+ result << "module #{module_name}\n"
112
+ module_count += 1
113
+ end
114
+
115
+ result << "class #{class_name} < ToolTask\n"
116
+
117
+ params.each do |param|
118
+ result << param.to_rdoc
119
+ end
120
+
121
+ while((module_count -= 1) >= 0)
122
+ result << "end\nend\n"
123
+ end
124
+
125
+ return result
126
+ end
127
+
128
+ # Arguments to be prepended in front of the command line output
129
+ def prepended_args=(args)
130
+ @prepended_args = args
131
+ end
132
+
133
+ # Returns arguments that were prepended in front of the command line output
134
+ def prepended_args
135
+ @prepended_args
136
+ end
137
+
138
+ # Arguments to appended at the end of the command line output
139
+ def appended_args=(args)
140
+ @appended_args = args
141
+ end
142
+
143
+ # Returns arguments that were appended at the end of the command line output
144
+ def appended_args
145
+ @appended_args
146
+ end
147
+
148
+ # Command line arguments to execute preprocessor.
149
+ # The preprocessor execution should accept text via STDIN and return its processed content via STDOUT.
150
+ #
151
+ # In the following example, the +MXMLCTask+ has been configured to use the C preprocessor (cpp) and
152
+ # place the processed output into a +_preprocessed+ folder, instead of the hidden default folder at
153
+ # .preprocessed.
154
+ #
155
+ # One side effect of the cpp tool is that it adds 2 carriage returns to the top of any processed files,
156
+ # so we have simply piped its output to the tail command which then strips those carriage returns from
157
+ # all files - which retains accurate line numbers for any compiler error messages.
158
+ #
159
+ # mxmlc 'bin/SomeProject.swf' => :corelib do |t|
160
+ # t.input = 'src/SomeProject.as'
161
+ # t.default_size = '800 600'
162
+ # t.preprocessor = 'cpp -D__DEBUG=true -P - - | tail -c +3'
163
+ # t.preprocessed_path = '_preprocessed'
164
+ # end
165
+ #
166
+ # Any source files found in this example project can now take advantage of any tools, macros or syntax
167
+ # available to CPP. For example, the +__DEBUG+ variable is now defined and can be accessed in ActionScript
168
+ # source code as follows:
169
+ #
170
+ # public static const DEBUG:Boolean = __DEBUG;
171
+ #
172
+ # Any commandline tool identified on this attribute will be provided the content of each file on STDIN and
173
+ # whatever it returns to STDOUT will be written into the +preprocessed_path+. This means that we can
174
+ # take advantage of the entire posix tool chain by piping inputs and outputs from one tool to another.
175
+ # Whatever the last tool returns will be handed off to the concrete compiler.
176
+ def preprocessor=(preprocessor)
177
+ @preprocessor = preprocessor
178
+ end
179
+
180
+ def preprocessor
181
+ @preprocessor
182
+ end
183
+
184
+ # Path where preprocessed files are stored. Defaults to '.preprocessed'
185
+ def preprocessed_path=(preprocessed_path)
186
+ @preprocessed_path = preprocessed_path
187
+ end
188
+
189
+ def preprocessed_path
190
+ @preprocessed_path ||= '.preprocessed'
191
+ end
192
+
193
+ def display_preprocess_message # :nodoc:
194
+ if(!preprocessor.nil?)
195
+ puts ">> Preprocessed text files in: #{File.join(Dir.pwd, preprocessed_path)} with #{preprocessor}"
196
+ end
197
+ end
198
+
199
+ def execute(*args)
200
+ display_preprocess_message
201
+ #puts ">> Executing #{File.basename(exe)} #{to_shell}"
202
+ exe = Sprout.get_executable(gem_name, gem_path, gem_version)
203
+ User.execute(exe, to_shell)
204
+ end
205
+
206
+ # Create a string that represents this configured tool for shell execution
207
+ def to_shell
208
+ return @to_shell_proc.call(self) if(!@to_shell_proc.nil?)
209
+
210
+ result = []
211
+ result << @prepended_args unless @prepended_args.nil?
212
+ params.each do |param|
213
+ if(param.visible?)
214
+ result << param.to_shell
215
+ end
216
+ end
217
+ result << @appended_args unless @appended_args.nil?
218
+ return result.join(' ')
219
+ end
220
+
221
+ # An Array of all parameters that have been added to this Tool.
222
+ def params
223
+ @params ||= []
224
+ end
225
+
226
+ # Called after initialize and define, usually subclasses should
227
+ # only override define.
228
+ def prepare
229
+ # Get each added param to inject prerequisites as necessary
230
+ params.each do |param|
231
+ param.prepare
232
+ end
233
+ # Ensure there are no duplicates in the prerequisite collection
234
+ @prerequisites = prerequisites.uniq
235
+ end
236
+
237
+ def define
238
+ resolve_libraries(prerequisites)
239
+ end
240
+
241
+ # The default file expression to append to each PathParam
242
+ # in order to build file change prerequisites.
243
+ #
244
+ # Defaults to '/**/**/*'
245
+ #
246
+ def default_file_expression
247
+ @default_file_expression ||= '/**/**/*'
248
+ end
249
+
250
+ protected
251
+
252
+ def initialize_task
253
+ end
254
+
255
+ def validate
256
+ params.each do |param|
257
+ param.validate
258
+ end
259
+ end
260
+
261
+ # +add_param+ is the workhorse of the ToolTask.
262
+ # This method is used to add new shell parameters to the task.
263
+ # +name+ is a symbol or string that represents the parameter that you would like to add
264
+ # such as :debug or :source_path.
265
+ # +type+ is usually sent as a Ruby symbol and can be one of the following:
266
+ #
267
+ # [:string] Any string value
268
+ # [:boolean] true or false
269
+ # [:number] Any number
270
+ # [:file] Path to a file
271
+ # [:url] Basic URL
272
+ # [:path] Path to a directory
273
+ # [:files] Collection of files
274
+ # [:paths] Collection of directories
275
+ # [:strings] Collection of arbitrary strings
276
+ # [:urls] Collection of URLs
277
+ #
278
+ # Be sure to check out the Sprout::TaskParam class to learn more about
279
+ # block editing the parameters.
280
+ #
281
+ # Once parameters have been added using the +add_param+ method, clients
282
+ # can set and get those parameters from the newly created task.
283
+ #
284
+ def add_param(name, type, &block) # :yields: Sprout::TaskParam
285
+ name = name.to_s
286
+
287
+ # First ensure the named accessor doesn't yet exist...
288
+ if(param_hash[name])
289
+ raise ToolTaskError.new("TaskBase.add_param called with existing parameter name: #{name}")
290
+ end
291
+
292
+ param = create_param(type)
293
+ param.init do |p|
294
+ p.belongs_to = self
295
+ p.name = name
296
+ p.type = type
297
+ yield p if block_given?
298
+ end
299
+
300
+ param_hash[name] = param
301
+ params << param
302
+ end
303
+
304
+ # Alias an existing parameter with another name. For example, the
305
+ # existing parameter :source_path might be given an alias '-sp' as follows:
306
+ #
307
+ # add_param_alias(:sp, :source_path)
308
+ #
309
+ # Alias parameters cannot be configured differently from the parameter
310
+ # that they alias
311
+ #
312
+ def add_param_alias(name, other_param)
313
+ if(param_hash.has_key? other_param.to_s)
314
+ param_hash[name.to_s] = param_hash[other_param.to_s]
315
+ else
316
+ raise ToolTaskError.new("TaskBase.add_param_alis called with")
317
+ end
318
+ end
319
+
320
+ protected
321
+
322
+ def create_param(type)
323
+ return eval("#{type.to_s.capitalize}Param.new")
324
+ end
325
+
326
+ def param_hash
327
+ @param_hash ||= {}
328
+ end
329
+
330
+ def respond_to?(name)
331
+ result = super
332
+ if(!result)
333
+ result = param_hash.has_key? name
334
+ end
335
+ return result
336
+ end
337
+
338
+ def clean_name(name)
339
+ name.gsub(/=$/, '')
340
+ end
341
+
342
+ def method_missing(name,*args)
343
+ name = name.to_s
344
+ cleaned = clean_name(name)
345
+ if(!respond_to?(cleaned))
346
+ raise NoMethodError.new("undefined method '#{name}' for #{self.class}", name)
347
+ end
348
+ param = param_hash[cleaned]
349
+
350
+ if(name =~ /=$/)
351
+ param.value = args.shift
352
+ elsif(param)
353
+ param.value
354
+ else
355
+ raise ToolTaskError.new("method_missing called with undefined parameter [#{name}]")
356
+ end
357
+ end
358
+
359
+ # Iterate over all prerequisites looking for any
360
+ # that are a LibraryTask.
361
+ # Concrete ToolTask implementations should
362
+ # override resolve_library in order to add
363
+ # the library sources or binaries appropriately.
364
+ def resolve_libraries(prerequisites)
365
+ prerequisites.each do |prereq|
366
+ instance = Rake::application[prereq]
367
+ if(instance.is_a?(LibraryTask))
368
+ resolve_library(instance)
369
+ end
370
+ end
371
+ end
372
+
373
+ # Concrete ToolTasks should override this method
374
+ # and add any dependent libraries appropriately
375
+ def resolve_library(library_task)
376
+ end
377
+
378
+ # If the provided path contains spaces, wrap it in quotes so that
379
+ # shell tools won't choke on the spaces
380
+ def clean_path(path)
381
+ if(path.index(' '))
382
+ path = %{"#{path}"}
383
+ end
384
+ return path
385
+ end
386
+
387
+ end
388
+
389
+ #######################################################
390
+ # Parameter Implementations
391
+
392
+ # The base class for all ToolTask parameters. This class is extended by a variety
393
+ # of concrete implementations.
394
+ #
395
+ # At the time of this writing, only the :boolean TaskParam modifies the interface by
396
+ # adding the +show_on_false+ attribute.
397
+ #
398
+ # Some other helpful features are as follows:
399
+ #
400
+ # :file, :files, :path and :paths will all add any items that have been added to
401
+ # their values as file task prerequisites. This is especially helpful when writing
402
+ # rake tasks for Command Line Interface (CLI) compilers.
403
+ #
404
+ class TaskParam
405
+ attr_accessor :belongs_to
406
+ attr_accessor :description
407
+ attr_accessor :hidden_name
408
+ attr_accessor :hidden_value
409
+ attr_accessor :name
410
+ attr_accessor :preprocessable
411
+ attr_accessor :required
412
+ attr_accessor :type
413
+ attr_accessor :validator
414
+ attr_accessor :visible
415
+
416
+ attr_writer :prefix
417
+ attr_writer :value
418
+ attr_writer :delimiter
419
+ attr_writer :shell_name
420
+ attr_writer :to_shell_proc
421
+
422
+ # Set the file_expression (blob) to append to each path
423
+ # in order to build the prerequisites FileList.
424
+ #
425
+ # Defaults to parent ToolTask.default_file_expression
426
+ attr_writer :file_expression
427
+
428
+ def init
429
+ yield self if block_given?
430
+ end
431
+
432
+ # By default, ToolParams only appear in the shell
433
+ # output when they are not nil
434
+ def visible?
435
+ @visible ||= value
436
+ end
437
+
438
+ def required?
439
+ (required == true)
440
+ end
441
+
442
+ def validate
443
+ if(required? && !visible?)
444
+ raise ToolTaskError.new("#{name} is required and must not be nil")
445
+ end
446
+ end
447
+
448
+ def prepare
449
+ prepare_prerequisites
450
+ end
451
+
452
+ def prepare_prerequisites
453
+ end
454
+
455
+ # Should the param name be hidden from the shell?
456
+ # Used for params like 'input' on mxmlc
457
+ def hidden_name?
458
+ @hidden_name ||= false
459
+ end
460
+
461
+ # Should the param value be hidden from the shell?
462
+ # Usually used for Boolean toggles like '-debug'
463
+ def hidden_value?
464
+ @hidden_value ||= false
465
+ end
466
+
467
+ # Leading character for each parameter
468
+ # Can sometimes be an empty string,
469
+ # other times it's a double dash '--'
470
+ # but usually it's just a single dash '-'
471
+ def prefix
472
+ @prefix ||= '-'
473
+ end
474
+
475
+ def value
476
+ @value ||= nil
477
+ end
478
+
479
+ def shell_value
480
+ value.to_s
481
+ end
482
+
483
+ def file_expression # :nodoc:
484
+ @file_expression ||= belongs_to.default_file_expression
485
+ end
486
+
487
+ # ToolParams join their name/value pair with an
488
+ # equals sign by default, this can be modified
489
+ # To a space or whatever you wish
490
+ def delimiter
491
+ @delimiter ||= '='
492
+ end
493
+
494
+ # Return the name with a single leading dash
495
+ # and underscores replaced with dashes
496
+ def shell_name
497
+ @shell_name ||= prefix + name.split('_').join('-')
498
+ end
499
+
500
+ def to_shell
501
+ if(!@to_shell_proc.nil?)
502
+ return @to_shell_proc.call(self)
503
+ elsif(hidden_name?)
504
+ return shell_value
505
+ elsif(hidden_value?)
506
+ return shell_name
507
+ else
508
+ return "#{shell_name}#{delimiter}#{shell_value}"
509
+ end
510
+ end
511
+
512
+ # Create a string that can be turned into a file
513
+ # that rdoc can parse to describe the customized
514
+ # or generated task using param name, type and
515
+ # description
516
+ def to_rdoc
517
+ result = ''
518
+ parts = description.split("\n") unless description.nil?
519
+ result << "# #{parts.join("\n# ")}\n" unless description.nil?
520
+ result << "def #{name}=(#{type})\n @#{name} = #{type}\nend\n\n"
521
+ return result
522
+ end
523
+
524
+ protected
525
+
526
+ def should_preprocess?
527
+ return preprocessable && !belongs_to.preprocessor.nil?
528
+ end
529
+
530
+ def prepare_preprocessor_paths(paths)
531
+ processed = []
532
+ paths.each do |path|
533
+ processed << prepare_preprocessor_path(path)
534
+ end
535
+ return processed
536
+ end
537
+
538
+ def prepare_preprocessor_files(files)
539
+ processed = []
540
+ files.each do |file|
541
+ processed << prepare_preprocessor_file(file)
542
+ end
543
+ return processed
544
+ end
545
+
546
+ def cleaned_preprocessed_path(path)
547
+ File.join(belongs_to.preprocessed_path, path.gsub('../', 'backslash/'))
548
+ end
549
+
550
+ def prepare_preprocessor_path(path)
551
+ processed_path = cleaned_preprocessed_path(path)
552
+ FileUtils.mkdir_p(processed_path)
553
+ files = FileList[path + file_expression]
554
+ files.each do |input_file|
555
+ prepare_preprocessor_file(input_file)
556
+ end
557
+
558
+ return processed_path
559
+ end
560
+
561
+ def prepare_preprocessor_file(input_file)
562
+ output_file = cleaned_preprocessed_path(input_file)
563
+ setup_preprocessing_file_tasks(input_file, output_file)
564
+ return output_file
565
+ end
566
+
567
+ def text_file?(file_name)
568
+ [/\.as$/, /\.txt$/, /\.mxml$/, /\.xml$/, /\.js$/, /\.html$/, /\.htm$/].select do |regex|
569
+ if (file_name.match(regex))
570
+ return true
571
+ end
572
+ end.size > 0
573
+ end
574
+
575
+ def setup_preprocessing_file_tasks(input_file, output_file)
576
+ return if(File.directory?(input_file))
577
+ CLEAN.add(belongs_to.preprocessed_path) if(!CLEAN.index(belongs_to.preprocessed_path))
578
+
579
+ # Only create the preprocessed action if one does not
580
+ # already exist. There were many being created before...
581
+
582
+ file input_file
583
+ file output_file => input_file do
584
+ # Couldn't return, b/c Rake complained...
585
+ if(!ToolTask::has_preprocessed_task?(output_file))
586
+ dir = File.dirname(output_file)
587
+ if(!File.exists?(dir))
588
+ FileUtils.mkdir_p(dir)
589
+ end
590
+
591
+ content = nil
592
+ # Open the input file and read its content:
593
+ File.open(input_file, 'r') do |readable|
594
+ content = readable.read
595
+ end
596
+
597
+ # Preprocess the content if it's a known text file type:
598
+ if(text_file?(input_file))
599
+ content = preprocess_content(content, belongs_to.preprocessor, input_file)
600
+ end
601
+
602
+ # Write the content to the output file:
603
+ File.open(output_file, 'w+') do |writable|
604
+ writable.write(content)
605
+ end
606
+
607
+ ToolTask::add_preprocessed_task(output_file)
608
+ end
609
+ end
610
+
611
+ belongs_to.prerequisites << output_file
612
+ end
613
+
614
+ def preprocess_content(content, statement, file_name)
615
+ process = ProcessRunner.new(statement)
616
+ process.puts(content)
617
+ process.close_write
618
+ result = process.read
619
+ error = process.read_err
620
+ if(error.size > 0)
621
+ belongs_to.display_preprocess_message
622
+ FileUtils.rm_rf(belongs_to.preprocessed_path)
623
+ raise ExecutionError.new("[ERROR] Preprocessor failed on file #{file_name} #{error}")
624
+ end
625
+ process.kill
626
+ Log.puts ">> Preprocessed and created: #{belongs_to.preprocessed_path}/#{file_name}"
627
+ return result
628
+ end
629
+
630
+ end
631
+
632
+ # Concrete param object for :string values
633
+ class StringParam < TaskParam # :nodoc:
634
+
635
+ def shell_value
636
+ value.gsub(/ /, "\ ")
637
+ end
638
+ end
639
+
640
+ # Concrete param object for :symbol values
641
+ # like class names
642
+ class SymbolParam < TaskParam # :nodoc:
643
+ end
644
+
645
+ # Concrete param object for :url values
646
+ class UrlParam < TaskParam # :nodoc:
647
+ end
648
+
649
+ # Concrete param object for :number values
650
+ class NumberParam < TaskParam # :nodoc:
651
+ end
652
+
653
+ # Concrete param object for :file values
654
+ class FileParam < TaskParam # :nodoc:
655
+
656
+ def prepare_prerequisites
657
+ if(value && value != belongs_to.name.to_s)
658
+ if(should_preprocess?)
659
+ @value = prepare_preprocessor_file(value)
660
+ else
661
+ file value
662
+ belongs_to.prerequisites << value
663
+ end
664
+ end
665
+ end
666
+ end
667
+
668
+ # Concrete param object for :path values
669
+ class PathParam < TaskParam # :nodoc:
670
+
671
+ def prepare_prerequisites
672
+ if(value && value != belongs_to.name.to_s)
673
+ if should_preprocess?
674
+ @value = prepare_preprocessor_path(value)
675
+ else
676
+ file value
677
+ belongs_to.prerequisites << value
678
+ end
679
+ end
680
+ end
681
+ end
682
+
683
+ # Concrete param object for :boolean values
684
+ class BooleanParam < TaskParam # :nodoc:
685
+ attr_writer :show_on_false
686
+
687
+ def visible?
688
+ @visible ||= value
689
+ if(show_on_false)
690
+ return true unless value
691
+ else
692
+ return @visible
693
+ end
694
+ end
695
+
696
+ def show_on_false
697
+ @show_on_false ||= false
698
+ end
699
+
700
+ def value
701
+ @value ||= false
702
+ end
703
+
704
+ end
705
+
706
+ # Concrete param object for collections of strings
707
+ class StringsParam < TaskParam # :nodoc:
708
+
709
+ # Files lists are initialized to an empty array by default
710
+ def value
711
+ @value ||= []
712
+ end
713
+
714
+ # By default, the FilesParams will not appear in the shell
715
+ # output if there are zero items in the collection
716
+ def visible?
717
+ @visible ||= (value && value.size > 0)
718
+ end
719
+
720
+ # Default delimiter is +=
721
+ # This is what will appear between each name/value pair as in:
722
+ # "source_path+=src source_path+=test source_path+=lib"
723
+ def delimiter
724
+ @delimiter ||= "+="
725
+ end
726
+
727
+ # Returns a shell formatted string of the collection
728
+ def to_shell
729
+ return @to_shell_proc.call(self) if(!@to_shell_proc.nil?)
730
+
731
+ result = []
732
+ value.each do |str|
733
+ result << "#{shell_name}#{delimiter}#{str}"
734
+ end
735
+ return result.join(' ')
736
+ end
737
+ end
738
+
739
+ # Concrete param object for collections of symbols (like class names)
740
+ class SymbolsParam < StringsParam # :nodoc:
741
+ end
742
+
743
+ # Concrete param object for collections of files
744
+ class FilesParam < StringsParam # :nodoc:
745
+
746
+ def prepare
747
+ super
748
+ usr = User.new
749
+ path = nil
750
+ value.each_index do |index|
751
+ path = value[index]
752
+ value[index] = usr.clean_path path
753
+ end
754
+ end
755
+
756
+ def prepare_prerequisites
757
+ if should_preprocess?
758
+ @value = prepare_preprocessor_files(value)
759
+ else
760
+ value.each do |f|
761
+ file f
762
+ belongs_to.prerequisites << f
763
+ end
764
+ end
765
+ end
766
+
767
+ end
768
+
769
+ # Concrete param object for collections of paths
770
+ class PathsParam < FilesParam # :nodoc:
771
+
772
+ def prepare_prerequisites
773
+ if should_preprocess?
774
+ @value = prepare_preprocessor_paths(value)
775
+ else
776
+ value.each do |path|
777
+ files = FileList[path + file_expression]
778
+ files.each do |f|
779
+ file f
780
+ belongs_to.prerequisites << f
781
+ end
782
+ end
783
+ end
784
+ end
785
+
786
+
787
+ end
788
+
789
+ # Concrete param object for collections of files
790
+ class UrlsParam < StringsParam # :nodoc:
791
+ end
792
+
793
+ end