rake 0.9.2.2 → 0.9.4

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 (50) hide show
  1. data/CHANGES +4 -0
  2. data/README.rdoc +10 -20
  3. data/Rakefile +6 -1
  4. data/TODO +1 -0
  5. data/bin/rake +4 -0
  6. data/doc/command_line_usage.rdoc +61 -12
  7. data/doc/release_notes/rake-0.9.2.2.rdoc +55 -0
  8. data/doc/release_notes/rake-0.9.3.rdoc +102 -0
  9. data/install.rb +1 -1
  10. data/lib/rake/application.rb +245 -140
  11. data/lib/rake/backtrace.rb +18 -0
  12. data/lib/rake/clean.rb +1 -1
  13. data/lib/rake/cloneable.rb +7 -16
  14. data/lib/rake/contrib/ftptools.rb +2 -1
  15. data/lib/rake/contrib/sys.rb +7 -6
  16. data/lib/rake/dsl_definition.rb +13 -7
  17. data/lib/rake/ext/module.rb +1 -1
  18. data/lib/rake/ext/string.rb +2 -1
  19. data/lib/rake/ext/time.rb +2 -1
  20. data/lib/rake/file_list.rb +9 -2
  21. data/lib/rake/file_utils_ext.rb +4 -3
  22. data/lib/rake/multi_task.rb +2 -5
  23. data/lib/rake/phony.rb +15 -0
  24. data/lib/rake/private_reader.rb +20 -0
  25. data/lib/rake/promise.rb +99 -0
  26. data/lib/rake/rake_module.rb +8 -0
  27. data/lib/rake/rdoctask.rb +1 -1
  28. data/lib/rake/runtest.rb +2 -1
  29. data/lib/rake/task.rb +29 -7
  30. data/lib/rake/task_arguments.rb +1 -1
  31. data/lib/rake/task_manager.rb +1 -1
  32. data/lib/rake/testtask.rb +8 -1
  33. data/lib/rake/thread_history_display.rb +48 -0
  34. data/lib/rake/thread_pool.rb +155 -0
  35. data/lib/rake/version.rb +6 -4
  36. data/lib/rake.rb +1 -0
  37. data/test/helper.rb +57 -0
  38. data/test/test_private_reader.rb +42 -0
  39. data/test/test_rake_application.rb +12 -1
  40. data/test/test_rake_application_options.rb +114 -4
  41. data/test/test_rake_backtrace.rb +81 -0
  42. data/test/test_rake_directory_task.rb +16 -5
  43. data/test/test_rake_file_task.rb +21 -1
  44. data/test/test_rake_functional.rb +40 -1
  45. data/test/test_rake_multi_task.rb +8 -0
  46. data/test/test_rake_reduce_compat.rb +65 -0
  47. data/test/test_rake_task.rb +50 -1
  48. data/test/test_rake_thread_pool.rb +123 -0
  49. data/test/test_thread_history_display.rb +91 -0
  50. metadata +50 -34
@@ -52,8 +52,8 @@ module Rake
52
52
 
53
53
  # Declare a file creation task.
54
54
  # (Mainly used for the directory command).
55
- def file_create(args, &block)
56
- Rake::FileCreationTask.define_task(args, &block)
55
+ def file_create(*args, &block)
56
+ Rake::FileCreationTask.define_task(*args, &block)
57
57
  end
58
58
 
59
59
  # Declare a set of files tasks to create the given directories on
@@ -62,12 +62,15 @@ module Rake
62
62
  # Example:
63
63
  # directory "testdata/doc"
64
64
  #
65
- def directory(dir)
65
+ def directory(*args, &block)
66
+ result = file_create(*args, &block)
67
+ dir, _ = *Rake.application.resolve_args(args)
66
68
  Rake.each_dir_parent(dir) do |d|
67
69
  file_create d do |t|
68
70
  mkdir_p t.name if ! File.exist?(t.name)
