jimweirich-rake 0.8.4.99 → 0.8.5

Sign up to get free protection for your applications and to get access to all the features.
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