jimweirich-rake 0.8.4.99 → 0.8.5

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/CHANGES CHANGED
@@ -1,6 +1,29 @@
1
-
2
1
  = Rake Changelog
3
2
 
3
+ == Pre-Version 0.9.x
4
+
5
+ * Allow single line comments immediately prior to a task to be used in
6
+ place of +desc+.
7
+
8
+ * Split rake.rb into individual files.
9
+
10
+ == Version 0.8.7
11
+
12
+ * Fixed EXEEXT for JRuby on windows.
13
+
14
+ == Version 0.8.6
15
+
16
+ * Minor fixes to the RDoc generation (removed dependency on darkfish
17
+ and removed inline source option).
18
+
19
+ == PreVersion 0.8.6
20
+
21
+ * Now allow # comments to comment a task definition.
22
+
23
+ == Version 0.8.5
24
+
25
+ * Better support for the system command on Windows.
26
+
4
27
  == Version 0.8.4
5
28
 
6
29
  * Preserve case when locating rakefiles (patch from James
data/README CHANGED
@@ -1,6 +1,6 @@
1
1
  = RAKE -- Ruby Make
2
2
 
3
- Supporting Rake version: 0.8.4
3
+ Supporting Rake version: 0.8.6
4
4
 
5
5
  This package contains Rake, a simple ruby build program with
6
6
  capabilities similar to make.
data/Rakefile CHANGED
@@ -135,13 +135,17 @@ rescue LoadError => ex
135
135
  DARKFISH_ENABLED = false
136
136
  end
137
137
 
138
+ BASE_RDOC_OPTIONS = [
139
+ '--line-numbers', '--inline-source',
140
+ '--main' , 'README',
141
+ '--title', 'Rake -- Ruby Make'
142
+ ]
143
+
138
144
  rd = Rake::RDocTask.new("rdoc") do |rdoc|
139
145
  rdoc.rdoc_dir = 'html'
140
146
  rdoc.template = 'doc/jamis.rb'
141
147
  rdoc.title = "Rake -- Ruby Make"
142
- rdoc.options << '--line-numbers' << '--inline-source' <<
143
- '--main' << 'README' <<
144
- '--title' << 'Rake -- Ruby Make'
148
+ rdoc.options = BASE_RDOC_OPTIONS.dup
145
149
  rdoc.options << '-SHN' << '-f' << 'darkfish' if DARKFISH_ENABLED
146
150
 
147
151
  rdoc.rdoc_files.include('README', 'MIT-LICENSE', 'TODO', 'CHANGES')
@@ -209,7 +213,7 @@ else
209
213
 
210
214
  s.has_rdoc = true
211
215
  s.extra_rdoc_files = rd.rdoc_files.reject { |fn| fn =~ /\.rb$/ }.to_a
212
- s.rdoc_options = rd.options
216
+ s.rdoc_options = BASE_RDOC_OPTIONS
213
217
 
214
218
  #### Author and project details.
215
219
 
data/doc/rakefile.rdoc CHANGED
@@ -365,18 +365,32 @@ loading.
365
365
 
366
366
  Standard Ruby comments (beginning with "#") can be used anywhere it is
367
367
  legal in Ruby source code, including comments for tasks and rules.
368
- However, if you wish a task to be described using the "-T" switch,
369
- then you need to use the +desc+ command to describe the task.
368
+ A single-line comment immediately before a task (with no blank line
369
+ between it and the task) will be used as that task's description, and
370
+ the task and description will appear in the list displayed
371
+ using the "-T" switch.
370
372
 
371
373
  === Example:
372
374
 
373
- desc "Create a distribution package"
375
+ # Create a distribution package
374
376
  task :package => [ ... ] do ... end
375
377
 
378
+ You can also use the +desc+ command before a task to set the
379
+ description for the task. In this case, intervening blank lines
380
+ are allowed
381
+
382
+ === Example:
383
+
384
+ desc 'Create a distribution package'
385
+
386
+ task :package => [ ... ] do ... end
387
+
388
+ The +desc+ comment takes priority over the comment for of description.
389
+
376
390
  The "-T" switch (or "--tasks" if you like to spell things out) will
377
- display a list of tasks that have a defined comment. If you use
378
- +desc+ to describe your major tasks, you have a semi-automatic way of
379
- generating a summary of your Rake file.
391
+ display a list of tasks that have a description. If you use
392
+ comments or +desc+ to describe your major tasks, you have a
393
+ semi-automatic way of generating a summary of your Rake file.
380
394
 
381
395
  traken$ rake -T
382
396
  (in /home/.../rake)
@@ -0,0 +1,53 @@
1
+ = Rake 0.8.5 Released
2
+
3
+ Rake version 0.8.5 is a new release of Rake with greatly improved
4
+ support for executing commands on Windows. The "sh" command now has
5
+ the same semantics on Windows that it has on Unix based platforms.
6
+
7
+ == Changes
8
+
9
+ === New Features / Enhancements in Version 0.8.5
10
+
11
+ * Improved implementation of the Rake system command for Windows.
12
+ (patch from James M. Lawrence/quix)
13
+
14
+ * Support for Ruby 1.9's improved system command. (patch from James
15
+ M. Lawrence/quix)
16
+
17
+ * Rake now includes the configured extension when invoking an
18
+ executable (Config::CONFIG['EXEEXT])
19
+
20
+ === Bug Fixes in Version 0.8.5
21
+
22
+ * Environment variable keys are now correctly cased (it matters in
23
+ some implementations).
24
+
25
+ == What is Rake
26
+
27
+ Rake is a build tool similar to the make program in many ways. But
28
+ instead of cryptic make recipes, Rake uses standard Ruby code to
29
+ declare tasks and dependencies. You have the full power of a modern
30
+ scripting language built right into your build tool.
31
+
32
+ == Availability
33
+
34
+ The easiest way to get and install rake is via RubyGems ...
35
+
36
+ gem install rake (you may need root/admin privileges)
37
+
38
+ Otherwise, you can get it from the more traditional places:
39
+
40
+ Home Page:: http://rake.rubyforge.org/
41
+ Download:: http://rubyforge.org/project/showfiles.php?group_id=50
42
+ GitHub:: git://github.com/jimweirich/rake.git
43
+
44
+ == Thanks
45
+
46
+ As usual, it was input from users that drove a alot of these changes. The
47
+ following people either contributed patches, made suggestions or made
48
+ otherwise helpful comments. Thanks to ...
49
+
50
+ * James M. Lawrence/quix
51
+ * Luis Lavena
52
+
53
+ -- Jim Weirich
data/lib/rake.rb CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  #--
4
4
 
5
- # Copyright 2003, 2004, 2005, 2006, 2007, 2008 by Jim Weirich (jim@weirichhouse.org)
5
+ # Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 by Jim Weirich (jim.weirich@gmail.com)
6
6
  #
7
7
  # Permission is hereby granted, free of charge, to any person obtaining a copy
8
8
  # of this software and associated documentation files (the "Software"), to
@@ -22,14 +22,8 @@
22
22
  # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
23
23
  # IN THE SOFTWARE.
24
24
  #++
25
- #
26
- # = Rake -- Ruby Make
27
- #
28
- # This is the main file for the Rake application. Normally it is referenced
29
- # as a library via a require statement, but it can be distributed
30
- # independently as an application.
31
25
 
32
- RAKEVERSION = '0.8.4.99'
26
+ RAKEVERSION = '0.8.7.1'
33
27
 
34
28
  require 'rbconfig'
35
29
  require 'fileutils'
@@ -38,1156 +32,36 @@ require 'monitor'
38
32
  require 'optparse'
39
33
  require 'ostruct'
40
34
 
41
- require 'rake/win32'
42
-
43
- $trace = false
44
-
45
- ######################################################################
46
- # Rake extensions to Module.
47
- #
48
- class Module
49
- # Check for an existing method in the current class before extending. IF
50
- # the method already exists, then a warning is printed and the extension is
51
- # not added. Otherwise the block is yielded and any definitions in the
52
- # block will take effect.
53
- #
54
- # Usage:
55
- #
56
- # class String
57
- # rake_extension("xyz") do
58
- # def xyz
59
- # ...
60
- # end
61
- # end
62
- # end
63
- #
64
- def rake_extension(method)
65
- if method_defined?(method)
66
- $stderr.puts "WARNING: Possible conflict with Rake extension: #{self}##{method} already exists"
67
- else
68
- yield
69
- end
70
- end
71
- end # module Module
72
-
73
-
74
- ######################################################################
75
- # User defined methods to be added to String.
76
- #
77
- class String
78
- rake_extension("ext") do
79
- # Replace the file extension with +newext+. If there is no extension on
80
- # the string, append the new extension to the end. If the new extension
81
- # is not given, or is the empty string, remove any existing extension.
82
- #
83
- # +ext+ is a user added method for the String class.
84
- def ext(newext='')
85
- return self.dup if ['.', '..'].include? self
86
- if newext != ''
87
- newext = (newext =~ /^\./) ? newext : ("." + newext)
88
- end
89
- self.chomp(File.extname(self)) << newext
90
- end
91
- end
92
-
93
- rake_extension("pathmap") do
94
- # Explode a path into individual components. Used by +pathmap+.
95
- def pathmap_explode
96
- head, tail = File.split(self)
97
- return [self] if head == self
98
- return [tail] if head == '.' || tail == '/'
99
- return [head, tail] if head == '/'
100
- return head.pathmap_explode + [tail]
101
- end
102
- protected :pathmap_explode
103
-
104
- # Extract a partial path from the path. Include +n+ directories from the
105
- # front end (left hand side) if +n+ is positive. Include |+n+|
106
- # directories from the back end (right hand side) if +n+ is negative.
107
- def pathmap_partial(n)
108
- dirs = File.dirname(self).pathmap_explode
109
- partial_dirs =
110
- if n > 0
111
- dirs[0...n]
112
- elsif n < 0
113
- dirs.reverse[0...-n].reverse
114
- else
115
- "."
116
- end
117
- File.join(partial_dirs)
118
- end
119
- protected :pathmap_partial
120
-
121
- # Preform the pathmap replacement operations on the given path. The
122
- # patterns take the form 'pat1,rep1;pat2,rep2...'.
123
- def pathmap_replace(patterns, &block)
124
- result = self
125
- patterns.split(';').each do |pair|
126
- pattern, replacement = pair.split(',')
127
- pattern = Regexp.new(pattern)
128
- if replacement == '*' && block_given?
129
- result = result.sub(pattern, &block)
130
- elsif replacement
131
- result = result.sub(pattern, replacement)
132
- else
133
- result = result.sub(pattern, '')
134
- end
135
- end
136
- result
137
- end
138
- protected :pathmap_replace
139
-
140
- # Map the path according to the given specification. The specification
141
- # controls the details of the mapping. The following special patterns are
142
- # recognized:
143
- #
144
- # * <b>%p</b> -- The complete path.
145
- # * <b>%f</b> -- The base file name of the path, with its file extension,
146
- # but without any directories.
147
- # * <b>%n</b> -- The file name of the path without its file extension.
148
- # * <b>%d</b> -- The directory list of the path.
149
- # * <b>%x</b> -- The file extension of the path. An empty string if there
150
- # is no extension.
151
- # * <b>%X</b> -- Everything *but* the file extension.
152
- # * <b>%s</b> -- The alternate file separater if defined, otherwise use
153
- # the standard file separator.
154
- # * <b>%%</b> -- A percent sign.
155
- #
156
- # The %d specifier can also have a numeric prefix (e.g. '%2d'). If the
157
- # number is positive, only return (up to) +n+ directories in the path,
158
- # starting from the left hand side. If +n+ is negative, return (up to)
159
- # |+n+| directories from the right hand side of the path.
160
- #
161
- # Examples:
162
- #
163
- # 'a/b/c/d/file.txt'.pathmap("%2d") => 'a/b'
164
- # 'a/b/c/d/file.txt'.pathmap("%-2d") => 'c/d'
165
- #
166
- # Also the %d, %p, %f, %n, %x, and %X operators can take a
167
- # pattern/replacement argument to perform simple string substititions on a
168
- # particular part of the path. The pattern and replacement are speparated
169
- # by a comma and are enclosed by curly braces. The replacement spec comes
170
- # after the % character but before the operator letter. (e.g.
171
- # "%{old,new}d"). Muliple replacement specs should be separated by
172
- # semi-colons (e.g. "%{old,new;src,bin}d").
173
- #
174
- # Regular expressions may be used for the pattern, and back refs may be
175
- # used in the replacement text. Curly braces, commas and semi-colons are
176
- # excluded from both the pattern and replacement text (let's keep parsing
177
- # reasonable).
178
- #
179
- # For example:
180
- #
181
- # "src/org/onestepback/proj/A.java".pathmap("%{^src,bin}X.class")
182
- #
183
- # returns:
184
- #
185
- # "bin/org/onestepback/proj/A.class"
186
- #
187
- # If the replacement text is '*', then a block may be provided to perform
188
- # some arbitrary calculation for the replacement.
189
- #
190
- # For example:
191
- #
192
- # "/path/to/file.TXT".pathmap("%X%{.*,*}x") { |ext|
193
- # ext.downcase
194
- # }
195
- #
196
- # Returns:
197
- #
198
- # "/path/to/file.txt"
199
- #
200
- def pathmap(spec=nil, &block)
201
- return self if spec.nil?
202
- result = ''
203
- spec.scan(/%\{[^}]*\}-?\d*[sdpfnxX%]|%-?\d+d|%.|[^%]+/) do |frag|
204
- case frag
205
- when '%f'
206
- result << File.basename(self)
207
- when '%n'
208
- result << File.basename(self).ext
209
- when '%d'
210
- result << File.dirname(self)
211
- when '%x'
212
- result << File.extname(self)
213
- when '%X'
214
- result << self.ext
215
- when '%p'
216
- result << self
217
- when '%s'
218
- result << (File::ALT_SEPARATOR || File::SEPARATOR)
219
- when '%-'
220
- # do nothing
221
- when '%%'
222
- result << "%"
223
- when /%(-?\d+)d/
224
- result << pathmap_partial($1.to_i)
225
- when /^%\{([^}]*)\}(\d*[dpfnxX])/
226
- patterns, operator = $1, $2
227
- result << pathmap('%' + operator).pathmap_replace(patterns, &block)
228
- when /^%/
229
- fail ArgumentError, "Unknown pathmap specifier #{frag} in '#{spec}'"
230
- else
231
- result << frag
232
- end
233
- end
234
- result
235
- end
236
- end
237
- end # class String
238
-
239
- ##############################################################################
240
- module Rake
241
-
242
- # Errors -----------------------------------------------------------
243
-
244
- # Error indicating an ill-formed task declaration.
245
- class TaskArgumentError < ArgumentError
246
- end
247
-
248
- # Error indicating a recursion overflow error in task selection.
249
- class RuleRecursionOverflowError < StandardError
250
- def initialize(*args)
251
- super
252
- @targets = []
253
- end
254
-
255
- def add_target(target)
256
- @targets << target
257
- end
258
-
259
- def message
260
- super + ": [" + @targets.reverse.join(' => ') + "]"
261
- end
262
- end
263
-
264
- # --------------------------------------------------------------------------
265
- # Rake module singleton methods.
266
- #
267
- class << self
268
- # Current Rake Application
269
- def application
270
- @application ||= Rake::Application.new
271
- end
272
-
273
- # Set the current Rake application object.
274
- def application=(app)
275
- @application = app
276
- end
277
-
278
- # Return the original directory where the Rake application was started.
279
- def original_dir
280
- application.original_dir
281
- end
282
-
283
- end
284
-
285
- # ##########################################################################
286
- # Mixin for creating easily cloned objects.
287
- #
288
- module Cloneable
289
- # Clone an object by making a new object and setting all the instance
290
- # variables to the same values.
291
- def dup
292
- sibling = self.class.new
293
- instance_variables.each do |ivar|
294
- value = self.instance_variable_get(ivar)
295
- new_value = value.clone rescue value
296
- sibling.instance_variable_set(ivar, new_value)
297
- end
298
- sibling.taint if tainted?
299
- sibling
300
- end
301
-
302
- def clone
303
- sibling = dup
304
- sibling.freeze if frozen?
305
- sibling
306
- end
307
- end
308
-
309
- ####################################################################
310
- # Exit status class for times the system just gives us a nil.
311
- class PseudoStatus
312
- attr_reader :exitstatus
313
- def initialize(code=0)
314
- @exitstatus = code
315
- end
316
- def to_i
317
- @exitstatus << 8
318
- end
319
- def >>(n)
320
- to_i >> n
321
- end
322
- def stopped?
323
- false
324
- end
325
- def exited?
326
- true
327
- end
328
- end
329
-
330
- ####################################################################
331
- # TaskAguments manage the arguments passed to a task.
332
- #
333
- class TaskArguments
334
- include Enumerable
335
-
336
- attr_reader :names
337
-
338
- # Create a TaskArgument object with a list of named arguments
339
- # (given by :names) and a set of associated values (given by
340
- # :values). :parent is the parent argument object.
341
- def initialize(names, values, parent=nil)
342
- @names = names
343
- @parent = parent
344
- @hash = {}
345
- names.each_with_index { |name, i|
346
- @hash[name.to_sym] = values[i] unless values[i].nil?
347
- }
348
- end
349
-
350
- # Create a new argument scope using the prerequisite argument
351
- # names.
352
- def new_scope(names)
353
- values = names.collect { |n| self[n] }
354
- self.class.new(names, values, self)
355
- end
356
-
357
- # Find an argument value by name or index.
358
- def [](index)
359
- lookup(index.to_sym)
360
- end
361
-
362
- # Specify a hash of default values for task arguments. Use the
363
- # defaults only if there is no specific value for the given
364
- # argument.
365
- def with_defaults(defaults)
366
- @hash = defaults.merge(@hash)
367
- end
368
-
369
- def each(&block)
370
- @hash.each(&block)
371
- end
372
-
373
- def method_missing(sym, *args, &block)
374
- lookup(sym.to_sym)
375
- end
376
-
377
- def to_hash
378
- @hash
379
- end
380
-
381
- def to_s
382
- @hash.inspect
383
- end
384
-
385
- def inspect
386
- to_s
387
- end
388
-
389
- protected
390
-
391
- def lookup(name)
392
- if @hash.has_key?(name)
393
- @hash[name]
394
- elsif ENV.has_key?(name.to_s)
395
- ENV[name.to_s]
396
- elsif ENV.has_key?(name.to_s.upcase)
397
- ENV[name.to_s.upcase]
398
- elsif @parent
399
- @parent.lookup(name)
400
- end
401
- end
402
- end
403
-
404
- EMPTY_TASK_ARGS = TaskArguments.new([], [])
405
-
406
- ####################################################################
407
- # InvocationChain tracks the chain of task invocations to detect
408
- # circular dependencies.
409
- class InvocationChain
410
- def initialize(value, tail)
411
- @value = value
412
- @tail = tail
413
- end
414
-
415
- def member?(obj)
416
- @value == obj || @tail.member?(obj)
417
- end
418
-
419
- def append(value)
420
- if member?(value)
421
- fail RuntimeError, "Circular dependency detected: #{to_s} => #{value}"
422
- end
423
- self.class.new(value, self)
424
- end
425
-
426
- def to_s
427
- "#{prefix}#{@value}"
428
- end
429
-
430
- def self.append(value, chain)
431
- chain.append(value)
432
- end
433
-
434
- private
435
-
436
- def prefix
437
- "#{@tail.to_s} => "
438
- end
439
-
440
- class EmptyInvocationChain
441
- def member?(obj)
442
- false
443
- end
444
- def append(value)
445
- InvocationChain.new(value, self)
446
- end
447
- def to_s
448
- "TOP"
449
- end
450
- end
451
-
452
- EMPTY = EmptyInvocationChain.new
453
-
454
- end # class InvocationChain
455
-
456
- end # module Rake
457
-
458
- module Rake
459
-
460
- # #########################################################################
461
- # A Task is the basic unit of work in a Rakefile. Tasks have associated
462
- # actions (possibly more than one) and a list of prerequisites. When
463
- # invoked, a task will first ensure that all of its prerequisites have an
464
- # opportunity to run and then it will execute its own actions.
465
- #
466
- # Tasks are not usually created directly using the new method, but rather
467
- # use the +file+ and +task+ convenience methods.
468
- #
469
- class Task
470
- # List of prerequisites for a task.
471
- attr_reader :prerequisites
472
-
473
- # List of actions attached to a task.
474
- attr_reader :actions
475
-
476
- # Application owning this task.
477
- attr_accessor :application
478
-
479
- # Comment for this task. Restricted to a single line of no more than 50
480
- # characters.
481
- attr_reader :comment
482
-
483
- # Full text of the (possibly multi-line) comment.
484
- attr_reader :full_comment
485
-
486
- # Array of nested namespaces names used for task lookup by this task.
487
- attr_reader :scope
488
-
489
- # Return task name
490
- def to_s
491
- name
492
- end
493
-
494
- def inspect
495
- "<#{self.class} #{name} => [#{prerequisites.join(', ')}]>"
496
- end
497
-
498
- # List of sources for task.
499
- attr_writer :sources
500
- def sources
501
- @sources ||= []
502
- end
503
-
504
- # First source from a rule (nil if no sources)
505
- def source
506
- @sources.first if defined?(@sources)
507
- end
508
-
509
- # Create a task named +task_name+ with no actions or prerequisites. Use
510
- # +enhance+ to add actions and prerequisites.
511
- def initialize(task_name, app)
512
- @name = task_name.to_s
513
- @prerequisites = []
514
- @actions = []
515
- @already_invoked = false
516
- @full_comment = nil
517
- @comment = nil
518
- @lock = Monitor.new
519
- @application = app
520
- @scope = app.current_scope
521
- @arg_names = nil
522
- end
523
-
524
- # Enhance a task with prerequisites or actions. Returns self.
525
- def enhance(deps=nil, &block)
526
- @prerequisites |= deps if deps
527
- @actions << block if block_given?
528
- self
529
- end
530
-
531
- # Name of the task, including any namespace qualifiers.
532
- def name
533
- @name.to_s
534
- end
535
-
536
- # Name of task with argument list description.
537
- def name_with_args # :nodoc:
538
- if arg_description
539
- "#{name}#{arg_description}"
540
- else
541
- name
542
- end
543
- end
544
-
545
- # Argument description (nil if none).
546
- def arg_description # :nodoc:
547
- @arg_names ? "[#{(arg_names || []).join(',')}]" : nil
548
- end
549
-
550
- # Name of arguments for this task.
551
- def arg_names
552
- @arg_names || []
553
- end
554
-
555
- # Reenable the task, allowing its tasks to be executed if the task
556
- # is invoked again.
557
- def reenable
558
- @already_invoked = false
559
- end
560
-
561
- # Clear the existing prerequisites and actions of a rake task.
562
- def clear
563
- clear_prerequisites
564
- clear_actions
565
- self
566
- end
567
-
568
- # Clear the existing prerequisites of a rake task.
569
- def clear_prerequisites
570
- prerequisites.clear
571
- self
572
- end
573
-
574
- # Clear the existing actions on a rake task.
575
- def clear_actions
576
- actions.clear
577
- self
578
- end
579
-
580
- # Invoke the task if it is needed. Prerequites are invoked first.
581
- def invoke(*args)
582
- task_args = TaskArguments.new(arg_names, args)
583
- invoke_with_call_chain(task_args, InvocationChain::EMPTY)
584
- end
585
-
586
- # Same as invoke, but explicitly pass a call chain to detect
587
- # circular dependencies.
588
- def invoke_with_call_chain(task_args, invocation_chain) # :nodoc:
589
- new_chain = InvocationChain.append(self, invocation_chain)
590
- @lock.synchronize do
591
- if application.options.trace
592
- puts "** Invoke #{name} #{format_trace_flags}"
593
- end
594
- return if @already_invoked
595
- @already_invoked = true
596
- invoke_prerequisites(task_args, new_chain)
597
- execute(task_args) if needed?
598
- end
599
- end
600
- protected :invoke_with_call_chain
601
-
602
- # Invoke all the prerequisites of a task.
603
- def invoke_prerequisites(task_args, invocation_chain) # :nodoc:
604
- @prerequisites.each { |n|
605
- prereq = application[n, @scope]
606
- prereq_args = task_args.new_scope(prereq.arg_names)
607
- prereq.invoke_with_call_chain(prereq_args, invocation_chain)
608
- }
609
- end
610
-
611
- # Format the trace flags for display.
612
- def format_trace_flags
613
- flags = []
614
- flags << "first_time" unless @already_invoked
615
- flags << "not_needed" unless needed?
616
- flags.empty? ? "" : "(" + flags.join(", ") + ")"
617
- end
618
- private :format_trace_flags
619
-
620
- # Execute the actions associated with this task.
621
- def execute(args=nil)
622
- args ||= EMPTY_TASK_ARGS
623
- if application.options.dryrun
624
- puts "** Execute (dry run) #{name}"
625
- return
626
- end
627
- if application.options.trace
628
- puts "** Execute #{name}"
629
- end
630
- application.enhance_with_matching_rule(name) if @actions.empty?
631
- @actions.each do |act|
632
- case act.arity
633
- when 1
634
- act.call(self)
635
- else
636
- act.call(self, args)
637
- end
638
- end
639
- end
640
-
641
- # Is this task needed?
642
- def needed?
643
- true
644
- end
645
-
646
- # Timestamp for this task. Basic tasks return the current time for their
647
- # time stamp. Other tasks can be more sophisticated.
648
- def timestamp
649
- @prerequisites.collect { |p| application[p].timestamp }.max || Time.now
650
- end
651
-
652
- # Add a description to the task. The description can consist of an option
653
- # argument list (enclosed brackets) and an optional comment.
654
- def add_description(description)
655
- return if ! description
656
- comment = description.strip
657
- add_comment(comment) if comment && ! comment.empty?
658
- end
659
-
660
- # Writing to the comment attribute is the same as adding a description.
661
- def comment=(description)
662
- add_description(description)
663
- end
664
-
665
- # Add a comment to the task. If a comment alread exists, separate
666
- # the new comment with " / ".
667
- def add_comment(comment)
668
- if @full_comment
669
- @full_comment << " / "
670
- else
671
- @full_comment = ''
672
- end
673
- @full_comment << comment
674
- if @full_comment =~ /\A([^.]+?\.)( |$)/
675
- @comment = $1
676
- else
677
- @comment = @full_comment
678
- end
679
- end
680
- private :add_comment
681
-
682
- # Set the names of the arguments for this task. +args+ should be
683
- # an array of symbols, one for each argument name.
684
- def set_arg_names(args)
685
- @arg_names = args.map { |a| a.to_sym }
686
- end
687
-
688
- # Return a string describing the internal state of a task. Useful for
689
- # debugging.
690
- def investigation
691
- result = "------------------------------\n"
692
- result << "Investigating #{name}\n"
693
- result << "class: #{self.class}\n"
694
- result << "task needed: #{needed?}\n"
695
- result << "timestamp: #{timestamp}\n"
696
- result << "pre-requisites: \n"
697
- prereqs = @prerequisites.collect {|name| application[name]}
698
- prereqs.sort! {|a,b| a.timestamp <=> b.timestamp}
699
- prereqs.each do |p|
700
- result << "--#{p.name} (#{p.timestamp})\n"
701
- end
702
- latest_prereq = @prerequisites.collect{|n| application[n].timestamp}.max
703
- result << "latest-prerequisite time: #{latest_prereq}\n"
704
- result << "................................\n\n"
705
- return result
706
- end
707
-
708
- # ----------------------------------------------------------------
709
- # Rake Module Methods
710
- #
711
- class << self
712
-
713
- # Clear the task list. This cause rake to immediately forget all the
714
- # tasks that have been assigned. (Normally used in the unit tests.)
715
- def clear
716
- Rake.application.clear
717
- end
718
-
719
- # List of all defined tasks.
720
- def tasks
721
- Rake.application.tasks
722
- end
723
-
724
- # Return a task with the given name. If the task is not currently
725
- # known, try to synthesize one from the defined rules. If no rules are
726
- # found, but an existing file matches the task name, assume it is a file
727
- # task with no dependencies or actions.
728
- def [](task_name)
729
- Rake.application[task_name]
730
- end
731
-
732
- # TRUE if the task name is already defined.
733
- def task_defined?(task_name)
734
- Rake.application.lookup(task_name) != nil
735
- end
736
-
737
- # Define a task given +args+ and an option block. If a rule with the
738
- # given name already exists, the prerequisites and actions are added to
739
- # the existing task. Returns the defined task.
740
- def define_task(*args, &block)
741
- Rake.application.define_task(self, *args, &block)
742
- end
743
-
744
- # Define a rule for synthesizing tasks.
745
- def create_rule(*args, &block)
746
- Rake.application.create_rule(*args, &block)
747
- end
748
-
749
- # Apply the scope to the task name according to the rules for
750
- # this kind of task. Generic tasks will accept the scope as
751
- # part of the name.
752
- def scope_name(scope, task_name)
753
- (scope + [task_name]).join(':')
754
- end
755
-
756
- end # class << Rake::Task
757
- end # class Rake::Task
758
-
759
-
760
- # #########################################################################
761
- # A FileTask is a task that includes time based dependencies. If any of a
762
- # FileTask's prerequisites have a timestamp that is later than the file
763
- # represented by this task, then the file must be rebuilt (using the
764
- # supplied actions).
765
- #
766
- class FileTask < Task
767
-
768
- # Is this file task needed? Yes if it doesn't exist, or if its time stamp
769
- # is out of date.
770
- def needed?
771
- ! File.exist?(name) || out_of_date?(timestamp)
772
- end
773
-
774
- # Time stamp for file task.
775
- def timestamp
776
- if File.exist?(name)
777
- File.mtime(name.to_s)
778
- else
779
- Rake::EARLY
780
- end
781
- end
782
-
783
- private
784
-
785
- # Are there any prerequisites with a later time than the given time stamp?
786
- def out_of_date?(stamp)
787
- @prerequisites.any? { |n| application[n].timestamp > stamp}
788
- end
789
-
790
- # ----------------------------------------------------------------
791
- # Task class methods.
792
- #
793
- class << self
794
- # Apply the scope to the task name according to the rules for this kind
795
- # of task. File based tasks ignore the scope when creating the name.
796
- def scope_name(scope, task_name)
797
- task_name
798
- end
799
- end
800
- end # class Rake::FileTask
801
-
802
- # #########################################################################
803
- # A FileCreationTask is a file task that when used as a dependency will be
804
- # needed if and only if the file has not been created. Once created, it is
805
- # not re-triggered if any of its dependencies are newer, nor does trigger
806
- # any rebuilds of tasks that depend on it whenever it is updated.
807
- #
808
- class FileCreationTask < FileTask
809
- # Is this file task needed? Yes if it doesn't exist.
810
- def needed?
811
- ! File.exist?(name)
812
- end
813
-
814
- # Time stamp for file creation task. This time stamp is earlier
815
- # than any other time stamp.
816
- def timestamp
817
- Rake::EARLY
818
- end
819
- end
820
-
821
- # #########################################################################
822
- # Same as a regular task, but the immediate prerequisites are done in
823
- # parallel using Ruby threads.
824
- #
825
- class MultiTask < Task
826
- private
827
- def invoke_prerequisites(args, invocation_chain)
828
- threads = @prerequisites.collect { |p|
829
- Thread.new(p) { |r| application[r].invoke_with_call_chain(args, invocation_chain) }
830
- }
831
- threads.each { |t| t.join }
832
- end
833
- end
834
- end # module Rake
835
-
836
- # ###########################################################################
837
- # Task Definition Functions ...
838
-
839
- # Declare a basic task.
840
- #
841
- # Example:
842
- # task :clobber => [:clean] do
843
- # rm_rf "html"
844
- # end
845
- #
846
- def task(*args, &block)
847
- Rake::Task.define_task(*args, &block)
848
- end
849
-
850
-
851
- # Declare a file task.
852
- #
853
- # Example:
854
- # file "config.cfg" => ["config.template"] do
855
- # open("config.cfg", "w") do |outfile|
856
- # open("config.template") do |infile|
857
- # while line = infile.gets
858
- # outfile.puts line
859
- # end
860
- # end
861
- # end
862
- # end
863
- #
864
- def file(*args, &block)
865
- Rake::FileTask.define_task(*args, &block)
866
- end
867
-
868
- # Declare a file creation task.
869
- # (Mainly used for the directory command).
870
- def file_create(args, &block)
871
- Rake::FileCreationTask.define_task(args, &block)
872
- end
873
-
874
- # Declare a set of files tasks to create the given directories on demand.
875
- #
876
- # Example:
877
- # directory "testdata/doc"
878
- #
879
- def directory(dir)
880
- Rake.each_dir_parent(dir) do |d|
881
- file_create d do |t|
882
- mkdir_p t.name if ! File.exist?(t.name)
883
- end
884
- end
885
- end
886
-
887
- # Declare a task that performs its prerequisites in parallel. Multitasks does
888
- # *not* guarantee that its prerequisites will execute in any given order
889
- # (which is obvious when you think about it)
890
- #
891
- # Example:
892
- # multitask :deploy => [:deploy_gem, :deploy_rdoc]
893
- #
894
- def multitask(args, &block)
895
- Rake::MultiTask.define_task(args, &block)
896
- end
897
-
898
- # Create a new rake namespace and use it for evaluating the given block.
899
- # Returns a NameSpace object that can be used to lookup tasks defined in the
900
- # namespace.
901
- #
902
- # E.g.
903
- #
904
- # ns = namespace "nested" do
905
- # task :run
906
- # end
907
- # task_run = ns[:run] # find :run in the given namespace.
908
- #
909
- def namespace(name=nil, &block)
910
- Rake.application.in_namespace(name, &block)
911
- end
912
-
913
- # Declare a rule for auto-tasks.
914
- #
915
- # Example:
916
- # rule '.o' => '.c' do |t|
917
- # sh %{cc -o #{t.name} #{t.source}}
918
- # end
919
- #
920
- def rule(*args, &block)
921
- Rake::Task.create_rule(*args, &block)
922
- end
923
-
924
- # Describe the next rake task.
925
- #
926
- # Example:
927
- # desc "Run the Unit Tests"
928
- # task :test => [:build]
929
- # runtests
930
- # end
931
- #
932
- def desc(description)
933
- Rake.application.last_description = description
934
- end
935
-
936
- # Import the partial Rakefiles +fn+. Imported files are loaded _after_ the
937
- # current file is completely loaded. This allows the import statement to
938
- # appear anywhere in the importing file, and yet allowing the imported files
939
- # to depend on objects defined in the importing file.
940
- #
941
- # A common use of the import statement is to include files containing
942
- # dependency declarations.
943
- #
944
- # See also the --rakelibdir command line option.
945
- #
946
- # Example:
947
- # import ".depend", "my_rules"
948
- #
949
- def import(*fns)
950
- fns.each do |fn|
951
- Rake.application.add_import(fn)
952
- end
953
- end
954
-
955
- # ###########################################################################
956
- # This a FileUtils extension that defines several additional commands to be
957
- # added to the FileUtils utility functions.
958
- #
959
- module FileUtils
960
- RUBY = File.join(
961
- Config::CONFIG['bindir'],
962
- Config::CONFIG['ruby_install_name'] + Config::CONFIG['EXEEXT']).
963
- sub(/.*\s.*/m, '"\&"')
964
-
965
- OPT_TABLE['sh'] = %w(noop verbose)
966
- OPT_TABLE['ruby'] = %w(noop verbose)
967
-
968
- # Run the system command +cmd+. If multiple arguments are given the command
969
- # is not run with the shell (same semantics as Kernel::exec and
970
- # Kernel::system).
971
- #
972
- # Example:
973
- # sh %{ls -ltr}
974
- #
975
- # sh 'ls', 'file with spaces'
976
- #
977
- # # check exit status after command runs
978
- # sh %{grep pattern file} do |ok, res|
979
- # if ! ok
980
- # puts "pattern not found (status = #{res.exitstatus})"
981
- # end
982
- # end
983
- #
984
- def sh(*cmd, &block)
985
- options = (Hash === cmd.last) ? cmd.pop : {}
986
- unless block_given?
987
- show_command = cmd.join(" ")
988
- show_command = show_command[0,42] + "..." unless $trace
989
- # TODO code application logic heref show_command.length > 45
990
- block = lambda { |ok, status|
991
- ok or fail "Command failed with status (#{status.exitstatus}): [#{show_command}]"
992
- }
993
- end
994
- if RakeFileUtils.verbose_flag == :default
995
- options[:verbose] = true
996
- else
997
- options[:verbose] ||= RakeFileUtils.verbose_flag
998
- end
999
- options[:noop] ||= RakeFileUtils.nowrite_flag
1000
- rake_check_options options, :noop, :verbose
1001
- rake_output_message cmd.join(" ") if options[:verbose]
1002
- unless options[:noop]
1003
- res = rake_system(*cmd)
1004
- status = $?
1005
- status = PseudoStatus.new(1) if !res && status.nil?
1006
- block.call(res, status)
1007
- end
1008
- end
1009
-
1010
- def rake_system(*cmd)
1011
- Rake::AltSystem.system(*cmd)
1012
- end
1013
- private :rake_system
1014
-
1015
- # Run a Ruby interpreter with the given arguments.
1016
- #
1017
- # Example:
1018
- # ruby %{-pe '$_.upcase!' <README}
1019
- #
1020
- def ruby(*args,&block)
1021
- options = (Hash === args.last) ? args.pop : {}
1022
- if args.length > 1 then
1023
- sh(*([RUBY] + args + [options]), &block)
1024
- else
1025
- sh("#{RUBY} #{args.first}", options, &block)
1026
- end
1027
- end
1028
-
1029
- LN_SUPPORTED = [true]
1030
-
1031
- # Attempt to do a normal file link, but fall back to a copy if the link
1032
- # fails.
1033
- def safe_ln(*args)
1034
- unless LN_SUPPORTED[0]
1035
- cp(*args)
1036
- else
1037
- begin
1038
- ln(*args)
1039
- rescue StandardError, NotImplementedError => ex
1040
- LN_SUPPORTED[0] = false
1041
- cp(*args)
1042
- end
1043
- end
1044
- end
1045
-
1046
- # Split a file path into individual directory names.
1047
- #
1048
- # Example:
1049
- # split_all("a/b/c") => ['a', 'b', 'c']
1050
- #
1051
- def split_all(path)
1052
- head, tail = File.split(path)
1053
- return [tail] if head == '.' || tail == '/'
1054
- return [head, tail] if head == '/'
1055
- return split_all(head) + [tail]
1056
- end
1057
- end
1058
-
1059
- # ###########################################################################
1060
- # RakeFileUtils provides a custom version of the FileUtils methods that
1061
- # respond to the <tt>verbose</tt> and <tt>nowrite</tt> commands.
1062
- #
1063
- module RakeFileUtils
1064
- include FileUtils
35
+ require 'rake/ext/module'
36
+ require 'rake/ext/string'
37
+ require 'rake/ext/time'
1065
38
 