69
71
  end
70
72
  end
73
+ result
71
74
  end
72
75
 
73
76
  # Declare a task that performs its prerequisites in
@@ -78,8 +81,8 @@ module Rake
78
81
  # Example:
79
82
  # multitask :deploy => [:deploy_gem, :deploy_rdoc]
80
83
  #
81
- def multitask(args, &block)
82
- Rake::MultiTask.define_task(args, &block)
84
+ def multitask(*args, &block)
85
+ Rake::MultiTask.define_task(*args, &block)
83
86
  end
84
87
 
85
88
  # Create a new rake namespace and use it for evaluating the given
@@ -167,10 +170,13 @@ module Rake
167
170
  private :#{name}
168
171
  }, __FILE__, line
169
172
  end
170
- end
173
+ end unless defined? Rake::REDUCE_COMPAT
171
174
 
172
175
  extend FileUtilsExt
173
176
  end
174
177
 
178
+ # Extend the main object with the DSL commands. This allows top-level
179
+ # calls to task, etc. to work from a Rakefile without polluting the
180
+ # object inheritance tree.
175
181
  self.extend Rake::DSL
176
- include Rake::DeprecatedObjectDSL
182
+ include Rake::DeprecatedObjectDSL unless defined? Rake::REDUCE_COMPAT
@@ -36,4 +36,4 @@ class Module
36
36
  rake_original_const_missing(const_name)
37
37
  end
38
38
  end
39
- end
39
+ end unless defined? Rake::REDUCE_COMPAT
@@ -4,6 +4,7 @@ require 'rake/ext/core'
4
4
  # Rake extension methods for String.
5
5
  #
6
6
  class String
7
+
7
8
  rake_extension("ext") do
8
9
  # Replace the file extension with +newext+. If there is no extension on
9
10
  # the string, append the new extension to the end. If the new extension
@@ -163,5 +164,5 @@ class String
163
164
  result
164
165
  end
165
166
  end
166
- end # class String
167
167
 
168
+ end
data/lib/rake/ext/time.rb CHANGED
@@ -1,6 +1,8 @@
1
1
  #--
2
2
  # Extensions to time to allow comparisons with an early time class.
3
3
 
4
+ require 'rake/early_time'
5
+
4
6
  class Time
5
7
  alias rake_original_time_compare :<=>
6
8
  def <=>(other)
@@ -11,4 +13,3 @@ class Time
11
13
  end
12
14
  end
13
15
  end
14
-
@@ -286,7 +286,7 @@ module Rake
286
286
  matched = 0
287
287
  each do |fn|
288
288
  begin
289
- open(fn, "rb", *options) do |inf|
289
+ open(fn, "r", *options) do |inf|
290
290
  count = 0
291
291
  inf.each do |line|
292
292
  count += 1
@@ -340,7 +340,7 @@ module Rake
340
340
 
341
341
  # Add matching glob patterns.
342
342
  def add_matching(pattern)
343
- Dir[pattern].each do |fn|
343
+ FileList.glob(pattern).each do |fn|
344
344
  self << fn unless exclude?(fn)
345
345
  end
346
346
  end
@@ -383,6 +383,13 @@ module Rake
383
383
  def [](*args)
384
384
  new(*args)
385
385
  end
386
+
387
+ # Get a sorted list of files matching the pattern. This method
388
+ # should be prefered to Dir[pattern] and Dir.glob[pattern] because
389
+ # the files returned are guaranteed to be sorted.
390
+ def glob(pattern, *args)
391
+ Dir.glob(pattern, *args).sort
392
+ end
386
393
  end
387
394
  end
388
395
  end
@@ -21,12 +21,13 @@ module Rake
21
21
  $fileutils_verbose = true
22
22
  $fileutils_nowrite = false
23
23
 
24
- FileUtils::OPT_TABLE.each do |name, opts|
24
+ FileUtils.commands.each do |name|
25
+ opts = FileUtils.options_of name
25
26
  default_options = []
