rake 0.9.2.2 → 13.0.6

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.
Files changed (138) hide show
  1. checksums.yaml +7 -0
  2. data/History.rdoc +2403 -0
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +64 -106
  5. data/doc/command_line_usage.rdoc +65 -21
  6. data/doc/glossary.rdoc +40 -49
  7. data/doc/jamis.rb +1 -0
  8. data/doc/rake.1 +156 -0
  9. data/doc/rakefile.rdoc +127 -62
  10. data/{bin → exe}/rake +1 -7
  11. data/lib/rake/application.rb +507 -271
  12. data/lib/rake/backtrace.rb +24 -0
  13. data/lib/rake/clean.rb +54 -8
  14. data/lib/rake/cloneable.rb +11 -19
  15. data/lib/rake/cpu_counter.rb +107 -0
  16. data/lib/rake/default_loader.rb +5 -0
  17. data/lib/rake/dsl_definition.rb +67 -48
  18. data/lib/rake/early_time.rb +5 -1
  19. data/lib/rake/ext/core.rb +5 -6
  20. data/lib/rake/ext/string.rb +61 -52
  21. data/lib/rake/file_creation_task.rb +4 -3
  22. data/lib/rake/file_list.rb +81 -49
  23. data/lib/rake/file_task.rb +15 -8
  24. data/lib/rake/file_utils.rb +63 -43
  25. data/lib/rake/file_utils_ext.rb +14 -25
  26. data/lib/rake/invocation_chain.rb +25 -19
  27. data/lib/rake/invocation_exception_mixin.rb +1 -0
  28. data/lib/rake/late_time.rb +18 -0
  29. data/lib/rake/linked_list.rb +112 -0
  30. data/lib/rake/loaders/makefile.rb +23 -9
  31. data/lib/rake/multi_task.rb +4 -6
  32. data/lib/rake/name_space.rb +36 -23
  33. data/lib/rake/packagetask.rb +71 -34
  34. data/lib/rake/phony.rb +16 -0
  35. data/lib/rake/private_reader.rb +21 -0
  36. data/lib/rake/promise.rb +100 -0
  37. data/lib/rake/pseudo_status.rb +8 -2
  38. data/lib/rake/rake_module.rb +41 -3
  39. data/lib/rake/rake_test_loader.rb +9 -4
  40. data/lib/rake/rule_recursion_overflow_error.rb +2 -2
  41. data/lib/rake/scope.rb +43 -0
  42. data/lib/rake/task.rb +186 -79
  43. data/lib/rake/task_argument_error.rb +1 -0
  44. data/lib/rake/task_arguments.rb +46 -15
  45. data/lib/rake/task_manager.rb +91 -67
  46. data/lib/rake/tasklib.rb +2 -12
  47. data/lib/rake/testtask.rb +61 -63
  48. data/lib/rake/thread_history_display.rb +49 -0
  49. data/lib/rake/thread_pool.rb +163 -0
  50. data/lib/rake/trace_output.rb +23 -0
  51. data/lib/rake/version.rb +5 -3
  52. data/lib/rake/win32.rb +14 -18
  53. data/lib/rake.rb +35 -33
  54. data/rake.gemspec +100 -0
  55. metadata +74 -176
  56. data/.gemtest +0 -0
  57. data/CHANGES +0 -522
  58. data/Rakefile +0 -369
  59. data/TODO +0 -20
  60. data/doc/rake.1.gz +0 -0
  61. data/doc/release_notes/rake-0.4.14.rdoc +0 -23
  62. data/doc/release_notes/rake-0.4.15.rdoc +0 -35
  63. data/doc/release_notes/rake-0.5.0.rdoc +0 -53
  64. data/doc/release_notes/rake-0.5.3.rdoc +0 -78
  65. data/doc/release_notes/rake-0.5.4.rdoc +0 -46
  66. data/doc/release_notes/rake-0.6.0.rdoc +0 -141
  67. data/doc/release_notes/rake-0.7.0.rdoc +0 -119
  68. data/doc/release_notes/rake-0.7.1.rdoc +0 -59
  69. data/doc/release_notes/rake-0.7.2.rdoc +0 -121
  70. data/doc/release_notes/rake-0.7.3.rdoc +0 -47
  71. data/doc/release_notes/rake-0.8.0.rdoc +0 -114
  72. data/doc/release_notes/rake-0.8.2.rdoc +0 -165
  73. data/doc/release_notes/rake-0.8.3.rdoc +0 -112
  74. data/doc/release_notes/rake-0.8.4.rdoc +0 -147
  75. data/doc/release_notes/rake-0.8.5.rdoc +0 -53
  76. data/doc/release_notes/rake-0.8.6.rdoc +0 -55
  77. data/doc/release_notes/rake-0.8.7.rdoc +0 -55
  78. data/doc/release_notes/rake-0.9.0.rdoc +0 -112
  79. data/doc/release_notes/rake-0.9.1.rdoc +0 -52
  80. data/doc/release_notes/rake-0.9.2.rdoc +0 -49
  81. data/install.rb +0 -90
  82. data/lib/rake/alt_system.rb +0 -109
  83. data/lib/rake/classic_namespace.rb +0 -11
  84. data/lib/rake/contrib/compositepublisher.rb +0 -21
  85. data/lib/rake/contrib/ftptools.rb +0 -150
  86. data/lib/rake/contrib/publisher.rb +0 -73
  87. data/lib/rake/contrib/rubyforgepublisher.rb +0 -16
  88. data/lib/rake/contrib/sshpublisher.rb +0 -50
  89. data/lib/rake/contrib/sys.rb +0 -191
  90. data/lib/rake/ext/module.rb +0 -39
  91. data/lib/rake/ext/time.rb +0 -14
  92. data/lib/rake/gempackagetask.rb +0 -15
  93. data/lib/rake/pathmap.rb +0 -1
  94. data/lib/rake/rdoctask.rb +0 -234
  95. data/lib/rake/ruby182_test_unit_fix.rb +0 -25
  96. data/lib/rake/runtest.rb +0 -21
  97. data/test/file_creation.rb +0 -34
  98. data/test/helper.rb +0 -492
  99. data/test/test_rake.rb +0 -40
  100. data/test/test_rake_application.rb +0 -489
  101. data/test/test_rake_application_options.rb +0 -335
  102. data/test/test_rake_clean.rb +0 -14
  103. data/test/test_rake_definitions.rb +0 -80
  104. data/test/test_rake_directory_task.rb +0 -46
  105. data/test/test_rake_dsl.rb +0 -77
  106. data/test/test_rake_early_time.rb +0 -31
  107. data/test/test_rake_extension.rb +0 -59
  108. data/test/test_rake_file_creation_task.rb +0 -56
  109. data/test/test_rake_file_list.rb +0 -628
  110. data/test/test_rake_file_list_path_map.rb +0 -8
  111. data/test/test_rake_file_task.rb +0 -102
  112. data/test/test_rake_file_utils.rb +0 -305
  113. data/test/test_rake_ftp_file.rb +0 -59
  114. data/test/test_rake_functional.rb +0 -450
  115. data/test/test_rake_invocation_chain.rb +0 -52
  116. data/test/test_rake_makefile_loader.rb +0 -44
  117. data/test/test_rake_multi_task.rb +0 -51
  118. data/test/test_rake_name_space.rb +0 -43
  119. data/test/test_rake_package_task.rb +0 -79
  120. data/test/test_rake_path_map.rb +0 -157
  121. data/test/test_rake_path_map_explode.rb +0 -34
  122. data/test/test_rake_path_map_partial.rb +0 -18
  123. data/test/test_rake_pseudo_status.rb +0 -21
  124. data/test/test_rake_rake_test_loader.rb +0 -21
  125. data/test/test_rake_rdoc_task.rb +0 -83
  126. data/test/test_rake_require.rb +0 -40
  127. data/test/test_rake_rules.rb +0 -327
  128. data/test/test_rake_task.rb +0 -267
  129. data/test/test_rake_task_argument_parsing.rb +0 -103
  130. data/test/test_rake_task_arguments.rb +0 -88
  131. data/test/test_rake_task_lib.rb +0 -9
  132. data/test/test_rake_task_manager.rb +0 -157
  133. data/test/test_rake_task_manager_argument_resolution.rb +0 -36
  134. data/test/test_rake_task_with_arguments.rb +0 -173
  135. data/test/test_rake_test_task.rb +0 -120
  136. data/test/test_rake_top_level_functions.rb +0 -111
  137. data/test/test_rake_win32.rb +0 -72
  138. data/test/test_sys.rb +0 -20