1066
- class << self
1067
- attr_accessor :verbose_flag, :nowrite_flag
1068
- end
1069
- RakeFileUtils.verbose_flag = :default
1070
- RakeFileUtils.nowrite_flag = false
1071
-
1072
- $fileutils_verbose = true
1073
- $fileutils_nowrite = false
1074
-
1075
- FileUtils::OPT_TABLE.each do |name, opts|
1076
- default_options = []
1077
- if opts.include?(:verbose) || opts.include?("verbose")
1078
- default_options << ':verbose => RakeFileUtils.verbose_flag'
1079
- end
1080
- if opts.include?(:noop) || opts.include?("noop")
1081
- default_options << ':noop => RakeFileUtils.nowrite_flag'
1082
- end
1083
-
1084
- next if default_options.empty?
1085
- module_eval(<<-EOS, __FILE__, __LINE__ + 1)
1086
- def #{name}( *args, &block )
1087
- super(
1088
- *rake_merge_option(args,
1089
- #{default_options.join(', ')}
1090
- ), &block)
1091
- end
1092
- EOS
1093
- end
1094
-
1095
- # Get/set the verbose flag controlling output from the FileUtils utilities.
1096
- # If verbose is true, then the utility method is echoed to standard output.
1097
- #
1098
- # Examples:
1099
- # verbose # return the current value of the verbose flag
1100
- # verbose(v) # set the verbose flag to _v_.
1101
- # verbose(v) { code } # Execute code with the verbose flag set temporarily to _v_.
1102
- # # Return to the original value when code is done.
1103
- def verbose(value=nil)
1104
- oldvalue = RakeFileUtils.verbose_flag
1105
- RakeFileUtils.verbose_flag = value unless value.nil?
1106
- if block_given?
1107
- begin
1108
- yield
1109
- ensure
1110
- RakeFileUtils.verbose_flag = oldvalue
1111
- end
1112
- end
1113
- RakeFileUtils.verbose_flag
1114
- end
1115
-
1116
- # Get/set the nowrite flag controlling output from the FileUtils utilities.
1117
- # If verbose is true, then the utility method is echoed to standard output.
1118
- #
1119
- # Examples:
1120
- # nowrite # return the current value of the nowrite flag
1121
- # nowrite(v) # set the nowrite flag to _v_.
1122
- # nowrite(v) { code } # Execute code with the nowrite flag set temporarily to _v_.
1123
- # # Return to the original value when code is done.
1124
- def nowrite(value=nil)
1125
- oldvalue = RakeFileUtils.nowrite_flag
1126
- RakeFileUtils.nowrite_flag = value unless value.nil?
1127
- if block_given?
1128
- begin
1129
- yield
1130
- ensure
1131
- RakeFileUtils.nowrite_flag = oldvalue
1132
- end
1133
- end
1134
- oldvalue
1135
- end
1136
-
1137
- # Use this function to prevent protentially destructive ruby code from
1138
- # running when the :nowrite flag is set.
1139
- #
1140
- # Example:
1141
- #
1142
- # when_writing("Building Project") do
1143
- # project.build
1144
- # end
1145
- #
1146
- # The following code will build the project under normal conditions. If the
1147
- # nowrite(true) flag is set, then the example will print:
1148
- # DRYRUN: Building Project
1149
- # instead of actually building the project.
1150
- #
1151
- def when_writing(msg=nil)
1152
- if RakeFileUtils.nowrite_flag
1153
- puts "DRYRUN: #{msg}" if msg
1154
- else
1155
- yield
1156
- end
1157
- end
1158
-
1159
- # Merge the given options with the default values.
1160
- def rake_merge_option(args, defaults)
1161
- if Hash === args.last
1162
- defaults.update(args.last)
1163
- args.pop
1164
- end
1165
- args.push defaults
1166
- args
1167
- end
1168
- private :rake_merge_option
39
+ require 'rake/win32'
1169
40
 