26
- if opts.include?(:verbose) || opts.include?("verbose")
27
+ if opts.include?("verbose")
27
28
  default_options << ':verbose => FileUtilsExt.verbose_flag'
28
29
  end
29
- if opts.include?(:noop) || opts.include?("noop")
30
+ if opts.include?("noop")
30
31
  default_options << ':noop => FileUtilsExt.nowrite_flag'
31
32
  end
32
33
 
@@ -5,11 +5,8 @@ module Rake
5
5
  #
6
6
  class MultiTask < Task
7
7
  private
8
- def invoke_prerequisites(args, invocation_chain)
9
- threads = @prerequisites.collect { |p|
10
- Thread.new(p) { |r| application[r, @scope].invoke_with_call_chain(args, invocation_chain) }
11
- }
12
- threads.each { |t| t.join }
8
+ def invoke_prerequisites(task_args, invocation_chain) # :nodoc:
9
+ invoke_prerequisites_concurrently(task_args, invocation_chain)
13
10
  end
14
11
  end
15
12
 
data/lib/rake/phony.rb ADDED
@@ -0,0 +1,15 @@
1
+ # Defines a :phony task that you can use as a dependency. This allows
2
+ # file-based tasks to use non-file-based tasks as prerequisites
3
+ # without forcing them to rebuild.
4
+ #
5
+ # See FileTask#out_of_date? and Task#timestamp for more info.
6
+
7
+ require 'rake'
8
+
9
+ task :phony
10
+
11
+ Rake::Task[:phony].tap do |task|
12
+ def task.timestamp # :nodoc:
13
+ Time.at 0
14
+ end
15
+ end
@@ -0,0 +1,20 @@
1
+ module Rake
2
+
3
+ # Include PrivateReader to use +private_reader+.
4
+ module PrivateReader # :nodoc: all
5
+
6
+ def self.included(base)
7
+ base.extend(ClassMethods)
8
+ end
9
+
10
+ module ClassMethods
11
+
12
+ # Declare a list of private accessors
13
+ def private_reader(*names)
14
+ attr_reader(*names)
15
+ private(*names)
16
+ end
17
+ end
18
+
19
+ end
20
+ end
@@ -0,0 +1,99 @@
1
+ module Rake
2
+
3
+ # A Promise object represents a promise to do work (a chore) in the
4
+ # future. The promise is created with a block and a list of
5
+ # arguments for the block. Calling value will return the value of
6
+ # the promised chore.
7
+ #
8
+ # Used by ThreadPool.
9
+ #
10
+ class Promise # :nodoc: all
11
+ NOT_SET = Object.new.freeze # :nodoc:
12
+
13
+ attr_accessor :recorder
14
+
15
+ # Create a promise to do the chore specified by the block.
16
+ def initialize(args, &block)
17
+ @mutex = Mutex.new
18
+ @result = NOT_SET
19
+ @error = NOT_SET
20
+ @args = args.collect { |a| begin; a.dup; rescue; a; end }
21
+ @block = block
22
+ end
23
+
24
+ # Return the value of this promise.
25
+ #
26
+ # If the promised chore is not yet complete, then do the work
27
+ # synchronously. We will wait.
28
+ def value
29
+ unless complete?
30
+ stat :sleeping_on, :item_id => object_id
31
+ @mutex.synchronize do
32
+ stat :has_lock_on, :item_id => object_id
33
+ chore
34
+ stat :releasing_lock_on, :item_id => object_id
35
+ end
36
+ end
37
+ error? ? raise(@error) : @result
38
+ end
39
+
40
+ # If no one else is working this promise, go ahead and do the chore.
41
+ def work
42
+ stat :attempting_lock_on, :item_id => object_id
43
+ if @mutex.try_lock
44
+ stat :has_lock_on, :item_id => object_id
45
+ chore
46
+ stat :releasing_lock_on, :item_id => object_id
47
+ @mutex.unlock
48
+ else
49
+ stat :bailed_on, :item_id => object_id
50
+ end
51
+ end
52
+
53
+ private
54
+
55
+ # Perform the chore promised
56
+ def chore
57
+ if complete?
58
+ stat :found_completed, :item_id => object_id
59
+ return
60
+ end
61
+ stat :will_execute, :item_id => object_id
62
+ begin
63
+ @result = @block.call(*@args)
64
+ rescue Exception => e
65
+ @error = e
66
+ end
67
+ stat :did_execute, :item_id => object_id
68
+ discard
69
+ end
70
+
71
+ # Do we have a result for the promise
72
+ def result?
73
+ ! @result.equal?(NOT_SET)
74
+ end
75
+
76
+ # Did the promise throw an error
77
+ def error?
78
+ ! @error.equal?(NOT_SET)
79
+ end
80
+
81
+ # Are we done with the promise
82
+ def complete?
83
+ result? || error?
84
+ end
85
+
86
+ # free up these items for the GC
87
+ def discard
88
+ @args = nil
89
+ @block = nil
90
+ end
91
+
92
+ # Record execution statistics if there is a recorder
93
+ def stat(*args)
94
+ @recorder.call(*args) if @recorder
95
+ end
96
+
97
+ end
98
+
99
+ end
@@ -24,6 +24,14 @@ module Rake
24
24
  def load_rakefile(path)