@@ -1,17 +1,24 @@
1
- require 'shellwords'
2
- require 'optparse'
1
+ # frozen_string_literal: true
2
+ require "optparse"
3
3
 
4
- require 'rake/task_manager'
5
- require 'rake/win32'
4
+ require "rake/task_manager"
5
+ require "rake/file_list"
6
+ require "rake/thread_pool"
7
+ require "rake/thread_history_display"
8
+ require "rake/trace_output"
9
+ require "rake/win32"
6
10
 
7
11
  module Rake
8
12
 
9
- ######################################################################
13
+ CommandLineOptionError = Class.new(StandardError)
14
+
15
+ ##
10
16
  # Rake main application object. When invoking +rake+ from the
11
17
  # command line, a Rake::Application object is created and run.
12
- #
18
+
13
19
  class Application
14
20
  include TaskManager
21
+ include TraceOutput
15
22
 
16
23
  # The name of the application (typically 'rake')
17
24
  attr_reader :name
@@ -28,12 +35,20 @@ module Rake
28
35
  # List of the top level task names (task names from the command line).
29
36
  attr_reader :top_level_tasks
30
37
 
31
- DEFAULT_RAKEFILES = ['rakefile', 'Rakefile', 'rakefile.rb', 'Rakefile.rb'].freeze
38
+ # Override the detected TTY output state (mostly for testing)
39
+ attr_writer :tty_output
40
+
41
+ DEFAULT_RAKEFILES = [
42
+ "rakefile",
43
+ "Rakefile",
44
+ "rakefile.rb",
45
+ "Rakefile.rb"
46
+ ].freeze
32
47
 
33
48
  # Initialize a Rake::Application object.
34
49
  def initialize
35
50
  super
36
- @name = 'rake'
51
+ @name = "rake"
37
52
  @rakefiles = DEFAULT_RAKEFILES.dup
38
53
  @rakefile = nil
39
54
  @pending_imports = []
@@ -42,11 +57,13 @@ module Rake
42
57
  @default_loader = Rake::DefaultLoader.new
43
58
  @original_dir = Dir.pwd
44
59
  @top_level_tasks = []
45
- add_loader('rb', DefaultLoader.new)
46
- add_loader('rf', DefaultLoader.new)
47
- add_loader('rake', DefaultLoader.new)
60
+ add_loader("rb", DefaultLoader.new)
61
+ add_loader("rf", DefaultLoader.new)
62
+ add_loader("rake", DefaultLoader.new)
48
63
  @tty_output = STDOUT.tty?
49
- @terminal_columns = ENV['RAKE_COLUMNS'].to_i
64
+ @terminal_columns = ENV["RAKE_COLUMNS"].to_i
65
+
66
+ set_default_options
50
67
  end
51
68
 
52
69
  # Run the Rake application. The run method performs the following
@@ -54,25 +71,30 @@ module Rake
54
71
  #
55
72
  # * Initialize the command line options (+init+).
56
73
  # * Define the tasks (+load_rakefile+).
57
- # * Run the top level tasks (+run_tasks+).
74
+ # * Run the top level tasks (+top_level+).
58
75
  #
59
76
  # If you wish to build a custom rake command, you should call
60
77
  # +init+ on your application. Then define any tasks. Finally,
61
78
  # call +top_level+ to run your top level tasks.
62
- def run
79
+ def run(argv = ARGV)
63
80
  standard_exception_handling do
64
- init
81
+ init "rake", argv
65
82
  load_rakefile
66
83
  top_level
67
84
  end
68
85
  end
69
86
 
70
87
  # Initialize the command line parameters and app name.