1170
- # Send the message to the default rake output (which is $stderr).
1171
- def rake_output_message(message)
1172
- $stderr.puts(message)
1173
- end
1174
- private :rake_output_message
41
+ require 'rake/task_argument_error'
42
+ require 'rake/rule_recursion_overflow_error'
43
+ require 'rake/rake_module'
44
+ require 'rake/psuedo_status'
45
+ require 'rake/task_arguments'
46
+ require 'rake/invocation_chain'
47
+ require 'rake/task'
48
+ require 'rake/file_task'
49
+ require 'rake/file_creation_task'
50
+ require 'rake/multi_task'
51
+ require 'rake/dsl'
52
+ require 'rake/rake_file_utils'
53
+ require 'rake/file_list'
54
+ require 'rake/default_loader'
55
+ require 'rake/early_time'
56
+ require 'rake/name_space'
57
+ require 'rake/task_manager'
58
+ require 'rake/application'
1175
59
 
1176
- # Check that the options do not contain options not listed in +optdecl+. An
1177
- # ArgumentError exception is thrown if non-declared options are found.
1178
- def rake_check_options(options, *optdecl)
1179
- h = options.dup
1180
- optdecl.each do |name|
1181
- h.delete name
1182
- end
1183
- raise ArgumentError, "no such option: #{h.keys.join(' ')}" unless h.empty?
1184
- end
1185
- private :rake_check_options
60
+ $trace = false
1186
61
 