25
25
  load(path)
26
26
  end
27
+
28
+ # Add files to the rakelib list
29
+ def add_rakelib(*files)
30
+ application.options.rakelib ||= []
31
+ files.each do |file|
32
+ application.options.rakelib << file
33
+ end
34
+ end
27
35
  end
28
36
 
29
37
  end
data/lib/rake/rdoctask.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  # rake/rdoctask is deprecated in favor of rdoc/task
2
2
 
3
3
  if Rake.application
4
- Rake.application.deprecate('require \'rake/rdoctask\'', 'require \'rdoc/task\' (in RDoc 2.4.2+)', __FILE__)
4
+ Rake.application.deprecate('require \'rake/rdoctask\'', 'require \'rdoc/task\' (in RDoc 2.4.2+)', caller.first)
5
5
  end
6
6
 
7
7
  require 'rubygems'
data/lib/rake/runtest.rb CHANGED
@@ -1,11 +1,12 @@
1
1
  require 'test/unit'
2
2
  require 'test/unit/assertions'
3
+ require 'rake/file_list'
3
4
 
4
5
  module Rake
5
6
  include Test::Unit::Assertions
6
7
 
7
8
  def run_tests(pattern='test/test*.rb', log_enabled=false)
8
- Dir["#{pattern}"].each { |fn|
9
+ FileList.glob(pattern).each { |fn|
9
10
  $stderr.puts fn if log_enabled
10
11
  begin
11
12
  require fn
data/lib/rake/task.rb CHANGED
@@ -123,6 +123,7 @@ module Rake
123
123
  def clear
124
124
  clear_prerequisites
125
125
  clear_actions
126
+ clear_comments
126
127
  self
127
128
  end
128
129
 
@@ -138,6 +139,13 @@ module Rake
138
139
  self
139
140
  end
140
141
 
142
+ # Clear the existing comments on a rake task.
143
+ def clear_comments
144
+ @full_comment = nil
145
+ @comment = nil
146
+ self
147
+ end
148
+
141
149
  # Invoke the task if it is needed. Prerequisites are invoked first.
142
150
  def invoke(*args)
143
151
  task_args = TaskArguments.new(arg_names, args)
@@ -150,7 +158,7 @@ module Rake
150
158
  new_chain = InvocationChain.append(self, invocation_chain)
151
159
  @lock.synchronize do
152
160
  if application.options.trace
153
- $stderr.puts "** Invoke #{name} #{format_trace_flags}"
161
+ application.trace "** Invoke #{name} #{format_trace_flags}"
154
162
  end
155
163
  return if @already_invoked
156
164
  @already_invoked = true
@@ -171,10 +179,24 @@ module Rake
171
179
 
172
180
  # Invoke all the prerequisites of a task.
173
181
  def invoke_prerequisites(task_args, invocation_chain) # :nodoc:
174
- prerequisite_tasks.each { |prereq|
175
- prereq_args = task_args.new_scope(prereq.arg_names)
176
- prereq.invoke_with_call_chain(prereq_args, invocation_chain)
177
- }
182
+ if application.options.always_multitask
183
+ invoke_prerequisites_concurrently(task_args, invocation_chain)
184
+ else
185
+ prerequisite_tasks.each { |prereq|
186
+ prereq_args = task_args.new_scope(prereq.arg_names)
187
+ prereq.invoke_with_call_chain(prereq_args, invocation_chain)
188
+ }
189
+ end
190
+ end
191
+
192
+ # Invoke all the prerequisites of a task in parallel.
193
+ def invoke_prerequisites_concurrently(args, invocation_chain) # :nodoc:
194
+ futures = @prerequisites.collect do |p|
195
+ application.thread_pool.future(p) do |r|
196
+ application[r, @scope].invoke_with_call_chain(args, invocation_chain)
197
+ end
198
+ end
199
+ futures.each { |f| f.value }
178
200
  end
179
201
 
180
202
  # Format the trace flags for display.
@@ -190,11 +212,11 @@ module Rake
190
212
  def execute(args=nil)
191
213
  args ||= EMPTY_TASK_ARGS
192
214
  if application.options.dryrun
193
- $stderr.puts "** Execute (dry run) #{name}"
215
+ application.trace "** Execute (dry run) #{name}"
194
216
  return
195
217
  end
196
218
  if application.options.trace
197
- $stderr.puts "** Execute #{name}"
219
+ application.trace "** Execute #{name}"
198
220
  end
199
221
  application.enhance_with_matching_rule(name) if @actions.empty?
200
222
  @actions.each do |act|
@@ -47,7 +47,7 @@ module Rake
47
47
  keys.map { |k| lookup(k) }
48
48
  end
49
49
 
50
- def method_missing(sym, *args, &block)
50
+ def method_missing(sym, *args)
51
51
  lookup(sym.to_sym)
52
52
  end
53
53
 
@@ -238,7 +238,7 @@ module Rake
238
238
  end
239
239
 
240
240
  def trace_rule(level, message)
241
- $stderr.puts "#{" "*level}#{message}" if Rake.application.options.trace_rules
241
+ options.trace_output.puts "#{" "*level}#{message}" if Rake.application.options.trace_rules
242
242
  end
243
243
 
244
244
  # Attempt to create a rule given the list of prerequisites.
data/lib/rake/testtask.rb CHANGED
@@ -96,7 +96,14 @@ module Rake
96
96
  desc "Run tests" + (@name==:test ? "" : " for #{@name}")
97
97
  task @name do
98
98
  FileUtilsExt.verbose(@verbose) do
99
- ruby "#{ruby_opts_string} #{run_code} #{file_list_string} #{option_list}"
99
+ args = "#{ruby_opts_string} #{run_code} #{file_list_string} #{option_list}"
100
+ ruby args do |ok, status|
101
+ if !ok && status.respond_to?(:signaled?) && status.signaled?
102
+ raise SignalException.new(status.termsig)
103
+ elsif !ok
104
+ fail "Command failed with status (#{status.exitstatus}): [ruby #{args}]"
105
+ end
106
+ end
100
107
  end
101
108
  end
102
109
  self
@@ -0,0 +1,48 @@
1
+ require 'rake/private_reader'
2
+
3
+ module Rake
4
+
5
+ class ThreadHistoryDisplay # :nodoc: all
6
+ include Rake::PrivateReader
7
+
8
+ private_reader :stats, :items, :threads
9
+
10
+ def initialize(stats)
11
+ @stats = stats
12
+ @items = { :_seq_ => 1 }
13
+ @threads = { :_seq_ => "A" }
14
+ end
15
+
16
+ def show
17
+ puts "Job History:"
18
+ stats.each do |stat|
19
+ stat[:data] ||= {}
20
+ rename(stat, :thread, threads)
21
+ rename(stat[:data], :item_id, items)
22
+ rename(stat[:data], :new_thread, threads)
23
+ rename(stat[:data], :deleted_thread, threads)
24
+ printf("%8d %2s %-20s %s\n",
25
+ (stat[:time] * 1_000_000).round,
26
+ stat[:thread],
27
+ stat[:event],
28
+ stat[:data].map { |k,v| "#{k}:#{v}" }.join(" "))
29
+ end
30
+ end
31
+
32
+ private
33
+
34
+ def rename(hash, key, renames)
35
+ if hash && hash[key]
36
+ original = hash[key]
37
+ value = renames[original]
38
+ unless value
39
+ value = renames[:_seq_]
40
+ renames[:_seq_] = renames[:_seq_].succ
41
+ renames[original] = value
42
+ end
43
+ hash[key] = value
44
+ end
45
+ end
46
+ end
47
+
48
+ end
@@ -0,0 +1,155 @@
1
+ require 'thread'
2
+ require 'set'
3
+
4
+ require 'rake/promise'
5
+
6
+ module Rake
7
+
8
+ class ThreadPool # :nodoc: all
9
+
10
+ # Creates a ThreadPool object.
11
+ # The parameter is the size of the pool.
12
+ def initialize(thread_count)
13
+ @max_active_threads = [thread_count, 0].max
14
+ @threads = Set.new
15
+ @threads_mon = Monitor.new
16
+ @queue = Queue.new
17
+ @join_cond = @threads_mon.new_cond
18
+
19
+ @history_start_time = nil
20
+ @history = []
21
+ @history_mon = Monitor.new
22
+ @total_threads_in_play = 0
23
+ end
24
+
25
+ # Creates a future executed by the +ThreadPool+.
26
+ #
27
+ # The args are passed to the block when executing (similarly to
28
+ # <tt>Thread#new</tt>) The return value is an object representing
29
+ # a future which has been created and added to the queue in the
30
+ # pool. Sending <tt>#value</tt> to the object will sleep the
31
+ # current thread until the future is finished and will return the
32
+ # result (or raise an exception thrown from the future)
33
+ def future(*args, &block)
34
+ promise = Promise.new(args, &block)
35
+ promise.recorder = lambda { |*stats| stat(*stats) }
36
+
37
+ @queue.enq promise
38
+ stat :queued, :item_id => promise.object_id
39
+ start_thread
40
+ promise
41
+ end
42
+
43
+ # Waits until the queue of futures is empty and all threads have exited.
44
+ def join
45
+ @threads_mon.synchronize do
46
+ begin
47
+ stat :joining
48
+ @join_cond.wait unless @threads.empty?
49
+ stat :joined
50
+ rescue Exception => e
51
+ stat :joined
52
+ $stderr.puts e
53
+ $stderr.print "Queue contains #{@queue.size} items. Thread pool contains #{@threads.count} threads\n"
54
+ $stderr.print "Current Thread #{Thread.current} status = #{Thread.current.status}\n"
55
+ $stderr.puts e.backtrace.join("\n")
56
+ @threads.each do |t|
57
+ $stderr.print "Thread #{t} status = #{t.status}\n"
58
+ # 1.8 doesn't support Thread#backtrace
59
+ $stderr.puts t.backtrace.join("\n") if t.respond_to? :backtrace
60
+ end
61
+ raise e
62
+ end
63
+ end
64
+ end
65
+
66
+ # Enable the gathering of history events.
67
+ def gather_history #:nodoc:
68
+ @history_start_time = Time.now if @history_start_time.nil?
69
+ end
70
+
71
+ # Return a array of history events for the thread pool.
72
+ #
73
+ # History gathering must be enabled to be able to see the events
74
+ # (see #gather_history). Best to call this when the job is
75
+ # complete (i.e. after ThreadPool#join is called).
76
+ def history # :nodoc:
77
+ @history_mon.synchronize { @history.dup }.
78
+ sort_by { |i| i[:time] }.
79
+ each { |i| i[:time] -= @history_start_time }
80
+ end
81
+
82
+ # Return a hash of always collected statistics for the thread pool.
83
+ def statistics # :nodoc:
84
+ {
85
+ :total_threads_in_play => @total_threads_in_play,
86
+ :max_active_threads => @max_active_threads,
87
+ }
88
+ end
89
+
90
+ private
91
+
92
+ # processes one item on the queue. Returns true if there was an
93
+ # item to process, false if there was no item
94
+ def process_queue_item #:nodoc:
95
+ return false if @queue.empty?
96
+
97
+ # Even though we just asked if the queue was empty, it
98
+ # still could have had an item which by this statement
99
+ # is now gone. For this reason we pass true to Queue#deq
100
+ # because we will sleep indefinitely if it is empty.
101
+ promise = @queue.deq(true)
102
+ stat :dequeued, :item_id => promise.object_id
103
+ promise.work
104
+ return true
105
+
106
+ rescue ThreadError # this means the queue is empty
107
+ false
108
+ end
109
+
110
+ def start_thread # :nodoc:
111
+ @threads_mon.synchronize do
112
+ next unless @threads.count < @max_active_threads
113
+
114
+ t = Thread.new do
115
+ begin
116
+ while @threads.count <= @max_active_threads
117
+ break unless process_queue_item
118
+ end
119
+ ensure
120
+ @threads_mon.synchronize do
121
+ @threads.delete Thread.current
122
+ stat :ended, :thread_count => @threads.count
123
+ @join_cond.broadcast if @threads.empty?
124
+ end
125
+ end
126
+ end
127
+ @threads << t
128
+ stat :spawned, :new_thread => t.object_id, :thread_count => @threads.count
129
+ @total_threads_in_play = @threads.count if @threads.count > @total_threads_in_play
130
+ end
131
+ end
132
+
133
+ def stat(event, data=nil) # :nodoc:
134
+ return if @history_start_time.nil?
135
+ info = {
136
+ :event => event,
137
+ :data => data,
138
+ :time => Time.now,
139
+ :thread => Thread.current.object_id,
140
+ }
141
+ @history_mon.synchronize { @history << info }
142
+ end
143
+
144
+ # for testing only
145
+
146
+ def __queue__ # :nodoc:
147
+ @queue
148
+ end
149
+
150
+ def __threads__ # :nodoc:
151
+ @threads.dup
152
+ end
153
+ end
154
+
155
+ end
data/lib/rake/version.rb CHANGED
@@ -1,8 +1,10 @@
1
1
  module Rake
2
- VERSION = '0.9.2.2'
3
-
4
2
  module Version # :nodoc: all
5
- MAJOR, MINOR, BUILD, PATCH = VERSION.split('.')
6
- NUMBERS = [ MAJOR, MINOR, BUILD, PATCH ]
3
+ NUMBERS = [
4
+ MAJOR = 0,
5
+ MINOR = 9,
6
+ BUILD = 4,
7
+ ]
7
8
  end
9
+ VERSION = Version::NUMBERS.join('.')
8
10
  end
data/lib/rake.rb CHANGED
@@ -58,6 +58,7 @@ require 'rake/early_time'
58
58
  require 'rake/name_space'
59
59
  require 'rake/task_manager'
60
60
  require 'rake/application'
61
+ require 'rake/backtrace'
61
62
 
62
63
  $trace = false
63
64