71
- def init(app_name='rake')
88
+ def init(app_name="rake", argv = ARGV)
72
89
  standard_exception_handling do
73
90
  @name = app_name
74
- handle_options
75
- collect_tasks
91
+ begin
92
+ args = handle_options argv
93
+ rescue ArgumentError
94
+ # Backward compatibility for capistrano
95
+ args = handle_options
96
+ end
97
+ collect_command_line_tasks(args)
76
98
  end
77
99
  end
78
100
 
@@ -85,7 +107,7 @@ module Rake
85
107
 
86
108
  # Run the top level tasks of a Rake application.
87
109
  def top_level
88
- standard_exception_handling do
110
+ run_with_threads do
89
111
  if options.show_tasks
90
112
  display_tasks_and_comments
91
113
  elsif options.show_prereqs
@@ -96,6 +118,22 @@ module Rake
96
118
  end
97
119
  end
98
120
 
121
+ # Run the given block with the thread startup and shutdown.
122
+ def run_with_threads
123
+ thread_pool.gather_history if options.job_stats == :history
124
+
125
+ yield
126
+
127
+ thread_pool.join
128
+ if options.job_stats
129
+ stats = thread_pool.statistics
130
+ puts "Maximum active threads: #{stats[:max_active_threads]} + main"
131
+ puts "Total threads in play: #{stats[:total_threads_in_play]} + main"
132
+ end
133
+ ThreadHistoryDisplay.new(thread_pool.history).show if
134
+ options.job_stats == :history
135
+ end
136
+
99
137
  # Add a loader to handle imported files ending in the extension
100
138
  # +ext+.
101
139
  def add_loader(ext, loader)
@@ -108,53 +146,108 @@ module Rake
108
146
  @options ||= OpenStruct.new
109
147
  end
110
148
 
111
- # private ----------------------------------------------------------------
149
+ # Return the thread pool used for multithreaded processing.
150
+ def thread_pool # :nodoc:
151
+ @thread_pool ||= ThreadPool.new(options.thread_pool_size || Rake.suggested_thread_count-1)
152
+ end
153
+
154
+ # internal ----------------------------------------------------------------
112
155
 
113
- def invoke_task(task_string)
156
+ # Invokes a task with arguments that are extracted from +task_string+
157
+ def invoke_task(task_string) # :nodoc:
114
158
  name, args = parse_task_string(task_string)
115
159
  t = self[name]
116
160
  t.invoke(*args)
117
161
  end
118
162
 