1187
- extend self
1188
- end
62
+ # Alias FileList to be available at the top level.
63
+ FileList = Rake::FileList
1189
64
 
1190
- # ###########################################################################
1191
65
  # Include the FileUtils file manipulation functions in the top level module,
1192
66
  # but mark them private so that they don't unintentionally define methods on
1193
67
  # other objects.
@@ -1195,1308 +69,3 @@ end
1195
69
  include RakeFileUtils
1196
70
  private(*FileUtils.instance_methods(false))
1197
71
  private(*RakeFileUtils.instance_methods(false))
1198
-
1199
- ######################################################################
1200
- module Rake
1201
-
1202
- # #########################################################################
1203
- # A FileList is essentially an array with a few helper methods defined to
1204
- # make file manipulation a bit easier.
1205
- #
1206
- # FileLists are lazy. When given a list of glob patterns for possible files
1207
- # to be included in the file list, instead of searching the file structures
1208
- # to find the files, a FileList holds the pattern for latter use.
1209
- #
1210
- # This allows us to define a number of FileList to match any number of
1211
- # files, but only search out the actual files when then FileList itself is
1212
- # actually used. The key is that the first time an element of the
1213
- # FileList/Array is requested, the pending patterns are resolved into a real
1214
- # list of file names.
1215
- #
1216
- class FileList
1217
-
1218
- include Cloneable
1219
-
1220
- # == Method Delegation
1221
- #
1222
- # The lazy evaluation magic of FileLists happens by implementing all the
1223
- # array specific methods to call +resolve+ before delegating the heavy
1224
- # lifting to an embedded array object (@items).
1225
- #
1226
- # In addition, there are two kinds of delegation calls. The regular kind
1227
- # delegates to the @items array and returns the result directly. Well,
1228
- # almost directly. It checks if the returned value is the @items object
1229
- # itself, and if so will return the FileList object instead.
1230
- #
1231
- # The second kind of delegation call is used in methods that normally
1232
- # return a new Array object. We want to capture the return value of these
1233
- # methods and wrap them in a new FileList object. We enumerate these
1234
- # methods in the +SPECIAL_RETURN+ list below.
1235
-
1236
- # List of array methods (that are not in +Object+) that need to be
1237
- # delegated.
1238
- ARRAY_METHODS = (Array.instance_methods - Object.instance_methods).map { |n| n.to_s }
1239
-
1240
- # List of additional methods that must be delegated.
1241
- MUST_DEFINE = %w[to_a inspect]
1242
-
1243
- # List of methods that should not be delegated here (we define special
1244
- # versions of them explicitly below).
1245
- MUST_NOT_DEFINE = %w[to_a to_ary partition *]
1246
-
1247
- # List of delegated methods that return new array values which need
1248
- # wrapping.
1249
- SPECIAL_RETURN = %w[
1250
- map collect sort sort_by select find_all reject grep
1251
- compact flatten uniq values_at
1252
- + - & |
1253
- ]
1254
-
1255
- DELEGATING_METHODS = (ARRAY_METHODS + MUST_DEFINE - MUST_NOT_DEFINE).collect{ |s| s.to_s }.sort.uniq
1256
-
1257
- # Now do the delegation.
1258
- DELEGATING_METHODS.each_with_index do |sym, i|
1259
- if SPECIAL_RETURN.include?(sym)
1260
- ln = __LINE__+1
1261
- class_eval %{
1262
- def #{sym}(*args, &block)
1263
- resolve
1264
- result = @items.send(:#{sym}, *args, &block)
1265
- FileList.new.import(result)
1266
- end
1267
- }, __FILE__, ln
1268
- else
1269
- ln = __LINE__+1
1270
- class_eval %{
1271
- def #{sym}(*args, &block)
1272
- resolve
1273
- result = @items.send(:#{sym}, *args, &block)
1274
- result.object_id == @items.object_id ? self : result
1275
- end
1276
- }, __FILE__, ln
1277
- end
1278
- end
1279
-
1280
- # Create a file list from the globbable patterns given. If you wish to
1281
- # perform multiple includes or excludes at object build time, use the
1282
- # "yield self" pattern.
1283
- #
1284
- # Example:
1285
- # file_list = FileList.new('lib/**/*.rb', 'test/test*.rb')
1286
- #
1287
- # pkg_files = FileList.new('lib/**/*') do |fl|
1288
- # fl.exclude(/\bCVS\b/)
1289
- # end
1290
- #
1291
- def initialize(*patterns)
1292
- @pending_add = []
1293
- @pending = false
1294
- @exclude_patterns = DEFAULT_IGNORE_PATTERNS.dup
1295
- @exclude_procs = DEFAULT_IGNORE_PROCS.dup
1296
- @exclude_re = nil
1297
- @items = []
1298
- patterns.each { |pattern| include(pattern) }
1299
- yield self if block_given?
1300
- end
1301
-
1302
- # Add file names defined by glob patterns to the file list. If an array
1303
- # is given, add each element of the array.
1304
- #
1305
- # Example:
1306
- # file_list.include("*.java", "*.cfg")
1307
- # file_list.include %w( math.c lib.h *.o )
1308
- #
1309
- def include(*filenames)
1310
- # TODO: check for pending
1311
- filenames.each do |fn|
1312
- if fn.respond_to? :to_ary
1313
- include(*fn.to_ary)
1314
- else
1315
- @pending_add << fn
1316
- end
1317
- end
1318
- @pending = true
1319
- self
1320
- end
1321
- alias :add :include
1322
-
1323
- # Register a list of file name patterns that should be excluded from the
1324
- # list. Patterns may be regular expressions, glob patterns or regular
1325
- # strings. In addition, a block given to exclude will remove entries that
1326
- # return true when given to the block.
1327
- #
1328
- # Note that glob patterns are expanded against the file system. If a file
1329
- # is explicitly added to a file list, but does not exist in the file
1330
- # system, then an glob pattern in the exclude list will not exclude the
1331
- # file.
1332
- #
1333
- # Examples:
1334
- # FileList['a.c', 'b.c'].exclude("a.c") => ['b.c']
1335
- # FileList['a.c', 'b.c'].exclude(/^a/) => ['b.c']
1336
- #
1337
- # If "a.c" is a file, then ...
1338
- # FileList['a.c', 'b.c'].exclude("a.*") => ['b.c']
1339
- #
1340
- # If "a.c" is not a file, then ...
1341
- # FileList['a.c', 'b.c'].exclude("a.*") => ['a.c', 'b.c']
1342
- #
1343
- def exclude(*patterns, &block)
1344
- patterns.each do |pat|
1345
- @exclude_patterns << pat
1346
- end
1347
- if block_given?
1348
- @exclude_procs << block
1349
- end
1350
- resolve_exclude if ! @pending
1351
- self
1352
- end
1353
-
1354
-
1355
- # Clear all the exclude patterns so that we exclude nothing.
1356
- def clear_exclude
1357
- @exclude_patterns = []
1358
- @exclude_procs = []
1359
- calculate_exclude_regexp if ! @pending
1360
- self
1361
- end
1362
-
1363
- # Define equality.
1364
- def ==(array)
1365
- to_ary == array
1366
- end
1367
-
1368
- # Return the internal array object.
1369
- def to_a
1370
- resolve
1371
- @items
1372
- end
1373
-
1374
- # Return the internal array object.
1375
- def to_ary
1376
- to_a
1377
- end
1378
-
1379
- # Lie about our class.
1380
- def is_a?(klass)
1381
- klass == Array || super(klass)
1382
- end
1383
- alias kind_of? is_a?
1384
-
1385
- # Redefine * to return either a string or a new file list.
1386
- def *(other)
1387
- result = @items * other
1388
- case result
1389
- when Array
1390
- FileList.new.import(result)
1391
- else
1392
- result
1393
- end
1394
- end
1395
-
1396
- # Resolve all the pending adds now.
1397
- def resolve
1398
- if @pending
1399
- @pending = false
1400
- @pending_add.each do |fn| resolve_add(fn) end
1401
- @pending_add = []
1402
- resolve_exclude
1403
- end
1404
- self
1405
- end
1406
-
1407
- def calculate_exclude_regexp
1408
- ignores = []
1409
- @exclude_patterns.each do |pat|
1410
- case pat
1411
- when Regexp
1412
- ignores << pat
1413
- when /[*?]/
1414
- Dir[pat].each do |p| ignores << p end
1415
- else
1416
- ignores << Regexp.quote(pat)
1417
- end
1418
- end
1419
- if ignores.empty?
1420
- @exclude_re = /^$/
1421
- else
1422
- re_str = ignores.collect { |p| "(" + p.to_s + ")" }.join("|")
1423
- @exclude_re = Regexp.new(re_str)
1424
- end
1425
- end
1426
-
1427
- def resolve_add(fn)
1428
- case fn
1429
- when %r{[*?\[\{]}
1430
- add_matching(fn)
1431
- else
1432
- self << fn
1433
- end
1434
- end
1435
- private :resolve_add
1436
-
1437
- def resolve_exclude
1438
- calculate_exclude_regexp
1439
- reject! { |fn| exclude?(fn) }
1440
- self
1441
- end
1442
- private :resolve_exclude
1443
-
1444
- # Return a new FileList with the results of running +sub+ against each
1445
- # element of the oringal list.
1446
- #
1447
- # Example:
1448
- # FileList['a.c', 'b.c'].sub(/\.c$/, '.o') => ['a.o', 'b.o']
1449
- #
1450
- def sub(pat, rep)
1451
- inject(FileList.new) { |res, fn| res << fn.sub(pat,rep) }
1452
- end
1453
-
1454
- # Return a new FileList with the results of running +gsub+ against each
1455
- # element of the original list.
1456
- #
1457
- # Example:
1458
- # FileList['lib/test/file', 'x/y'].gsub(/\//, "\\")
1459
- # => ['lib\\test\\file', 'x\\y']
1460
- #
1461
- def gsub(pat, rep)
1462
- inject(FileList.new) { |res, fn| res << fn.gsub(pat,rep) }
1463
- end
1464
-
1465
- # Same as +sub+ except that the oringal file list is modified.
1466
- def sub!(pat, rep)
1467
- each_with_index { |fn, i| self[i] = fn.sub(pat,rep) }
1468
- self
1469
- end
1470
-
1471
- # Same as +gsub+ except that the original file list is modified.
1472
- def gsub!(pat, rep)
1473
- each_with_index { |fn, i| self[i] = fn.gsub(pat,rep) }
1474
- self
1475
- end
1476
-
1477
- # Apply the pathmap spec to each of the included file names, returning a
1478
- # new file list with the modified paths. (See String#pathmap for
1479
- # details.)
1480
- def pathmap(spec=nil)
1481
- collect { |fn| fn.pathmap(spec) }
1482
- end
1483
-
1484
- # Return a new FileList with <tt>String#ext</tt> method applied
1485
- # to each member of the array.
1486
- #
1487
- # This method is a shortcut for:
1488
- #
1489
- # array.collect { |item| item.ext(newext) }
1490
- #
1491
- # +ext+ is a user added method for the Array class.
1492
- def ext(newext='')
1493
- collect { |fn| fn.ext(newext) }
1494
- end
1495
-
1496
-
1497
- # Grep each of the files in the filelist using the given pattern. If a
1498
- # block is given, call the block on each matching line, passing the file
1499
- # name, line number, and the matching line of text. If no block is given,
1500
- # a standard emac style file:linenumber:line message will be printed to
1501
- # standard out.
1502
- def egrep(pattern, *options)
1503
- each do |fn|
1504
- open(fn, "rb", *options) do |inf|
1505
- count = 0
1506
- inf.each do |line|
1507
- count += 1
1508
- if pattern.match(line)
1509
- if block_given?
1510
- yield fn, count, line
1511
- else
1512
- puts "#{fn}:#{count}:#{line}"
1513
- end
1514
- end
1515
- end
1516
- end
1517
- end
1518
- end
1519
-
1520
- # Return a new file list that only contains file names from the current
1521
- # file list that exist on the file system.
1522
- def existing
1523
- select { |fn| File.exist?(fn) }
1524
- end
1525
-
1526
- # Modify the current file list so that it contains only file name that
1527
- # exist on the file system.
1528
- def existing!
1529
- resolve
1530
- @items = @items.select { |fn| File.exist?(fn) }
1531
- self
1532
- end
1533
-
1534
- # FileList version of partition. Needed because the nested arrays should
1535
- # be FileLists in this version.
1536
- def partition(&block) # :nodoc:
1537
- resolve
1538
- result = @items.partition(&block)
1539
- [
1540
- FileList.new.import(result[0]),
1541
- FileList.new.import(result[1]),
1542
- ]
1543
- end
1544
-
1545
- # Convert a FileList to a string by joining all elements with a space.
1546
- def to_s
1547
- resolve
1548
- self.join(' ')
1549
- end
1550
-
1551
- # Add matching glob patterns.
1552
- def add_matching(pattern)
1553
- Dir[pattern].each do |fn|
1554
- self << fn unless exclude?(fn)
1555
- end
1556
- end
1557
- private :add_matching
1558
-
1559
- # Should the given file name be excluded?
1560
- def exclude?(fn)
1561
- calculate_exclude_regexp unless @exclude_re
1562
- fn =~ @exclude_re || @exclude_procs.any? { |p| p.call(fn) }
1563
- end
1564
-
1565
- DEFAULT_IGNORE_PATTERNS = [
1566
- /(^|[\/\\])CVS([\/\\]|$)/,
1567
- /(^|[\/\\])\.svn([\/\\]|$)/,
1568
- /\.bak$/,
1569
- /~$/
1570
- ]
1571
- DEFAULT_IGNORE_PROCS = [
1572
- proc { |fn| fn =~ /(^|[\/\\])core$/ && ! File.directory?(fn) }
1573
- ]
1574
- # @exclude_patterns = DEFAULT_IGNORE_PATTERNS.dup
1575
-
1576
- def import(array)
1577
- @items = array
1578
- self
1579
- end
1580
-
1581
- class << self
1582
- # Create a new file list including the files listed. Similar to:
1583
- #
1584
- # FileList.new(*args)
1585
- def [](*args)
1586
- new(*args)
1587
- end
1588
- end
1589
- end # FileList
1590
- end
1591
-
1592
- module Rake
1593
- class << self
1594
-
1595
- # Yield each file or directory component.
1596
- def each_dir_parent(dir) # :nodoc:
1597
- old_length = nil
1598
- while dir != '.' && dir.length != old_length
1599
- yield(dir)
1600
- old_length = dir.length
1601
- dir = File.dirname(dir)
1602
- end
1603
- end
1604
- end
1605
- end # module Rake
1606
-
1607
- # Alias FileList to be available at the top level.
1608
- FileList = Rake::FileList
1609
-
1610
- # ###########################################################################
1611
- module Rake
1612
-
1613
- # Default Rakefile loader used by +import+.
1614
- class DefaultLoader
1615
- def load(fn)
1616
- Kernel.load(File.expand_path(fn))
1617
- end
1618
- end
1619
-
1620
- # EarlyTime is a fake timestamp that occurs _before_ any other time value.
1621
- class EarlyTime
1622
- include Comparable
1623
- include Singleton
1624
-
1625
- def <=>(other)
1626
- -1
1627
- end
1628
-
1629
- def to_s
1630
- "<EARLY TIME>"
1631
- end
1632
- end
1633
-
1634
- EARLY = EarlyTime.instance
1635
- end # module Rake
1636
-
1637
- # ###########################################################################
1638
- # Extensions to time to allow comparisons with an early time class.
1639
- #
1640
- class Time
1641
- alias rake_original_time_compare :<=>
1642
- def <=>(other)
1643
- if Rake::EarlyTime === other
1644
- - other.<=>(self)
1645
- else
1646
- rake_original_time_compare(other)
1647
- end
1648
- end
1649
- end # class Time
1650
-
1651
- module Rake
1652
-
1653
- ####################################################################
1654
- # The NameSpace class will lookup task names in the the scope
1655
- # defined by a +namespace+ command.
1656
- #
1657
- class NameSpace
1658
-
1659
- # Create a namespace lookup object using the given task manager
1660
- # and the list of scopes.
1661
- def initialize(task_manager, scope_list)
1662
- @task_manager = task_manager
1663
- @scope = scope_list.dup
1664
- end
1665
-
1666
- # Lookup a task named +name+ in the namespace.
1667
- def [](name)
1668
- @task_manager.lookup(name, @scope)
1669
- end
1670
-
1671
- # Return the list of tasks defined in this and nested namespaces.
1672
- def tasks
1673
- @task_manager.tasks_in_scope(@scope)
1674
- end
1675
- end # NameSpace
1676
-
1677
-
1678
- ####################################################################
1679
- # The TaskManager module is a mixin for managing tasks.
1680
- module TaskManager
1681
- # Track the last comment made in the Rakefile.
1682
- attr_accessor :last_description
1683
- alias :last_comment :last_description # Backwards compatibility
1684
-
1685
- def initialize
1686
- super
1687
- @tasks = Hash.new
1688
- @rules = Array.new
1689
- @scope = Array.new
1690
- @last_description = nil
1691
- end
1692
-
1693
- def create_rule(*args, &block)
1694
- pattern, arg_names, deps = resolve_args(args)
1695
- pattern = Regexp.new(Regexp.quote(pattern) + '$') if String === pattern
1696
- @rules << [pattern, deps, block]
1697
- end
1698
-
1699
- def define_task(task_class, *args, &block)
1700
- task_name, arg_names, deps = resolve_args(args)
1701
- task_name = task_class.scope_name(@scope, task_name)
1702
- deps = [deps] unless deps.respond_to?(:to_ary)
1703
- deps = deps.collect {|d| d.to_s }
1704
- task = intern(task_class, task_name)
1705
- task.set_arg_names(arg_names) unless arg_names.empty?
1706
- task.add_description(@last_description)
1707
- @last_description = nil
1708
- task.enhance(deps, &block)
1709
- task
1710
- end
1711
-
1712
- # Lookup a task. Return an existing task if found, otherwise
1713
- # create a task of the current type.
1714
- def intern(task_class, task_name)
1715
- @tasks[task_name.to_s] ||= task_class.new(task_name, self)
1716
- end
1717
-
1718
- # Find a matching task for +task_name+.
1719
- def [](task_name, scopes=nil)
1720
- task_name = task_name.to_s
1721
- self.lookup(task_name, scopes) or
1722
- enhance_with_matching_rule(task_name) or
1723
- synthesize_file_task(task_name) or
1724
- fail "Don't know how to build task '#{task_name}'"
1725
- end
1726
-
1727
- def synthesize_file_task(task_name)
1728
- return nil unless File.exist?(task_name)
1729
- define_task(Rake::FileTask, task_name)
1730
- end
1731
-
1732
- # Resolve the arguments for a task/rule. Returns a triplet of
1733
- # [task_name, arg_name_list, prerequisites].
1734
- def resolve_args(args)
1735
- if args.last.is_a?(Hash)
1736
- deps = args.pop
1737
- resolve_args_with_dependencies(args, deps)
1738
- else
1739
- resolve_args_without_dependencies(args)
1740
- end
1741
- end
1742
-
1743
- # Resolve task arguments for a task or rule when there are no
1744
- # dependencies declared.
1745
- #
1746
- # The patterns recognized by this argument resolving function are:
1747
- #
1748
- # task :t
1749
- # task :t, [:a]
1750
- # task :t, :a (deprecated)
1751
- #
1752
- def resolve_args_without_dependencies(args)
1753
- task_name = args.shift
1754
- if args.size == 1 && args.first.respond_to?(:to_ary)
1755
- arg_names = args.first.to_ary
1756
- else
1757
- arg_names = args
1758
- end
1759
- [task_name, arg_names, []]
1760
- end
1761
- private :resolve_args_without_dependencies
1762
-
1763
- # Resolve task arguments for a task or rule when there are
1764
- # dependencies declared.
1765
- #
1766
- # The patterns recognized by this argument resolving function are:
1767
- #
1768
- # task :t => [:d]
1769
- # task :t, [a] => [:d]
1770
- # task :t, :needs => [:d] (deprecated)
1771
- # task :t, :a, :needs => [:d] (deprecated)
1772
- #
1773
- def resolve_args_with_dependencies(args, hash) # :nodoc:
1774
- fail "Task Argument Error" if hash.size != 1
1775
- key, value = hash.map { |k, v| [k,v] }.first
1776
- if args.empty?
1777
- task_name = key
1778
- arg_names = []
1779
- deps = value
1780
- elsif key == :needs
1781
- task_name = args.shift
1782
- arg_names = args
1783
- deps = value
1784
- else
1785
- task_name = args.shift
1786
- arg_names = key
1787
- deps = value
1788
- end
1789
- deps = [deps] unless deps.respond_to?(:to_ary)
1790
- [task_name, arg_names, deps]
1791
- end
1792
- private :resolve_args_with_dependencies
1793
-
1794
- # If a rule can be found that matches the task name, enhance the
1795
- # task with the prerequisites and actions from the rule. Set the
1796
- # source attribute of the task appropriately for the rule. Return
1797
- # the enhanced task or nil of no rule was found.
1798
- def enhance_with_matching_rule(task_name, level=0)
1799
- fail Rake::RuleRecursionOverflowError,
1800
- "Rule Recursion Too Deep" if level >= 16
1801
- @rules.each do |pattern, extensions, block|
1802
- if md = pattern.match(task_name)
1803
- task = attempt_rule(task_name, extensions, block, level)
1804
- return task if task
1805
- end
1806
- end
1807
- nil
1808
- rescue Rake::RuleRecursionOverflowError => ex
1809
- ex.add_target(task_name)
1810
- fail ex
1811
- end
1812
-
1813
- # List of all defined tasks in this application.
1814
- def tasks
1815
- @tasks.values.sort_by { |t| t.name }
1816
- end
1817
-
1818
- # List of all the tasks defined in the given scope (and its
1819
- # sub-scopes).
1820
- def tasks_in_scope(scope)
1821
- prefix = scope.join(":")
1822
- tasks.select { |t|
1823
- /^#{prefix}:/ =~ t.name
1824
- }
1825
- end
1826
-
1827
- # Clear all tasks in this application.
1828
- def clear
1829
- @tasks.clear
1830
- @rules.clear
1831
- end
1832
-
1833
- # Lookup a task, using scope and the scope hints in the task name.
1834
- # This method performs straight lookups without trying to
1835
- # synthesize file tasks or rules. Special scope names (e.g. '^')
1836
- # are recognized. If no scope argument is supplied, use the
1837
- # current scope. Return nil if the task cannot be found.
1838
- def lookup(task_name, initial_scope=nil)
1839
- initial_scope ||= @scope
1840
- task_name = task_name.to_s
1841
- if task_name =~ /^rake:/
1842
- scopes = []
1843
- task_name = task_name.sub(/^rake:/, '')
1844
- elsif task_name =~ /^(\^+)/
1845
- scopes = initial_scope[0, initial_scope.size - $1.size]
1846
- task_name = task_name.sub(/^(\^+)/, '')
1847
- else
1848
- scopes = initial_scope
1849
- end
1850
- lookup_in_scope(task_name, scopes)
1851
- end
1852
-
1853
- # Lookup the task name
1854
- def lookup_in_scope(name, scope)
1855
- n = scope.size
1856
- while n >= 0
1857
- tn = (scope[0,n] + [name]).join(':')
1858
- task = @tasks[tn]
1859
- return task if task
1860
- n -= 1
1861
- end
1862
- nil
1863
- end
1864
- private :lookup_in_scope
1865
-
1866
- # Return the list of scope names currently active in the task
1867
- # manager.
1868
- def current_scope
1869
- @scope.dup
1870
- end
1871
-
1872
- # Evaluate the block in a nested namespace named +name+. Create
1873
- # an anonymous namespace if +name+ is nil.
1874
- def in_namespace(name)
1875
- name ||= generate_name
1876
- @scope.push(name)
1877
- ns = NameSpace.new(self, @scope)
1878
- yield(ns)
1879
- ns
1880
- ensure
1881
- @scope.pop
1882
- end
1883
-
1884
- private
1885
-
1886
- # Generate an anonymous namespace name.
1887
- def generate_name
1888
- @seed ||= 0
1889
- @seed += 1
1890
- "_anon_#{@seed}"
1891
- end
1892
-
1893
- def trace_rule(level, message)
1894
- puts "#{" "*level}#{message}" if Rake.application.options.trace_rules
1895
- end
1896
-
1897
- # Attempt to create a rule given the list of prerequisites.
1898
- def attempt_rule(task_name, extensions, block, level)
1899
- sources = make_sources(task_name, extensions)
1900
- prereqs = sources.collect { |source|
1901
- trace_rule level, "Attempting Rule #{task_name} => #{source}"
1902
- if File.exist?(source) || Rake::Task.task_defined?(source)
1903
- trace_rule level, "(#{task_name} => #{source} ... EXIST)"
1904
- source
1905
- elsif parent = enhance_with_matching_rule(source, level+1)
1906
- trace_rule level, "(#{task_name} => #{source} ... ENHANCE)"
1907
- parent.name
1908
- else
1909
- trace_rule level, "(#{task_name} => #{source} ... FAIL)"
1910
- return nil
1911
- end
1912
- }
1913
- task = FileTask.define_task({task_name => prereqs}, &block)
1914
- task.sources = prereqs
1915
- task
1916
- end
1917
-
1918
- # Make a list of sources from the list of file name extensions /
1919
- # translation procs.
1920
- def make_sources(task_name, extensions)
1921
- extensions.collect { |ext|
1922
- case ext
1923
- when /%/
1924
- task_name.pathmap(ext)
1925
- when %r{/}
1926
- ext
1927
- when /^\./
1928
- task_name.ext(ext)
1929
- when String
1930
- ext
1931
- when Proc
1932
- if ext.arity == 1
1933
- ext.call(task_name)
1934
- else
1935
- ext.call
1936
- end
1937
- else
1938
- fail "Don't know how to handle rule dependent: #{ext.inspect}"
1939
- end
1940
- }.flatten
1941
- end
1942
-
1943
- end # TaskManager
1944
-
1945
- ######################################################################
1946
- # Rake main application object. When invoking +rake+ from the
1947
- # command line, a Rake::Application object is created and run.
1948
- #
1949
- class Application
1950
- include TaskManager
1951
-
1952
- # The name of the application (typically 'rake')
1953
- attr_reader :name
1954
-
1955
- # The original directory where rake was invoked.
1956
- attr_reader :original_dir
1957
-
1958
- # Name of the actual rakefile used.
1959
- attr_reader :rakefile
1960
-
1961
- # List of the top level task names (task names from the command line).
1962
- attr_reader :top_level_tasks
1963
-
1964
- DEFAULT_RAKEFILES = ['rakefile', 'Rakefile', 'rakefile.rb', 'Rakefile.rb'].freeze
1965
-
1966
- # Initialize a Rake::Application object.
1967
- def initialize
1968
- super
1969
- @name = 'rake'
1970
- @rakefiles = DEFAULT_RAKEFILES.dup
1971
- @rakefile = nil
1972
- @pending_imports = []
1973
- @imported = []
1974
- @loaders = {}
1975
- @default_loader = Rake::DefaultLoader.new
1976
- @original_dir = Dir.pwd
1977
- @top_level_tasks = []
1978
- add_loader('rb', DefaultLoader.new)
1979
- add_loader('rf', DefaultLoader.new)
1980
- add_loader('rake', DefaultLoader.new)
1981
- @tty_output = STDOUT.tty?
1982
- end
1983
-
1984
- # Run the Rake application. The run method performs the following three steps:
1985
- #
1986
- # * Initialize the command line options (+init+).
1987
- # * Define the tasks (+load_rakefile+).
1988
- # * Run the top level tasks (+run_tasks+).
1989
- #
1990
- # If you wish to build a custom rake command, you should call +init+ on your
1991
- # application. The define any tasks. Finally, call +top_level+ to run your top
1992
- # level tasks.
1993
- def run
1994
- standard_exception_handling do
1995
- init
1996
- load_rakefile
1997
- top_level
1998
- end
1999
- end
2000
-
2001
- # Initialize the command line parameters and app name.
2002
- def init(app_name='rake')
2003
- standard_exception_handling do
2004
- @name = app_name
2005
- handle_options
2006
- collect_tasks
2007
- end
2008
- end
2009
-
2010
- # Find the rakefile and then load it and any pending imports.
2011
- def load_rakefile
2012
- standard_exception_handling do
2013
- raw_load_rakefile
2014
- end
2015
- end
2016
-
2017
- # Run the top level tasks of a Rake application.
2018
- def top_level
2019
- standard_exception_handling do
2020
- if options.show_tasks
2021
- display_tasks_and_comments
2022
- elsif options.show_prereqs
2023
- display_prerequisites
2024
- else
2025
- top_level_tasks.each { |task_name| invoke_task(task_name) }
2026
- end
2027
- end
2028
- end
2029
-
2030
- # Add a loader to handle imported files ending in the extension
2031
- # +ext+.
2032
- def add_loader(ext, loader)
2033
- ext = ".#{ext}" unless ext =~ /^\./
2034
- @loaders[ext] = loader
2035
- end
2036
-
2037
- # Application options from the command line
2038
- def options
2039
- @options ||= OpenStruct.new
2040
- end
2041
-
2042
- # private ----------------------------------------------------------------
2043
-
2044
- def invoke_task(task_string)
2045
- name, args = parse_task_string(task_string)
2046
- t = self[name]
2047
- t.invoke(*args)
2048
- end
2049
-
2050
- def parse_task_string(string)
2051
- if string =~ /^([^\[]+)(\[(.*)\])$/
2052
- name = $1
2053
- args = $3.split(/\s*,\s*/)
2054
- else
2055
- name = string
2056
- args = []
2057
- end
2058
- [name, args]
2059
- end
2060
-
2061
- # Provide standard execption handling for the given block.
2062
- def standard_exception_handling
2063
- begin
2064
- yield
2065
- rescue SystemExit => ex
2066
- # Exit silently with current status
2067
- raise
2068
- rescue OptionParser::InvalidOption => ex
2069
- # Exit silently
2070
- exit(false)
2071
- rescue Exception => ex
2072
- # Exit with error message
2073
- $stderr.puts "#{name} aborted!"
2074
- $stderr.puts ex.message
2075
- if options.trace
2076
- $stderr.puts ex.backtrace.join("\n")
2077
- else
2078
- $stderr.puts ex.backtrace.find {|str| str =~ /#{@rakefile}/ } || ""
2079
- $stderr.puts "(See full trace by running task with --trace)"
2080
- end
2081
- exit(false)
2082
- end
2083
- end
2084
-
2085
- # True if one of the files in RAKEFILES is in the current directory.
2086
- # If a match is found, it is copied into @rakefile.
2087
- def have_rakefile
2088
- @rakefiles.each do |fn|
2089
- if File.exist?(fn)
2090
- others = Dir.glob(fn, File::FNM_CASEFOLD)
2091
- return others.size == 1 ? others.first : fn
2092
- elsif fn == ''
2093
- return fn
2094
- end
2095
- end
2096
- return nil
2097
- end
2098
-
2099
- # True if we are outputting to TTY, false otherwise
2100
- def tty_output?
2101
- @tty_output
2102
- end
2103
-
2104
- # Override the detected TTY output state (mostly for testing)
2105
- def tty_output=( tty_output_state )
2106
- @tty_output = tty_output_state
2107
- end
2108
-
2109
- # We will truncate output if we are outputting to a TTY or if we've been
2110
- # given an explicit column width to honor
2111
- def truncate_output?
2112
- tty_output? || ENV['RAKE_COLUMNS']
2113
- end
2114
-
2115
- # Display the tasks and comments.
2116
- def display_tasks_and_comments
2117
- displayable_tasks = tasks.select { |t|
2118
- t.comment && t.name =~ options.show_task_pattern
2119
- }
2120
- if options.full_description
2121
- displayable_tasks.each do |t|
2122
- puts "#{name} #{t.name_with_args}"
2123
- t.full_comment.split("\n").each do |line|
2124
- puts " #{line}"
2125
- end
2126
- puts
2127
- end
2128
- else
2129
- width = displayable_tasks.collect { |t| t.name_with_args.length }.max || 10
2130
- max_column = truncate_output? ? terminal_width - name.size - width - 7 : nil
2131
- displayable_tasks.each do |t|
2132
- printf "#{name} %-#{width}s # %s\n",
2133
- t.name_with_args, max_column ? truncate(t.comment, max_column) : t.comment
2134
- end
2135
- end
2136
- end
2137
-
2138
- def terminal_width
2139
- if ENV['RAKE_COLUMNS']
2140
- result = ENV['RAKE_COLUMNS'].to_i
2141
- else
2142
- result = unix? ? dynamic_width : 80
2143
- end
2144
- (result < 10) ? 80 : result
2145
- rescue
2146
- 80
2147
- end
2148
-
2149
- # Calculate the dynamic width of the
2150
- def dynamic_width
2151
- @dynamic_width ||= (dynamic_width_stty.nonzero? || dynamic_width_tput)
2152
- end
2153
-
2154
- def dynamic_width_stty
2155
- %x{stty size 2>/dev/null}.split[1].to_i
2156
- end
2157
-
2158
- def dynamic_width_tput
2159
- %x{tput cols 2>/dev/null}.to_i
2160
- end
2161
-
2162
- def unix?
2163
- RUBY_PLATFORM =~ /(aix|darwin|linux|(net|free|open)bsd|cygwin|solaris|irix|hpux)/i
2164
- end
2165
-
2166
- def windows?
2167
- Win32.windows?
2168
- end
2169
-
2170
- def truncate(string, width)
2171
- if string.length <= width
2172
- string
2173
- else
2174
- ( string[0, width-3] || "" ) + "..."
2175
- end
2176
- end
2177
-
2178
- # Display the tasks and prerequisites
2179
- def display_prerequisites
2180
- tasks.each do |t|
2181
- puts "#{name} #{t.name}"
2182
- t.prerequisites.each { |pre| puts " #{pre}" }
2183
- end
2184
- end
2185
-
2186
- # A list of all the standard options used in rake, suitable for
2187
- # passing to OptionParser.
2188
- def standard_rake_options
2189
- [
2190
- ['--classic-namespace', '-C', "Put Task and FileTask in the top level namespace",
2191
- lambda { |value|
2192
- require 'rake/classic_namespace'
2193
- options.classic_namespace = true
2194
- }
2195
- ],
2196
- ['--describe', '-D [PATTERN]', "Describe the tasks (matching optional PATTERN), then exit.",
2197
- lambda { |value|
2198
- options.show_tasks = true
2199
- options.full_description = true
2200
- options.show_task_pattern = Regexp.new(value || '')
2201
- }
2202
- ],
2203
- ['--dry-run', '-n', "Do a dry run without executing actions.",
2204
- lambda { |value|
2205
- verbose(true)
2206
- nowrite(true)
2207
- options.dryrun = true
2208
- options.trace = true
2209
- }
2210
- ],
2211
- ['--execute', '-e CODE', "Execute some Ruby code and exit.",
2212
- lambda { |value|
2213
- eval(value)
2214
- exit
2215
- }
2216
- ],
2217
- ['--execute-print', '-p CODE', "Execute some Ruby code, print the result, then exit.",
2218
- lambda { |value|
2219
- puts eval(value)
2220
- exit
2221
- }
2222
- ],
2223
- ['--execute-continue', '-E CODE',
2224
- "Execute some Ruby code, then continue with normal task processing.",
2225
- lambda { |value| eval(value) }
2226
- ],
2227
- ['--libdir', '-I LIBDIR', "Include LIBDIR in the search path for required modules.",
2228
- lambda { |value| $:.push(value) }
2229
- ],
2230
- ['--prereqs', '-P', "Display the tasks and dependencies, then exit.",
2231
- lambda { |value| options.show_prereqs = true }
2232
- ],
2233
- ['--quiet', '-q', "Do not log messages to standard output.",
2234
- lambda { |value| verbose(false) }
2235
- ],
2236
- ['--rakefile', '-f [FILE]', "Use FILE as the rakefile.",
2237
- lambda { |value|
2238
- value ||= ''
2239
- @rakefiles.clear
2240
- @rakefiles << value
2241
- }
2242
- ],
2243
- ['--rakelibdir', '--rakelib', '-R RAKELIBDIR',
2244
- "Auto-import any .rake files in RAKELIBDIR. (default is 'rakelib')",
2245
- lambda { |value| options.rakelib = value.split(':') }
2246
- ],
2247
- ['--require', '-r MODULE', "Require MODULE before executing rakefile.",
2248
- lambda { |value|
2249
- begin
2250
- require value
2251
- rescue LoadError => ex
2252
- begin
2253
- rake_require value
2254
- rescue LoadError => ex2
2255
- raise ex
2256
- end
2257
- end
2258
- }
2259
- ],
2260
- ['--rules', "Trace the rules resolution.",
2261
- lambda { |value| options.trace_rules = true }
2262
- ],
2263
- ['--no-search', '--nosearch', '-N', "Do not search parent directories for the Rakefile.",
2264
- lambda { |value| options.nosearch = true }
2265
- ],
2266
- ['--silent', '-s', "Like --quiet, but also suppresses the 'in directory' announcement.",
2267
- lambda { |value|
2268
- verbose(false)
2269
- options.silent = true
2270
- }
2271
- ],
2272
- ['--system', '-g',
2273
- "Using system wide (global) rakefiles (usually '~/.rake/*.rake').",
2274
- lambda { |value| options.load_system = true }
2275
- ],
2276
- ['--no-system', '--nosystem', '-G',
2277
- "Use standard project Rakefile search paths, ignore system wide rakefiles.",
2278
- lambda { |value| options.ignore_system = true }
2279
- ],
2280
- ['--tasks', '-T [PATTERN]', "Display the tasks (matching optional PATTERN) with descriptions, then exit.",
2281
- lambda { |value|
2282
- options.show_tasks = true
2283
- options.show_task_pattern = Regexp.new(value || '')
2284
- options.full_description = false
2285
- }
2286
- ],
2287
- ['--trace', '-t', "Turn on invoke/execute tracing, enable full backtrace.",
2288
- lambda { |value|
2289
- options.trace = true
2290
- verbose(true)
2291
- }
2292
- ],
2293
- ['--verbose', '-v', "Log message to standard output.",
2294
- lambda { |value| verbose(true) }
2295
- ],
2296
- ['--version', '-V', "Display the program version.",
2297
- lambda { |value|
2298
- puts "rake, version #{RAKEVERSION}"
2299
- exit
2300
- }
2301
- ]
2302
- ]
2303
- end
2304
-
2305
- # Read and handle the command line options.
2306
- def handle_options
2307
- options.rakelib = ['rakelib']
2308
-
2309
- OptionParser.new do |opts|
2310
- opts.banner = "rake [-f rakefile] {options} targets..."
2311
- opts.separator ""
2312
- opts.separator "Options are ..."
2313
-
2314
- opts.on_tail("-h", "--help", "-H", "Display this help message.") do
2315
- puts opts
2316
- exit
2317
- end
2318
-
2319
- standard_rake_options.each { |args| opts.on(*args) }
2320
- end.parse!
2321
-
2322
- # If class namespaces are requested, set the global options
2323
- # according to the values in the options structure.
2324
- if options.classic_namespace
2325
- $show_tasks = options.show_tasks
2326
- $show_prereqs = options.show_prereqs
2327
- $trace = options.trace
2328
- $dryrun = options.dryrun
2329
- $silent = options.silent
2330
- end
2331
- end
2332
-
2333
- # Similar to the regular Ruby +require+ command, but will check
2334
- # for *.rake files in addition to *.rb files.
2335
- def rake_require(file_name, paths=$LOAD_PATH, loaded=$")
2336
- return false if loaded.include?(file_name)
2337
- paths.each do |path|
2338
- fn = file_name + ".rake"
2339
- full_path = File.join(path, fn)
2340
- if File.exist?(full_path)
2341
- load full_path
2342
- loaded << fn
2343
- return true
2344
- end
2345
- end
2346
- fail LoadError, "Can't find #{file_name}"
2347
- end
2348
-
2349
- def find_rakefile_location
2350
- here = Dir.pwd
2351
- while ! (fn = have_rakefile)
2352
- Dir.chdir("..")
2353
- if Dir.pwd == here || options.nosearch
2354
- return nil
2355
- end
2356
- here = Dir.pwd
2357
- end
2358
- [fn, here]
2359
- ensure
2360
- Dir.chdir(Rake.original_dir)
2361
- end
2362
-
2363
- def raw_load_rakefile # :nodoc:
2364
- rakefile, location = find_rakefile_location
2365
- if (! options.ignore_system) &&
2366
- (options.load_system || rakefile.nil?) &&
2367
- system_dir && File.directory?(system_dir)
2368
- puts "(in #{Dir.pwd})" unless options.silent
2369
- glob("#{system_dir}/*.rake") do |name|
2370
- add_import name
2371
- end
2372
- else
2373
- fail "No Rakefile found (looking for: #{@rakefiles.join(', ')})" if
2374
- rakefile.nil?
2375
- @rakefile = rakefile
2376
- Dir.chdir(location)
2377
- puts "(in #{Dir.pwd})" unless options.silent
2378
- $rakefile = @rakefile if options.classic_namespace
2379
- load File.expand_path(@rakefile) if @rakefile && @rakefile != ''
2380
- options.rakelib.each do |rlib|
2381
- glob("#{rlib}/*.rake") do |name|
2382
- add_import name
2383
- end
2384
- end
2385
- end
2386
- load_imports
2387
- end
2388
-
2389
- def glob(path, &block)
2390
- Dir[path.gsub("\\", '/')].each(&block)
2391
- end
2392
- private :glob
2393
-
2394
- # The directory path containing the system wide rakefiles.
2395
- def system_dir
2396
- @system_dir ||=
2397
- begin
2398
- if ENV['RAKE_SYSTEM']
2399
- ENV['RAKE_SYSTEM']
2400
- else
2401
- standard_system_dir
2402
- end
2403
- end
2404
- end
2405
-
2406
- # The standard directory containing system wide rake files.
2407
- if Win32.windows?
2408
- def standard_system_dir #:nodoc:
2409
- Win32.win32_system_dir
2410
- end
2411
- else
2412
- def standard_system_dir #:nodoc:
2413
- File.join(File.expand_path('~'), '.rake')
2414
- end
2415
- end
2416
- private :standard_system_dir
2417
-
2418
- # Collect the list of tasks on the command line. If no tasks are
2419
- # given, return a list containing only the default task.
2420
- # Environmental assignments are processed at this time as well.
2421
- def collect_tasks
2422
- @top_level_tasks = []
2423
- ARGV.each do |arg|
2424
- if arg =~ /^(\w+)=(.*)$/
2425
- ENV[$1] = $2
2426
- else
2427
- @top_level_tasks << arg unless arg =~ /^-/
2428
- end
2429
- end
2430
- @top_level_tasks.push("default") if @top_level_tasks.size == 0
2431
- end
2432
-
2433
- # Add a file to the list of files to be imported.
2434
- def add_import(fn)
2435
- @pending_imports << fn
2436
- end
2437
-
2438
- # Load the pending list of imported files.
2439
- def load_imports
2440
- while fn = @pending_imports.shift
2441
- next if @imported.member?(fn)
2442
- if fn_task = lookup(fn)
2443
- fn_task.invoke
2444
- end
2445
- ext = File.extname(fn)
2446
- loader = @loaders[ext] || @default_loader
2447
- loader.load(fn)
2448
- @imported << fn
2449
- end
2450
- end
2451
-
2452
- # Warn about deprecated use of top level constant names.
2453
- def const_warning(const_name)
2454
- @const_warning ||= false
2455
- if ! @const_warning
2456
- $stderr.puts %{WARNING: Deprecated reference to top-level constant '#{const_name}' } +
2457
- %{found at: #{rakefile_location}} # '
2458
- $stderr.puts %{ Use --classic-namespace on rake command}
2459
- $stderr.puts %{ or 'require "rake/classic_namespace"' in Rakefile}
2460
- end
2461
- @const_warning = true
2462
- end
2463
-
2464
- def rakefile_location
2465
- begin
2466
- fail
2467
- rescue RuntimeError => ex
2468
- ex.backtrace.find {|str| str =~ /#{@rakefile}/ } || ""
2469
- end
2470
- end
2471
- end
2472
- end
2473
-
2474
-
2475
- class Module
2476
- # Rename the original handler to make it available.
2477
- alias :rake_original_const_missing :const_missing
2478
-
2479
- # Check for deprecated uses of top level (i.e. in Object) uses of
2480
- # Rake class names. If someone tries to reference the constant
2481
- # name, display a warning and return the proper object. Using the
2482
- # --classic-namespace command line option will define these
2483
- # constants in Object and avoid this handler.
2484
- def const_missing(const_name)
2485
- case const_name
2486
- when :Task
2487
- Rake.application.const_warning(const_name)
2488
- Rake::Task
2489
- when :FileTask
2490
- Rake.application.const_warning(const_name)
2491
- Rake::FileTask
2492
- when :FileCreationTask
2493
- Rake.application.const_warning(const_name)
2494
- Rake::FileCreationTask
2495
- when :RakeApp
2496
- Rake.application.const_warning(const_name)
2497
- Rake::Application
2498
- else
2499
- rake_original_const_missing(const_name)
2500
- end
2501
- end
2502
- end