119
- def parse_task_string(string)
120
- if string =~ /^([^\[]+)(\[(.*)\])$/
121
- name = $1
122
- args = $3.split(/\s*,\s*/)
123
- else
124
- name = string
125
- args = []
126
- end
127
- [name, args]
163
+ def parse_task_string(string) # :nodoc:
164
+ /^([^\[]+)(?:\[(.*)\])$/ =~ string.to_s
165
+
166
+ name = $1
167
+ remaining_args = $2
168
+
169
+ return string, [] unless name
170
+ return name, [] if remaining_args.empty?
171
+
172
+ args = []
173
+
174
+ begin
175
+ /\s*((?:[^\\,]|\\.)*?)\s*(?:,\s*(.*))?$/ =~ remaining_args
176
+
177
+ remaining_args = $2
178
+ args << $1.gsub(/\\(.)/, '\1')
179
+ end while remaining_args
180
+
181
+ return name, args
128
182
  end
129
183
 
130
184
  # Provide standard exception handling for the given block.
131
- def standard_exception_handling
132
- begin
133
- yield
134
- rescue SystemExit => ex
135
- # Exit silently with current status
136
- raise
137
- rescue OptionParser::InvalidOption => ex
138
- $stderr.puts ex.message
139
- exit(false)
140
- rescue Exception => ex
141
- # Exit with error message
142
- display_error_message(ex)
143
- exit(false)
144
- end
185
+ def standard_exception_handling # :nodoc:
186
+ yield
187
+ rescue SystemExit
188
+ # Exit silently with current status
189
+ raise
190
+ rescue OptionParser::InvalidOption => ex
191
+ $stderr.puts ex.message
192
+ exit(false)
193
+ rescue Exception => ex
194
+ # Exit with error message
195
+ display_error_message(ex)
196
+ exit_because_of_exception(ex)
197
+ end
198
+
199
+ # Exit the program because of an unhandled exception.
200
+ # (may be overridden by subclasses)
201
+ def exit_because_of_exception(ex) # :nodoc:
202
+ exit(false)
145
203
  end
146
204
 
147
205
  # Display the error message that caused the exception.
148
- def display_error_message(ex)
149
- $stderr.puts "#{name} aborted!"
150
- $stderr.puts ex.message
151
- if options.trace
152
- $stderr.puts ex.backtrace.join("\n")
206
+ def display_error_message(ex) # :nodoc:
207
+ trace "#{name} aborted!"
208
+ display_exception_details(ex)
209
+ trace "Tasks: #{ex.chain}" if has_chain?(ex)
210
+ trace "(See full trace by running task with --trace)" unless
211
+ options.backtrace
212
+ end
213
+
214
+ def display_exception_details(ex) # :nodoc:
215
+ display_exception_details_seen << ex
216
+
217
+ display_exception_message_details(ex)
218
+ display_exception_backtrace(ex)
219
+ display_cause_details(ex.cause) if has_cause?(ex)
220
+ end
221
+
222
+ def display_cause_details(ex) # :nodoc:
223
+ return if display_exception_details_seen.include? ex
224
+
225
+ trace "\nCaused by:"
226
+ display_exception_details(ex)
227
+ end
228
+
229
+ def display_exception_details_seen # :nodoc:
230
+ Thread.current[:rake_display_exception_details_seen] ||= []
231
+ end
232
+
233
+ def has_cause?(ex) # :nodoc:
234
+ ex.respond_to?(:cause) && ex.cause
235
+ end
236
+
237
+ def display_exception_message_details(ex) # :nodoc:
238
+ if ex.instance_of?(RuntimeError)
239
+ trace ex.message
240
+ else
241
+ trace "#{ex.class.name}: #{ex.message}"
242
+ end
243
+ end
244
+
245
+ def display_exception_backtrace(ex) # :nodoc:
246
+ if options.backtrace
247
+ trace ex.backtrace.join("\n")
153
248
  else
154
- $stderr.puts rakefile_location(ex.backtrace)
249
+ trace Backtrace.collapse(ex.backtrace).join("\n")
155
250
  end
156
- $stderr.puts "Tasks: #{ex.chain}" if has_chain?(ex)
157
- $stderr.puts "(See full trace by running task with --trace)" unless options.trace
158
251
  end
159
252
 
160
253
  # Warn about deprecated usage.
@@ -162,27 +255,28 @@ module Rake
162
255
  # Example:
163
256
  # Rake.application.deprecate("import", "Rake.import", caller.first)
164
257
  #
165
- def deprecate(old_usage, new_usage, call_site)
166
- return if options.ignore_deprecate
167
- $stderr.puts "WARNING: '#{old_usage}' is deprecated. " +
168
- "Please use '#{new_usage}' instead.\n" +
169
- " at #{call_site}"
258
+ def deprecate(old_usage, new_usage, call_site) # :nodoc:
259
+ unless options.ignore_deprecate
260
+ $stderr.puts "WARNING: '#{old_usage}' is deprecated. " +
261
+ "Please use '#{new_usage}' instead.\n" +
262
+ " at #{call_site}"
263
+ end
170
264
  end
171
265
 
172
266
  # Does the exception have a task invocation chain?
173
- def has_chain?(exception)
267
+ def has_chain?(exception) # :nodoc:
174
268
  exception.respond_to?(:chain) && exception.chain
175
269
  end
176
270
  private :has_chain?
177
271
 
178
272
  # True if one of the files in RAKEFILES is in the current directory.
179
273
  # If a match is found, it is copied into @rakefile.
180
- def have_rakefile
274
+ def have_rakefile # :nodoc:
181
275
  @rakefiles.each do |fn|
182
276
  if File.exist?(fn)
183
- others = Dir.glob(fn, File::FNM_CASEFOLD)
277
+ others = FileList.glob(fn, File::FNM_CASEFOLD)
184
278
  return others.size == 1 ? others.first : fn
185
- elsif fn == ''
279
+ elsif fn == ""
186
280
  return fn
187
281
  end
188
282
  end
@@ -190,39 +284,41 @@ module Rake
190
284
  end
191
285
 
192
286
  # True if we are outputting to TTY, false otherwise
193
- def tty_output?
287
+ def tty_output? # :nodoc:
194
288
  @tty_output
195
289
  end
196
290
 
197
- # Override the detected TTY output state (mostly for testing)
198
- def tty_output=( tty_output_state )
199
- @tty_output = tty_output_state
200
- end
201
-
202
291
  # We will truncate output if we are outputting to a TTY or if we've been
203
292
  # given an explicit column width to honor
204
- def truncate_output?
293
+ def truncate_output? # :nodoc:
205
294
  tty_output? || @terminal_columns.nonzero?
206
295
  end
207
296
 
208
297
  # Display the tasks and comments.
209
- def display_tasks_and_comments
298
+ def display_tasks_and_comments # :nodoc:
210
299
  displayable_tasks = tasks.select { |t|
211
- t.comment && t.name =~ options.show_task_pattern
300
+ (options.show_all_tasks || t.comment) &&
301
+ t.name =~ options.show_task_pattern
212
302
  }
213
303
  case options.show_tasks
214
304
  when :tasks
215
- width = displayable_tasks.collect { |t| t.name_with_args.length }.max || 10
216
- max_column = truncate_output? ? terminal_width - name.size - width - 7 : nil
305
+ width = displayable_tasks.map { |t| t.name_with_args.length }.max || 10
306
+ if truncate_output?
307
+ max_column = terminal_width - name.size - width - 7
308
+ else
309
+ max_column = nil
310
+ end
217
311
 
218
312
  displayable_tasks.each do |t|
219
- printf "#{name} %-#{width}s # %s\n",
220
- t.name_with_args, max_column ? truncate(t.comment, max_column) : t.comment
313
+ printf("#{name} %-#{width}s # %s\n",
314
+ t.name_with_args,
315
+ max_column ? truncate(t.comment, max_column) : t.comment)
221
316
  end
222
317
  when :describe
223
318
  displayable_tasks.each do |t|
224
319
  puts "#{name} #{t.name_with_args}"
225
- t.full_comment.split("\n").each do |line|
320
+ comment = t.full_comment || ""
321
+ comment.split("\n").each do |line|
226
322
  puts " #{line}"
227
323
  end
228
324
  puts
@@ -230,7 +326,7 @@ module Rake
230
326
  when :lines
231
327
  displayable_tasks.each do |t|
232
328
  t.locations.each do |loc|
233
- printf "#{name} %-30s %s\n",t.name_with_args, loc
329
+ printf "#{name} %-30s %s\n", t.name_with_args, loc
234
330
  end
235
331
  end
236
332
  else
@@ -238,7 +334,7 @@ module Rake
238
334
  end
239
335
  end
240
336
 
241
- def terminal_width
337
+ def terminal_width # :nodoc:
242
338
  if @terminal_columns.nonzero?
243
339
  result = @terminal_columns
244
340
  else
@@ -250,180 +346,306 @@ module Rake
250
346
  end
251
347
 
252
348
  # Calculate the dynamic width of the
253
- def dynamic_width
349
+ def dynamic_width # :nodoc:
254
350
  @dynamic_width ||= (dynamic_width_stty.nonzero? || dynamic_width_tput)
255
351
  end
256
352
 
257
- def dynamic_width_stty
353
+ def dynamic_width_stty # :nodoc:
258
354
  %x{stty size 2>/dev/null}.split[1].to_i
259
355
  end
260
356
 
261
- def dynamic_width_tput
357
+ def dynamic_width_tput # :nodoc:
262
358
  %x{tput cols 2>/dev/null}.to_i
263
359
  end
264
360
 
265
- def unix?
266
- RbConfig::CONFIG['host_os'] =~ /(aix|darwin|linux|(net|free|open)bsd|cygwin|solaris|irix|hpux)/i
361
+ def unix? # :nodoc:
362
+ RbConfig::CONFIG["host_os"] =~
363
+ /(aix|darwin|linux|(net|free|open)bsd|cygwin|solaris|irix|hpux)/i
267
364
  end
268
365
 
269
- def windows?
366
+ def windows? # :nodoc:
270
367
  Win32.windows?
271
368
  end
272
369
 
273
- def truncate(string, width)
274
- if string.length <= width
370
+ def truncate(string, width) # :nodoc:
371
+ if string.nil?
372
+ ""
373
+ elsif string.length <= width
275
374
  string
276
375
  else
277
- ( string[0, width-3] || "" ) + "..."
376
+ (string[0, width - 3] || "") + "..."
278
377
  end
279
378
  end
280
379
 
281
380
  # Display the tasks and prerequisites
282
- def display_prerequisites
381
+ def display_prerequisites # :nodoc:
283
382
  tasks.each do |t|
284
383
  puts "#{name} #{t.name}"
285
384
  t.prerequisites.each { |pre| puts " #{pre}" }
286
385
  end
287
386
  end
288
387
 
388
+ def trace(*strings) # :nodoc:
389
+ options.trace_output ||= $stderr
390
+ trace_on(options.trace_output, *strings)
391
+ end
392
+
393
+ def sort_options(options) # :nodoc:
394
+ options.sort_by { |opt|
395
+ opt.select { |o| o.is_a?(String) && o =~ /^-/ }.map(&:downcase).sort.reverse
396
+ }
397
+ end
398
+ private :sort_options
399
+
289
400
  # A list of all the standard options used in rake, suitable for
290
401
  # passing to OptionParser.
291
- def standard_rake_options
292
- [
293
- ['--classic-namespace', '-C', "Put Task and FileTask in the top level namespace",
294
- lambda { |value|
295
- require 'rake/classic_namespace'
296
- options.classic_namespace = true
297
- }
298
- ],
299
- ['--describe', '-D [PATTERN]', "Describe the tasks (matching optional PATTERN), then exit.",
300
- lambda { |value|
301
- options.show_tasks = :describe
302
- options.show_task_pattern = Regexp.new(value || '')
303
- TaskManager.record_task_metadata = true
304
- }
305
- ],
306
- ['--dry-run', '-n', "Do a dry run without executing actions.",
307
- lambda { |value|
308
- Rake.verbose(true)
309
- Rake.nowrite(true)
310
- options.dryrun = true
311
- options.trace = true
312
- }
313
- ],
314
- ['--execute', '-e CODE', "Execute some Ruby code and exit.",
315
- lambda { |value|
316
- eval(value)
317
- exit
318
- }
319
- ],
320
- ['--execute-print', '-p CODE', "Execute some Ruby code, print the result, then exit.",
321
- lambda { |value|
322
- puts eval(value)
323
- exit
324
- }
325
- ],
326
- ['--execute-continue', '-E CODE',
327
- "Execute some Ruby code, then continue with normal task processing.",
328
- lambda { |value| eval(value) }
329
- ],
330
- ['--libdir', '-I LIBDIR', "Include LIBDIR in the search path for required modules.",
331
- lambda { |value| $:.push(value) }
332
- ],
333
- ['--no-search', '--nosearch', '-N', "Do not search parent directories for the Rakefile.",
334
- lambda { |value| options.nosearch = true }
335
- ],
336
- ['--prereqs', '-P', "Display the tasks and dependencies, then exit.",
337
- lambda { |value| options.show_prereqs = true }
338
- ],
339
- ['--quiet', '-q', "Do not log messages to standard output.",
340
- lambda { |value| Rake.verbose(false) }
341
- ],
342
- ['--rakefile', '-f [FILE]', "Use FILE as the rakefile.",
343
- lambda { |value|
344
- value ||= ''
345
- @rakefiles.clear
346
- @rakefiles << value
347
- }
348
- ],
349
- ['--rakelibdir', '--rakelib', '-R RAKELIBDIR',
350
- "Auto-import any .rake files in RAKELIBDIR. (default is 'rakelib')",
351
- # HACK Use File::PATH_SEPARATOR
352
- lambda { |value| options.rakelib = value.split(':') }
353
- ],
354
- ['--require', '-r MODULE', "Require MODULE before executing rakefile.",
355
- lambda { |value|
356
- begin
357
- require value
358
- rescue LoadError => ex
402
+ def standard_rake_options # :nodoc:
403
+ sort_options(
404
+ [
405
+ ["--all", "-A",
406
+ "Show all tasks, even uncommented ones (in combination with -T or -D)",
407
+ lambda { |value|
408
+ options.show_all_tasks = value
409
+ }
410
+ ],
411
+ ["--backtrace=[OUT]",
412
+ "Enable full backtrace. OUT can be stderr (default) or stdout.",
413
+ lambda { |value|
414
+ options.backtrace = true
415
+ select_trace_output(options, "backtrace", value)
416
+ }
417
+ ],
418
+ ["--build-all", "-B",
419
+ "Build all prerequisites, including those which are up-to-date.",
420
+ lambda { |value|
421
+ options.build_all = true
422
+ }
423
+ ],
424
+ ["--comments",
425
+ "Show commented tasks only",
426
+ lambda { |value|
427
+ options.show_all_tasks = !value
428
+ }
429
+ ],
430
+ ["--describe", "-D [PATTERN]",
431
+ "Describe the tasks (matching optional PATTERN), then exit.",
432
+ lambda { |value|
433
+ select_tasks_to_show(options, :describe, value)
434
+ }
435
+ ],
436
+ ["--directory", "-C [DIRECTORY]",
437
+ "Change to DIRECTORY before doing anything.",
438
+ lambda { |value|
439
+ Dir.chdir value
440
+ @original_dir = Dir.pwd
441
+ }
442
+ ],
443
+ ["--dry-run", "-n",
444
+ "Do a dry run without executing actions.",
445
+ lambda { |value|
446
+ Rake.verbose(true)
447
+ Rake.nowrite(true)
448
+ options.dryrun = true
449
+ options.trace = true
450
+ }
451
+ ],
452
+ ["--execute", "-e CODE",
453
+ "Execute some Ruby code and exit.",
454
+ lambda { |value|
455
+ eval(value)
456
+ exit
457
+ }
458
+ ],
459
+ ["--execute-print", "-p CODE",
460
+ "Execute some Ruby code, print the result, then exit.",
461
+ lambda { |value|
462
+ puts eval(value)
463
+ exit
464
+ }
465
+ ],
466
+ ["--execute-continue", "-E CODE",
467
+ "Execute some Ruby code, " +
468
+ "then continue with normal task processing.",
469
+ lambda { |value| eval(value) }
470
+ ],
471
+ ["--jobs", "-j [NUMBER]",
472
+ "Specifies the maximum number of tasks to execute in parallel. " +
473
+ "(default is number of CPU cores + 4)",
474
+ lambda { |value|
475
+ if value.nil? || value == ""
476
+ value = Float::INFINITY
477
+ elsif value =~ /^\d+$/
478
+ value = value.to_i
479
+ else
480
+ value = Rake.suggested_thread_count
481
+ end
482
+ value = 1 if value < 1
483
+ options.thread_pool_size = value - 1
484
+ }
485
+ ],
486
+ ["--job-stats [LEVEL]",
487
+ "Display job statistics. " +
488
+ "LEVEL=history displays a complete job list",
489
+ lambda { |value|
490
+ if value =~ /^history/i
491
+ options.job_stats = :history
492
+ else
493
+ options.job_stats = true
494
+ end
495
+ }
496
+ ],
497
+ ["--libdir", "-I LIBDIR",
498
+ "Include LIBDIR in the search path for required modules.",
499
+ lambda { |value| $:.push(value) }
500
+ ],
501
+ ["--multitask", "-m",
502
+ "Treat all tasks as multitasks.",
503
+ lambda { |value| options.always_multitask = true }
504
+ ],
505
+ ["--no-search", "--nosearch",
506
+ "-N", "Do not search parent directories for the Rakefile.",
507
+ lambda { |value| options.nosearch = true }
508
+ ],
509
+ ["--prereqs", "-P",
510
+ "Display the tasks and dependencies, then exit.",
511
+ lambda { |value| options.show_prereqs = true }
512
+ ],
513
+ ["--quiet", "-q",
514
+ "Do not log messages to standard output.",
515
+ lambda { |value| Rake.verbose(false) }
516
+ ],
517
+ ["--rakefile", "-f [FILENAME]",
518
+ "Use FILENAME as the rakefile to search for.",
519
+ lambda { |value|
520
+ value ||= ""
521
+ @rakefiles.clear
522
+ @rakefiles << value
523
+ }
524
+ ],
525
+ ["--rakelibdir", "--rakelib", "-R RAKELIBDIR",
526
+ "Auto-import any .rake files in RAKELIBDIR. " +
527
+ "(default is 'rakelib')",
528
+ lambda { |value|
529
+ options.rakelib = value.split(File::PATH_SEPARATOR)
530
+ }
531
+ ],
532
+ ["--require", "-r MODULE",
533
+ "Require MODULE before executing rakefile.",
534
+ lambda { |value|
359
535
  begin
360
- rake_require value
361
- rescue LoadError
362
- raise ex
536
+ require value
537
+ rescue LoadError => ex
538
+ begin
539
+ rake_require value
540
+ rescue LoadError
541
+ raise ex
542
+ end
363
543
  end
364
- end
365
- }
366
- ],
367
- ['--rules', "Trace the rules resolution.",
368
- lambda { |value| options.trace_rules = true }
369
- ],
370
- ['--silent', '-s', "Like --quiet, but also suppresses the 'in directory' announcement.",
371
- lambda { |value|
372
- Rake.verbose(false)
373
- options.silent = true
374
- }
375
- ],
376
- ['--system', '-g',
377
- "Using system wide (global) rakefiles (usually '~/.rake/*.rake').",
378
- lambda { |value| options.load_system = true }
379
- ],
380
- ['--no-system', '--nosystem', '-G',
381
- "Use standard project Rakefile search paths, ignore system wide rakefiles.",
382
- lambda { |value| options.ignore_system = true }
383
- ],
384
- ['--tasks', '-T [PATTERN]', "Display the tasks (matching optional PATTERN) with descriptions, then exit.",
385
- lambda { |value|
386
- options.show_tasks = :tasks
387
- options.show_task_pattern = Regexp.new(value || '')
388
- Rake::TaskManager.record_task_metadata = true
389
- }
390
- ],
391
- ['--trace', '-t', "Turn on invoke/execute tracing, enable full backtrace.",
392
- lambda { |value|
393
- options.trace = true
394
- Rake.verbose(true)
395
- }
396
- ],
397
- ['--verbose', '-v', "Log message to standard output.",
398
- lambda { |value| Rake.verbose(true) }
399
- ],
400
- ['--version', '-V', "Display the program version.",
401
- lambda { |value|
402
- puts "rake, version #{RAKEVERSION}"
403
- exit
404
- }
405
- ],
406
- ['--where', '-W [PATTERN]', "Describe the tasks (matching optional PATTERN), then exit.",
407
- lambda { |value|
408
- options.show_tasks = :lines
409
- options.show_task_pattern = Regexp.new(value || '')
410
- Rake::TaskManager.record_task_metadata = true
411
- }
412
- ],
413
- ['--no-deprecation-warnings', '-X', "Disable the deprecation warnings.",
414
- lambda { |value|
415
- options.ignore_deprecate = true
416
- }
417
- ],
418
- ]
419
- end
420
-
421
- # Read and handle the command line options.
422
- def handle_options
423
- options.rakelib = ['rakelib']
544
+ }
545
+ ],
546
+ ["--rules",
547
+ "Trace the rules resolution.",
548
+ lambda { |value| options.trace_rules = true }
549
+ ],
550
+ ["--silent", "-s",
551
+ "Like --quiet, but also suppresses the " +
552
+ "'in directory' announcement.",
553
+ lambda { |value|
554
+ Rake.verbose(false)
555
+ options.silent = true
556
+ }
557
+ ],
558
+ ["--suppress-backtrace PATTERN",
559
+ "Suppress backtrace lines matching regexp PATTERN. " +
560
+ "Ignored if --trace is on.",
561
+ lambda { |value|
562
+ options.suppress_backtrace_pattern = Regexp.new(value)
563
+ }
564
+ ],
565
+ ["--system", "-g",
566
+ "Using system wide (global) rakefiles " +
567
+ "(usually '~/.rake/*.rake').",
568
+ lambda { |value| options.load_system = true }
569
+ ],
570
+ ["--no-system", "--nosystem", "-G",
571
+ "Use standard project Rakefile search paths, " +
572
+ "ignore system wide rakefiles.",
573
+ lambda { |value| options.ignore_system = true }
574
+ ],
575
+ ["--tasks", "-T [PATTERN]",
576
+ "Display the tasks (matching optional PATTERN) " +
577
+ "with descriptions, then exit. " +
578
+ "-AT combination displays all of tasks contained no description.",
579
+ lambda { |value|
580
+ select_tasks_to_show(options, :tasks, value)
581
+ }
582
+ ],
583
+ ["--trace=[OUT]", "-t",
584
+ "Turn on invoke/execute tracing, enable full backtrace. " +
585
+ "OUT can be stderr (default) or stdout.",
586
+ lambda { |value|
587
+ options.trace = true
588
+ options.backtrace = true
589
+ select_trace_output(options, "trace", value)
590
+ Rake.verbose(true)
591
+ }
592
+ ],
593
+ ["--verbose", "-v",
594
+ "Log message to standard output.",
595
+ lambda { |value| Rake.verbose(true) }
596
+ ],
597
+ ["--version", "-V",
598
+ "Display the program version.",
599
+ lambda { |value|
600
+ puts "rake, version #{Rake::VERSION}"
601
+ exit
602
+ }
603
+ ],
604
+ ["--where", "-W [PATTERN]",
605
+ "Describe the tasks (matching optional PATTERN), then exit.",
606
+ lambda { |value|
607
+ select_tasks_to_show(options, :lines, value)
608
+ options.show_all_tasks = true
609
+ }
610
+ ],
611
+ ["--no-deprecation-warnings", "-X",
612
+ "Disable the deprecation warnings.",
613
+ lambda { |value|
614
+ options.ignore_deprecate = true
615
+ }
616
+ ],
617
+ ])
618
+ end
619
+
620
+ def select_tasks_to_show(options, show_tasks, value) # :nodoc:
621
+ options.show_tasks = show_tasks
622
+ options.show_task_pattern = Regexp.new(value || "")
623
+ Rake::TaskManager.record_task_metadata = true
624
+ end
625
+ private :select_tasks_to_show
626
+
627
+ def select_trace_output(options, trace_option, value) # :nodoc:
628
+ value = value.strip unless value.nil?
629
+ case value
630
+ when "stdout"
631
+ options.trace_output = $stdout
632
+ when "stderr", nil
633
+ options.trace_output = $stderr
634
+ else
635
+ fail CommandLineOptionError,
636
+ "Unrecognized --#{trace_option} option '#{value}'"
637
+ end
638
+ end
639
+ private :select_trace_output
640
+
641
+ # Read and handle the command line options. Returns the command line
642
+ # arguments that we didn't understand, which should (in theory) be just
643
+ # task names and env vars.
644
+ def handle_options(argv) # :nodoc:
645
+ set_default_options
424
646
 
425
647
  OptionParser.new do |opts|
426
- opts.banner = "rake [-f rakefile] {options} targets..."
648
+ opts.banner = "#{Rake.application.name} [-f rakefile] {options} targets..."
427
649
  opts.separator ""
428
650
  opts.separator "Options are ..."
429
651
 
@@ -433,23 +655,13 @@ module Rake
433
655
  end
434
656
 
435
657
  standard_rake_options.each { |args| opts.on(*args) }
436
- opts.environment('RAKEOPT')
437
- end.parse!
438
-
439
- # If class namespaces are requested, set the global options
440
- # according to the values in the options structure.
441
- if options.classic_namespace
442
- $show_tasks = options.show_tasks
443
- $show_prereqs = options.show_prereqs
444
- $trace = options.trace
445
- $dryrun = options.dryrun
446
- $silent = options.silent
447
- end
658
+ opts.environment("RAKEOPT")
659
+ end.parse(argv)
448
660
  end
449
661
 
450
662
  # Similar to the regular Ruby +require+ command, but will check
451
663
  # for *.rake files in addition to *.rb files.
452
- def rake_require(file_name, paths=$LOAD_PATH, loaded=$")
664
+ def rake_require(file_name, paths=$LOAD_PATH, loaded=$") # :nodoc:
453
665
  fn = file_name + ".rake"
454
666
  return false if loaded.include?(fn)
455
667
  paths.each do |path|
@@ -463,13 +675,11 @@ module Rake
463
675
  fail LoadError, "Can't find #{file_name}"
464
676
  end
465
677
 
466
- def find_rakefile_location
678
+ def find_rakefile_location # :nodoc:
467
679
  here = Dir.pwd
468
- while ! (fn = have_rakefile)
680
+ until (fn = have_rakefile)
469
681
  Dir.chdir("..")
470
- if Dir.pwd == here || options.nosearch
471
- return nil
472
- end
682
+ return nil if Dir.pwd == here || options.nosearch
473
683
  here = Dir.pwd
474
684
  end
475
685
  [fn, here]
@@ -477,14 +687,14 @@ module Rake
477
687
  Dir.chdir(Rake.original_dir)
478
688
  end
479
689
 
480
- def print_rakefile_directory(location)
690
+ def print_rakefile_directory(location) # :nodoc:
481
691
  $stderr.puts "(in #{Dir.pwd})" unless
482
692
  options.silent or original_dir == location
483
693
  end
484
694
 
485
695
  def raw_load_rakefile # :nodoc:
486
696
  rakefile, location = find_rakefile_location
487
- if (! options.ignore_system) &&
697
+ if (!options.ignore_system) &&
488
698
  (options.load_system || rakefile.nil?) &&
489
699
  system_dir && File.directory?(system_dir)
490
700
  print_rakefile_directory(location)
@@ -497,8 +707,8 @@ module Rake
497
707
  @rakefile = rakefile
498
708
  Dir.chdir(location)
499
709
  print_rakefile_directory(location)
500
- $rakefile = @rakefile if options.classic_namespace
501
- Rake.load_rakefile(File.expand_path(@rakefile)) if @rakefile && @rakefile != ''
710
+ Rake.load_rakefile(File.expand_path(@rakefile)) if
711
+ @rakefile && @rakefile != ""
502
712
  options.rakelib.each do |rlib|
503
713
  glob("#{rlib}/*.rake") do |name|
504
714
  add_import name
@@ -508,17 +718,17 @@ module Rake
508
718
  load_imports
509
719
  end
510
720
 
511
- def glob(path, &block)
512
- Dir[path.gsub("\\", '/')].each(&block)
721
+ def glob(path, &block) # :nodoc:
722
+ FileList.glob(path.tr("\\", "/")).each(&block)
513
723
  end
514
724
  private :glob
515
725
 
516
726
  # The directory path containing the system wide rakefiles.
517
- def system_dir
727
+ def system_dir # :nodoc:
518
728
  @system_dir ||=
519
729
  begin
520
- if ENV['RAKE_SYSTEM']
521
- ENV['RAKE_SYSTEM']
730
+ if ENV["RAKE_SYSTEM"]
731
+ ENV["RAKE_SYSTEM"]
522
732
  else
523
733
  standard_system_dir
524
734
  end
@@ -532,7 +742,7 @@ module Rake
532
742
  end
533
743
  else
534
744
  def standard_system_dir #:nodoc:
535
- File.join(File.expand_path('~'), '.rake')
745
+ File.join(File.expand_path("~"), ".rake")
536
746
  end
537
747
  end
538
748
  private :standard_system_dir
@@ -540,56 +750,82 @@ module Rake
540
750
  # Collect the list of tasks on the command line. If no tasks are
541
751
  # given, return a list containing only the default task.
542
752
  # Environmental assignments are processed at this time as well.
543
- def collect_tasks
753
+ #
754
+ # `args` is the list of arguments to peruse to get the list of tasks.
755
+ # It should be the command line that was given to rake, less any
756
+ # recognised command-line options, which OptionParser.parse will
757
+ # have taken care of already.
758
+ def collect_command_line_tasks(args) # :nodoc:
544
759
  @top_level_tasks = []
545
- ARGV.each do |arg|
546
- if arg =~ /^(\w+)=(.*)$/
760
+ args.each do |arg|
761
+ if arg =~ /^(\w+)=(.*)$/m
547
762
  ENV[$1] = $2
548
763
  else
549
764
  @top_level_tasks << arg unless arg =~ /^-/
550
765
  end
551
766
  end
552
- @top_level_tasks.push("default") if @top_level_tasks.size == 0
767
+ @top_level_tasks.push(default_task_name) if @top_level_tasks.empty?
768
+ end
769
+
770
+ # Default task name ("default").
771
+ # (May be overridden by subclasses)
772
+ def default_task_name # :nodoc:
773
+ "default"
553
774
  end
554
775
 
555
776
  # Add a file to the list of files to be imported.
556
- def add_import(fn)
777
+ def add_import(fn) # :nodoc:
557
778
  @pending_imports << fn
558
779
  end
559
780
 
560
781
  # Load the pending list of imported files.
561
- def load_imports
782
+ def load_imports # :nodoc:
562
783
  while fn = @pending_imports.shift
563
784
  next if @imported.member?(fn)
564
- if fn_task = lookup(fn)
565
- fn_task.invoke
566
- end
785
+ fn_task = lookup(fn) and fn_task.invoke
567
786
  ext = File.extname(fn)
568
787
  loader = @loaders[ext] || @default_loader
569
788
  loader.load(fn)
789
+ if fn_task = lookup(fn) and fn_task.needed?
790
+ fn_task.reenable
791
+ fn_task.invoke
792
+ loader.load(fn)
793
+ end
570
794
  @imported << fn
571
795
  end
572
796
  end
573
797
 
574
- # Warn about deprecated use of top level constant names.
575
- def const_warning(const_name)
576
- @const_warning ||= false
577
- if ! @const_warning
578
- $stderr.puts %{WARNING: Deprecated reference to top-level constant '#{const_name}' } +
579
- %{found at: #{rakefile_location}} # '
580
- $stderr.puts %{ Use --classic-namespace on rake command}
581
- $stderr.puts %{ or 'require "rake/classic_namespace"' in Rakefile}
582
- end
583
- @const_warning = true
584
- end
585
-
586
- def rakefile_location backtrace = caller
587
- backtrace.map { |t| t[/([^:]+):/,1] }
798
+ def rakefile_location(backtrace=caller) # :nodoc:
799
+ backtrace.map { |t| t[/([^:]+):/, 1] }
588
800
 
589
801
  re = /^#{@rakefile}$/
590
802
  re = /#{re.source}/i if windows?
591
803
 
592
- backtrace.find { |str| str =~ re } || ''
804
+ backtrace.find { |str| str =~ re } || ""
805
+ end
806
+
807
+ def set_default_options # :nodoc:
808
+ options.always_multitask = false
809
+ options.backtrace = false
810
+ options.build_all = false
811
+ options.dryrun = false
812
+ options.ignore_deprecate = false
813
+ options.ignore_system = false
814
+ options.job_stats = false
815
+ options.load_system = false
816
+ options.nosearch = false
817
+ options.rakelib = %w[rakelib]
818
+ options.show_all_tasks = false
819
+ options.show_prereqs = false
820
+ options.show_task_pattern = nil
821
+ options.show_tasks = nil
822
+ options.silent = false
823
+ options.suppress_backtrace_pattern = nil
824
+ options.thread_pool_size = Rake.suggested_thread_count
825
+ options.trace = false
826
+ options.trace_output = $stderr
827
+ options.trace_rules = false
593
828
  end
829
+
594
830
  end
595
831
  end