rake 0.9.3.beta.3 → 0.9.3.beta.4

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of rake might be problematic. Click here for more details.

data/Rakefile CHANGED
@@ -60,6 +60,7 @@ task :default => :test
60
60
 
61
61
  Rake::TestTask.new do |t|
62
62
  files = FileList['test/helper.rb', 'test/test_*.rb']
63
+ t.loader = :testrb
63
64
  t.test_files = files
64
65
  t.libs << "."
65
66
  t.warning = true
@@ -11,6 +11,16 @@ Options are:
11
11
  during the execution of the <b>rake</b> command. You can access
12
12
  the value by using ENV['<em>name</em>'].
13
13
 
14
+ [<tt>--all</tt> (-A)]
15
+ Used in combination with the -T and -D options, will force
16
+ those options to show all the tasks, even the ones without comments.
17
+
18
+ [<tt>--backtrace</tt> _output_ (-n)]
19
+ Enable a full backtrace (i.e. like --trace, but without the task
20
+ tracing details). The backtrace output will be directed to stderr
21
+ by default. If the options _output_ parameter is set to "stdout",
22
+ then the output will be directed to standard output.
23
+
14
24
  [<tt>--classic-namespace</tt> (-n)]
15
25
  Import the Task, FileTask, and FileCreateTask into the top-level
16
26
  scope to be compatible with older versions of Rake. Alternatively
@@ -18,6 +28,11 @@ Options are:
18
28
  'rake/classic_namespace'</code> in your Rakefile to get the
19
29
  classic behavior.
20
30
 
31
+ [<tt>--comments</tt>]
32
+ Used in combination with the -W options to force the output to
33
+ contain commented options only. This is the reverse of
34
+ <tt>--all</tt>.
35
+
21
36
  [<tt>--describe</tt> _pattern_ (-D)]
22
37
  Describe the tasks (matching optional PATTERN), then exit.
23
38
 
@@ -38,14 +53,27 @@ Options are:
38
53
  Display some help text and exit.
39
54
 
40
55
  [<tt>--jobs</tt> _number_ (-j)]
41
- Specifies the maximum number of concurrent tasks. The suggested
42
- value is equal to the number of CPUs.
43
-
56
+ Specifies the number of active concurrent tasks used. The
57
+ suggested value is equal to the number of CPUs. The concurrent
58
+ tasks are used to execute the <tt>multitask</tt> prerequisites.
59
+ Also see the <tt>-m</tt> option which turns all tasks into
60
+ multitasks.
61
+
44
62
  Sample values:
45
63
  (no -j) : unlimited concurrent tasks (standard rake behavior)
46
64
  -j : 2 concurrent tasks (exact number may change)
47
65
  -j 16 : 16 concurrent tasks
48
66
 
67
+ [<tt>--job-stats</tt> _level_]
68
+
69
+ Display job statistics at the completion of the run. By default,
70
+ this will display the requested number of active tasks (from the
71
+ -j options) and the maximum number of tasks in play at any given
72
+ time.
73
+
74
+ If the optional _level_ is <tt>history</tt>, then a complete trace
75
+ of task history will be displayed on standard output.
76
+
49
77
  [<tt>--libdir</tt> _directory_ (-I)]
50
78
  Add _directory_ to the list of directories searched for require.
51
79
 
@@ -72,6 +100,16 @@ Options are:
72
100
  [<tt>--rakelibdir</tt> _rakelibdir_ (-R)]
73
101
  Auto-import any .rake files in RAKELIBDIR. (default is 'rakelib')
74
102
 
103
+ [<tt>--reduce-compat</tt>]
104
+
105
+ Remove the DSL commands from the Object inheritance hierarchy and
106
+ do not define top level constants. This reduces the backwards
107
+ compatibility of Rake, but allows rake to be used with software
108
+ that would otherwise have conflicting definitions.
109
+
110
+ *NOTE:* The next major version of Rake will only be able to be run
111
+ in "reduce-compat" mode.
112
+
75
113
  [<tt>--require</tt> _name_ (-r)]
76
114
  Require _name_ before executing the Rakefile.
77
115
 
@@ -81,6 +119,11 @@ Options are:
81
119
  [<tt>--silent (-s)</tt>]
82
120
  Like --quiet, but also suppresses the 'in directory' announcement.
83
121
 
122
+ [<tt>--suppress-backtrace _pattern_ </tt>]
123
+ Line matching the regular expression _pattern_ will be removed
124
+ from the backtrace output. Note that the --backtrace option is the
125
+ full backtrace without these lines suppressed.
126
+
84
127
  [<tt>--system</tt> (-g)]
85
128
  Use the system wide (global) rakefiles. The project Rakefile is
86
129
  ignored. By default, the system wide rakefiles are used only if no
@@ -97,16 +140,6 @@ Options are:
97
140
  are defined using the "desc" command. If a pattern is given, then
98
141
  only tasks matching the pattern are displayed.
99
142
 
100
- [<tt>--no-top-level-dsl</tt> (-X)]
101
- Do not put the Rake DSL commands into the top level scope.
102
-
103
- [<tt>--top-level-dsl</tt>]
104
- Put the Rake DSL commands into the top level scope (default).
105
-
106
- NOTE: Although currently Rake defaults to its DSL in the top level
107
- scope, the plan is to deprecate this in the future and default ot
108
- having the DSL commands *not* appear in the top level scope.
109
-
110
143
  [<tt>--trace</tt> (-t)]
111
144
  Turn on invoke/execute tracing. Also enable full backtrace on
112
145
  errors.
@@ -119,7 +152,11 @@ Options are:
119
152
 
120
153
  [<tt>--where</tt> <em>pattern</em> (-W)]
121
154
  Display tasks that match <em>pattern</em> and the file and line
122
- number where the task is defined.
155
+ number where the task is defined. By default this option will
156
+ display all tasks, not just the tasks that have descriptions.
157
+
158
+ [<tt>--no-deprecation-warnings</tt> (-W)]
159
+ Do not display the deprecation warnings.
123
160
 
124
161
  In addition, any command line option of the form
125
162
  <em>VAR</em>=<em>VALUE</em> will be added to the environment hash
@@ -0,0 +1,55 @@
1
+ = Rake 0.9.3 Released
2
+
3
+ Rake version 0.9.3 is mainly bug fixes.
4
+
5
+ == Changes
6
+
7
+ * The rake test loader now removes arguments it has processed. Issue #51
8
+ * Rake::TaskArguments now responds to #values_at
9
+ * RakeFileUtils.verbose_flag = nil silences output the same as 0.8.7
10
+ * Rake tests are now directory-independent
11
+ * Rake tests are no longer require flexmock
12
+ * Commands constant is no longer polluting top level namespace.
13
+ * Show only the interesting portion of the backtrace by default (James M. Lawrence).
14
+ * Added --reduce-compat option to remove backward compatible DSL hacks (James M. Lawrence).
15
+
16
+ == What is Rake
17
+
18
+ Rake is a build tool similar to the make program in many ways. But
19
+ instead of cryptic make recipes, Rake uses standard Ruby code to
20
+ declare tasks and dependencies. You have the full power of a modern
21
+ scripting language built right into your build tool.
22
+
23
+ == Availability
24
+
25
+ The easiest way to get and install rake is via RubyGems ...
26
+
27
+ gem install rake (you may need root/admin privileges)
28
+
29
+ Otherwise, you can get it from the more traditional places:
30
+
31
+ Home Page:: http://rake.rubyforge.org/
32
+ Download:: http://rubyforge.org/project/showfiles.php?group_id=50
33
+ GitHub:: git://github.com/jimweirich/rake.git
34
+
35
+ == Thanks
36
+
37
+ As usual, it was input from users that drove a alot of these changes. The
38
+ following people either contributed patches, made suggestions or made
39
+ otherwise helpful comments. Thanks to ...
40
+
41
+ * James M. Lawrence (quix)
42
+ * Roger Pack
43
+ * Cezary Baginski
44
+ * Sean Scot August Moon
45
+ * R.T. Lechow
46
+ * Alex Chaffee
47
+ * James Tucker
48
+ * Matthias Lüdtke
49
+ * Santiago Pastorino
50
+
51
+ Also, bit thanks to Eric Hodel for assisting with getting this release
52
+ out the door (where "assisting" includes, but is not by any means
53
+ limited to, "pushing" me to get it done).
54
+
55
+ -- Jim Weirich
@@ -1,17 +1,59 @@
1
1
  = Rake 0.9.3 Released
2
2
 
3
- Rake version 0.9.3 is mainly bug fixes.
3
+ Rake version 0.9.3 contains some new, backwards compatible features and
4
+ a number of bug fixes.
4
5
 
5
6
  == Changes
6
7
 
7
- * The rake test loader now removes arguments it has processed. Issue #51
8
- * Rake::TaskArguments now responds to #values_at
9
- * RakeFileUtils.verbose_flag = nil silences output the same as 0.8.7
10
- * Rake tests are now directory-independent
11
- * Rake tests are no longer require flexmock
12
- * Commands constant is no longer polluting top level namespace.
13
- * Show only the interesting portion of the backtrace by default (James M. Lawrence).
14
- * Added --reduce-compat optiont to remove backward compatible DSL hacks (James M. Lawrence).
8
+ === New Features
9
+
10
+ * Multitask tasks now use a thread pool. Use -j to limit the number of
11
+ available threads.
12
+
13
+ * Use -m to turn regular tasks into multitasks (use at your own risk).
14
+
15
+ * You can now do "Rake.add_rakelib 'dir'" in your Rakefile to
16
+ programatically add rake task libraries.
17
+
18
+ * You can specific backtrace suppression patterns (see
19
+ --supress-backtrace)
20
+
21
+ * Directory tasks can now take prerequisites and actions
22
+
23
+ * Use --backtrace to request a full backtrace without the task trace.
24
+
25
+ * You can say "--backtrace=stdout" and "--trace=stdout" to route trace
26
+ output to standard output rather than standard error.
27
+
28
+ * Optional 'phony' target (enable with 'require 'rake/phony'") for
29
+ special purpose builds.
30
+
31
+ * Task#clear now clears task comments as well as actions and
32
+ prerequisites. Task#clear_comment will specifically target comments.
33
+
34
+ * The --all option will force -T and -D to consider all the tasks,
35
+ with and without descriptions.
36
+
37
+ === Bug Fixes
38
+
39
+ * Semi-colons in windows rakefile paths now work.
40
+
41
+ * Improved Control-C support when invoking multiple test suites.
42
+
43
+ * egrep method now reads files in text mode (better support for
44
+ Windows)
45
+
46
+ * Better deprecation line number reporting.
47
+
48
+ * The -W option now works with all tasks, whether they have a
49
+ description or not.
50
+
51
+ * File globs in rake should not be sorted alphabetically, independent
52
+ of file system and platform.
53
+
54
+ * Numerous internal improvements.
55
+
56
+ * Documentation typos and fixes.
15
57
 
16
58
  == What is Rake
17
59
 
@@ -28,7 +70,7 @@ The easiest way to get and install rake is via RubyGems ...
28
70
 
29
71
  Otherwise, you can get it from the more traditional places:
30
72
 
31
- Home Page:: http://rake.rubyforge.org/
73
+ Home Page:: http://github.com/jimweirich/rake
32
74
  Download:: http://rubyforge.org/project/showfiles.php?group_id=50
33
75
  GitHub:: git://github.com/jimweirich/rake.git
34
76
 
@@ -38,18 +80,23 @@ As usual, it was input from users that drove a alot of these changes. The
38
80
  following people either contributed patches, made suggestions or made
39
81
  otherwise helpful comments. Thanks to ...
40
82
 
41
- * James M. Lawrence (quix)
42
- * Roger Pack
43
- * Cezary Baginski
44
- * Sean Scot August Moon
45
- * R.T. Lechow
46
- * Alex Chaffee
47
- * James Tucker
48
- * Matthias Lüdtke
49
- * Santiago Pastorino
50
-
51
- Also, bit thanks to Eric Hodel for assisting with getting this release
52
- out the door (where "assisting" includes, but is not by any means
53
- limited to, "pushing" me to get it done).
83
+ * Aaron Patterson
84
+ * Dylan Smith
85
+ * Jo Liss
86
+ * Jonas Pfenniger
87
+ * Kazuki Tsujimoto
88
+ * Michael Bishop
89
+ * Michael Elufimov
90
+ * NAKAMURA Usaku
91
+ * Ryan Davis
92
+ * Sam Grönblom
93
+ * Sam Phippen
94
+ * Sergio Wong
95
+ * Tay Ray Chuan
96
+ * grosser
97
+ * quix
98
+
99
+ Also, many thanks to Eric Hodel for assisting with getting this release
100
+ out the door.
54
101
 
55
102
  -- Jim Weirich
@@ -58,7 +58,7 @@ module Rake
58
58
  #
59
59
  # * Initialize the command line options (+init+).
60
60
  # * Define the tasks (+load_rakefile+).
61
- # * Run the top level tasks (+run_tasks+).
61
+ # * Run the top level tasks (+top_level+).
62
62
  #
63
63
  # If you wish to build a custom rake command, you should call
64
64
  # +init+ on your application. Then define any tasks. Finally,
@@ -67,15 +67,7 @@ module Rake
67
67
  standard_exception_handling do
68
68
  init
69
69
  load_rakefile
70
- thread_pool.gather_history if options.job_stats == :history
71
70
  top_level
72
- thread_pool.join
73
- if options.job_stats
74
- stats = thread_pool.statistics
75
- puts "Maximum active threads: #{stats[:max_active_threads]}"
76
- puts "Total threads in play: #{stats[:total_threads_in_play]}"
77
- end
78
- ThreadHistoryDisplay.new(thread_pool.history).show if options.job_stats == :history
79
71
  end
80
72
  end
81
73
 
@@ -97,13 +89,30 @@ module Rake
97
89
 
98
90
  # Run the top level tasks of a Rake application.
99
91
  def top_level
100
- if options.show_tasks
101
- display_tasks_and_comments
102
- elsif options.show_prereqs
103
- display_prerequisites
104
- else
105
- top_level_tasks.each { |task_name| invoke_task(task_name) }
92
+ run_with_threads do
93
+ if options.show_tasks
94
+ display_tasks_and_comments
95
+ elsif options.show_prereqs
96
+ display_prerequisites
97
+ else
98
+ top_level_tasks.each { |task_name| invoke_task(task_name) }
99
+ end
100
+ end
101
+ end
102
+
103
+ # Run the given block with the thread startup and shutdown.
104
+ def run_with_threads
105
+ thread_pool.gather_history if options.job_stats == :history
106
+
107
+ yield
108
+
109
+ thread_pool.join
110
+ if options.job_stats
111
+ stats = thread_pool.statistics
112
+ puts "Maximum active threads: #{stats[:max_active_threads]}"
113
+ puts "Total threads in play: #{stats[:total_threads_in_play]}"
106
114
  end
115
+ ThreadHistoryDisplay.new(thread_pool.history).show if options.job_stats == :history
107
116
  end
108
117
 
109
118
  # Add a loader to handle imported files ending in the extension
@@ -5,8 +5,9 @@ module Rake
5
5
  keys.grep(/(prefix|libdir)/)) + [
6
6
  File.join(File.dirname(__FILE__), ".."),
7
7
  ].map { |f| Regexp.quote(File.expand_path(f)) }
8
+ SUPPRESSED_PATHS.reject! { |s| s.nil? || s =~ /^ *$/ }
8
9
 
9
- SUPPRESS_PATTERN = %r!(\A#{SUPPRESSED_PATHS.join('|')}|bin/rake:\d+)!
10
+ SUPPRESS_PATTERN = %r!(\A#{SUPPRESSED_PATHS.join('|')}|bin/rake:\d+)!i
10
11
 
11
12
  def self.collapse(backtrace)
12
13
  pattern = Rake.application.options.suppress_backtrace_pattern ||
@@ -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
@@ -11,4 +11,3 @@ class Time
11
11
  end
12
12
  end
13
13
  end
14
-
@@ -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
data/lib/rake/task.rb CHANGED
@@ -196,7 +196,7 @@ module Rake
196
196
  application[r, @scope].invoke_with_call_chain(args, invocation_chain)
197
197
  end
198
198
  end
199
- futures.each { |f| f.call }
199
+ futures.each { |f| f.value }
200
200
  end
201
201
 
202
202
  # Format the trace flags for display.
@@ -1,8 +1,11 @@
1
+ require 'rake/private_reader'
2
+
1
3
  module Rake
2
4
 
3
- class ThreadHistoryDisplay
4
- attr_reader :stats, :items, :threads
5
- private :stats, :items, :threads
5
+ class ThreadHistoryDisplay # :nodoc: all
6
+ include Rake::PrivateReader
7
+
8
+ private_reader :stats, :items, :threads
6
9
 
7
10
  def initialize(stats)
8
11
  @stats = stats
@@ -13,7 +16,7 @@ module Rake
13
16
  def show
14
17
  puts "Job History:"
15
18
  stats.each do |stat|
16
- stat[:data] ||= []
19
+ stat[:data] ||= {}
17
20
  rename(stat, :thread, threads)
18
21
  rename(stat[:data], :item_id, items)
19
22
  rename(stat[:data], :new_thread, threads)
@@ -1,6 +1,8 @@
1
1
  require 'thread'
2
2
  require 'set'
3
3
 
4
+ require 'rake/promise'
5
+
4
6
  module Rake
5
7
 
6
8
  class ThreadPool # :nodoc: all
@@ -28,63 +30,12 @@ module Rake
28
30
  # pool. Sending <tt>#value</tt> to the object will sleep the
29
31
  # current thread until the future is finished and will return the
30
32
  # result (or raise an exception thrown from the future)
31
- def future(*args,&block)
32
- # capture the local args for the block (like Thread#start)
33
- local_args = args.collect { |a| begin; a.dup; rescue; a; end }
34
-
35
- promise_mutex = Mutex.new
36
- promise_result = promise_error = NOT_SET
37
-
38
- # (promise code builds on Ben Lavender's public-domain 'promise' gem)
39
- promise = lambda do
40
- # return immediately if the future has been executed
41
- unless promise_result.equal?(NOT_SET) && promise_error.equal?(NOT_SET)
42
- return promise_error.equal?(NOT_SET) ? promise_result : raise(promise_error)
43
- end
44
-
45
- # try to get the lock and execute the promise, otherwise, sleep.
46
- if promise_mutex.try_lock
47
- if promise_result.equal?(NOT_SET) && promise_error.equal?(NOT_SET)
48
- #execute the promise
49
- begin
50
- promise_result = block.call(*local_args)
51
- rescue Exception => e
52
- promise_error = e
53
- end
54
- block = local_args = nil # GC can now clean these up
55
- end
56
- promise_mutex.unlock
57
- else
58
- # Even if we didn't get the lock, we need to sleep until the
59
- # promise has finished executing. If, however, the current
60
- # thread is part of the thread pool, we need to free up a
61
- # new thread in the pool so there will always be a thread
62
- # doing work.
63
-
64
- wait_for_promise = lambda {
65
- stat :waiting, item_id: promise.object_id
66
- promise_mutex.synchronize {}
67
- stat :continue, item_id: promise.object_id
68
- }
69
-
70
- unless @threads_mon.synchronize { @threads.include? Thread.current }
71
- wait_for_promise.call
72
- else
73
- @threads_mon.synchronize { @max_active_threads += 1 }
74
- start_thread
75
- wait_for_promise.call
76
- @threads_mon.synchronize { @max_active_threads -= 1 }
77
- end
78
- end
79
- promise_error.equal?(NOT_SET) ? promise_result : raise(promise_error)
80
- end
81
-
82
- def promise.value
83
- call
84
- end
33
+ def future(*args, &block)
34
+ promise = Promise.new(args, &block)
35
+ promise.recorder = lambda { |*stats| stat(*stats) }
85
36
 
86
37
  @queue.enq promise
87
- stat :item_queued, item_id: promise.object_id
38
+ stat :queued, :item_id => promise.object_id
88
39
  start_thread
89
40
  promise
90
41
  end
@@ -93,14 +44,18 @@ module Rake
93
44
  def join
94
45
  @threads_mon.synchronize do
95
46
  begin
96
- @join_cond.wait unless @threads.empty?
47
+ stat :joining
48
+ @join_cond.wait unless @threads.empty?
49
+ stat :joined
97
50
  rescue Exception => e
51
+ stat :joined
98
52
  $stderr.puts e
99
53
  $stderr.print "Queue contains #{@queue.size} items. Thread pool contains #{@threads.count} threads\n"
100
54
  $stderr.print "Current Thread #{Thread.current} status = #{Thread.current.status}\n"
101
55
  $stderr.puts e.backtrace.join("\n")
102
56
  @threads.each do |t|
103
57
  $stderr.print "Thread #{t} status = #{t.status}\n"
58
+ # 1.8 doesn't support Thread#backtrace
104
59
  $stderr.puts t.backtrace.join("\n") if t.respond_to? :backtrace
105
60
  end
106
61
  raise e
@@ -119,45 +74,58 @@ module Rake
119
74
  # (see #gather_history). Best to call this when the job is
120
75
  # complete (i.e. after ThreadPool#join is called).
121
76
  def history # :nodoc:
122
- @history_mon.synchronize { @history.dup }
77
+ @history_mon.synchronize { @history.dup }.
78
+ sort_by { |i| i[:time] }.
79
+ each { |i| i[:time] -= @history_start_time }
123
80
  end
124
81
 
125
82
  # Return a hash of always collected statistics for the thread pool.
126
83
  def statistics # :nodoc:
127
84
  {
128
- total_threads_in_play: @total_threads_in_play,
129
- max_active_threads: @max_active_threads,
85
+ :total_threads_in_play => @total_threads_in_play,
86
+ :max_active_threads => @max_active_threads,
130
87
  }
131
88
  end
132
89
 
133
90
  private
134
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
+
135
110
  def start_thread # :nodoc:
136
111
  @threads_mon.synchronize do
137
112
  next unless @threads.count < @max_active_threads
138
113
 
139
114
  t = Thread.new do
140
115
  begin
141
- while @threads.count <= @max_active_threads && !@queue.empty? do
142
- # Even though we just asked if the queue was empty, it
143
- # still could have had an item which by this statement
144
- # is now gone. For this reason we pass true to Queue#deq
145
- # because we will sleep indefinitely if it is empty.
146
- block = @queue.deq(true)
147
- stat :item_dequeued, item_id: block.object_id
148
- block.call
116
+ while @threads.count <= @max_active_threads
117
+ break unless process_queue_item
149
118
  end
150
- rescue ThreadError # this means the queue is empty
151
119
  ensure
152
120
  @threads_mon.synchronize do
153
121
  @threads.delete Thread.current
154
- stat :thread_deleted, deleted_thread: Thread.current.object_id, thread_count: @threads.count
122
+ stat :ended, :thread_count => @threads.count
155
123
  @join_cond.broadcast if @threads.empty?
156
124
  end
157
125
  end
158
126
  end
159
127
  @threads << t
160
- stat :thread_created, new_thread: t.object_id, thread_count: @threads.count
128
+ stat :spawned, :new_thread => t.object_id, :thread_count => @threads.count
161
129
  @total_threads_in_play = @threads.count if @threads.count > @total_threads_in_play
162
130
  end
163
131
  end
@@ -165,10 +133,10 @@ module Rake
165
133
  def stat(event, data=nil) # :nodoc:
166
134
  return if @history_start_time.nil?
167
135
  info = {
168
- event: event,
169
- data: data,
170
- time: (Time.now-@history_start_time),
171
- thread: Thread.current.object_id,
136
+ :event => event,
137
+ :data => data,
138
+ :time => Time.now,
139
+ :thread => Thread.current.object_id,
172
140
  }
173
141
  @history_mon.synchronize { @history << info }
174
142
  end
@@ -182,8 +150,6 @@ module Rake
182
150
  def __threads__ # :nodoc:
183
151
  @threads.dup
184
152
  end
185
-
186
- NOT_SET = Object.new.freeze # :nodoc:
187
153
  end
188
154
 
189
155
  end
data/lib/rake/version.rb CHANGED
@@ -5,7 +5,7 @@ module Rake
5
5
  MINOR = 9,
6
6
  BUILD = 3,
7
7
  'beta',
8
- BETA = 3,
8
+ BETA = 4,
9
9
  ]
10
10
  end
11
11
  VERSION = Version::NUMBERS.join('.')
@@ -0,0 +1,42 @@
1
+ require File.expand_path('../helper', __FILE__)
2
+ require 'rake/private_reader'
3
+
4
+ class TestPrivateAttrs < Rake::TestCase
5
+
6
+ class Sample
7
+ include Rake::PrivateReader
8
+
9
+ private_reader :reader, :a
10
+
11
+ def initialize
12
+ @reader = :RVALUE
13
+ end
14
+
15
+ def get_reader
16
+ reader
17
+ end
18
+
19
+ end
20
+
21
+ def setup
22
+ super
23
+ @sample = Sample.new
24
+ end
25
+
26
+ def test_private_reader_is_private
27
+ assert_private do @sample.reader end
28
+ assert_private do @sample.a end
29
+ end
30
+
31
+ def test_private_reader_returns_data
32
+ assert_equal :RVALUE, @sample.get_reader
33
+ end
34
+
35
+ private
36
+
37
+ def assert_private
38
+ ex = assert_raises(NoMethodError) do yield end
39
+ assert_match(/private/, ex.message)
40
+ end
41
+
42
+ end
@@ -498,4 +498,3 @@ class TestRakeApplication < Rake::TestCase
498
498
  end
499
499
 
500
500
  end
501
-
@@ -24,8 +24,8 @@ class TestRakeBacktrace < Rake::TestCase
24
24
 
25
25
  assert_equal "rake aborted!", lines[0]
26
26
  assert_equal "foooo!", lines[1]
27
- assert_match %r!\A#{Regexp.quote Dir.pwd}/Rakefile:3!, lines[2]
28
- assert_match %r!\ATasks:!, lines[3]
27
+ assert_something_matches %r!\A#{Regexp.quote Dir.pwd}/Rakefile:3!i, lines
28
+ assert_something_matches %r!\ATasks:!, lines
29
29
  end
30
30
 
31
31
  def test_multi_collapse
@@ -42,9 +42,9 @@ class TestRakeBacktrace < Rake::TestCase
42
42
 
43
43
  assert_equal "rake aborted!", lines[0]
44
44
  assert_equal "barrr!", lines[1]
45
- assert_match %r!\A#{Regexp.quote Dir.pwd}/Rakefile:6!, lines[2]
46
- assert_match %r!\A#{Regexp.quote Dir.pwd}/Rakefile:3!, lines[3]
47
- assert_match %r!\ATasks:!, lines[4]
45
+ assert_something_matches %r!\A#{Regexp.quote Dir.pwd}/Rakefile:6!i, lines
46
+ assert_something_matches %r!\A#{Regexp.quote Dir.pwd}/Rakefile:3!i, lines
47
+ assert_something_matches %r!\ATasks:!, lines
48
48
  end
49
49
 
50
50
  def test_suppress_option
@@ -57,11 +57,25 @@ class TestRakeBacktrace < Rake::TestCase
57
57
  lines = rake("baz").split("\n")
58
58
  assert_equal "rake aborted!", lines[0]
59
59
  assert_equal "bazzz!", lines[1]
60
- assert_match %r!Rakefile!, lines[2]
60
+ assert_something_matches %r!Rakefile!i, lines
61
61
 
62
- lines = rake("--suppress-backtrace", "R.k.file", "baz").split("\n")
62
+ lines = rake("--suppress-backtrace", ".ak.file", "baz").split("\n")
63
63
  assert_equal "rake aborted!", lines[0]
64
64
  assert_equal "bazzz!", lines[1]
65
- refute_match %r!Rakefile!, lines[2]
65
+ refute_match %r!Rakefile!i, lines[2]
66
66
  end
67
+
68
+ private
69
+
70
+ # Assert that the pattern matches at least one line in +lines+.
71
+ def assert_something_matches(pattern, lines)
72
+ lines.each do |ln|
73
+ if pattern =~ ln
74
+ assert_match pattern, ln
75
+ return
76
+ end
77
+ end
78
+ flunk "expected #{pattern.inspect} to match something in:\n #{lines.join("\n ")}"
79
+ end
80
+
67
81
  end
@@ -69,7 +69,7 @@ class TestRakeTestThreadPool < Rake::TestCase
69
69
  }
70
70
 
71
71
  pool.join
72
- assert_equal true, pool.__send__(:__queue__).empty?
72
+ assert_equal true, pool.__send__(:__queue__).empty?, "queue should be empty"
73
73
  end
74
74
 
75
75
  # test that throwing an exception way down in the blocks propagates
@@ -88,29 +88,6 @@ class TestRakeTestThreadPool < Rake::TestCase
88
88
 
89
89
  end
90
90
 
91
- def test_pool_always_has_max_threads_doing_work
92
- # here we need to test that even if some threads are halted, there
93
- # are always at least max_threads that are not sleeping.
94
- pool = ThreadPool.new(2)
95
- initial_sleep_time = 0.2
96
- future1 = pool.future { sleep initial_sleep_time }
97
- dependent_futures = 5.times.collect { pool.future{ future1.value } }
98
- future2 = pool.future { sleep initial_sleep_time }
99
- future3 = pool.future { sleep 0.01 }
100
-
101
- sleep initial_sleep_time / 2.0 # wait for everything to queue up
102
-
103
- # at this point, we should have 5 threads sleeping depending on future1, and
104
- # two threads doing work on future1 and future 2.
105
- assert_equal pool.__send__(:__threads__).count, 7
106
-
107
- # future 3 is in the queue because there aren't enough active threads to work on it.
108
- assert_equal pool.__send__(:__queue__).size, 1
109
-
110
- [future1, dependent_futures, future2, future3].flatten.each { |f| f.value }
111
- pool.join
112
- end
113
-
114
91
  def test_pool_prevents_deadlock
115
92
  pool = ThreadPool.new(5)
116
93
 
@@ -18,7 +18,7 @@ class TestThreadHistoryDisplay < Rake::TestCase
18
18
  end
19
19
 
20
20
  def test_item_queued
21
- @stats << event(:item_queued, item_id: 123)
21
+ @stats << event(:item_queued, :item_id => 123)
22
22
  out, _ = capture_io do
23
23
  @display.show
24
24
  end
@@ -26,7 +26,7 @@ class TestThreadHistoryDisplay < Rake::TestCase
26
26
  end
27
27
 
28
28
  def test_item_dequeued
29
- @stats << event(:item_dequeued, item_id: 123)
29
+ @stats << event(:item_dequeued, :item_id => 123)
30
30
  out, _ = capture_io do
31
31
  @display.show
32
32
  end
@@ -34,8 +34,8 @@ class TestThreadHistoryDisplay < Rake::TestCase
34
34
  end
35
35
 
36
36
  def test_multiple_items
37
- @stats << event(:item_queued, item_id: 123)
38
- @stats << event(:item_queued, item_id: 124)
37
+ @stats << event(:item_queued, :item_id => 123)
38
+ @stats << event(:item_queued, :item_id => 124)
39
39
  out, _ = capture_io do
40
40
  @display.show
41
41
  end
@@ -44,7 +44,7 @@ class TestThreadHistoryDisplay < Rake::TestCase
44
44
  end
45
45
 
46
46
  def test_waiting
47
- @stats << event(:waiting, item_id: 123)
47
+ @stats << event(:waiting, :item_id => 123)
48
48
  out, _ = capture_io do
49
49
  @display.show
50
50
  end
@@ -52,7 +52,7 @@ class TestThreadHistoryDisplay < Rake::TestCase
52
52
  end
53
53
 
54
54
  def test_continue
55
- @stats << event(:continue, item_id: 123)
55
+ @stats << event(:continue, :item_id => 123)
56
56
  out, _ = capture_io do
57
57
  @display.show
58
58
  end
@@ -60,29 +60,29 @@ class TestThreadHistoryDisplay < Rake::TestCase
60
60
  end
61
61
 
62
62
  def test_thread_deleted
63
- @stats << event(:thread_deleted, deleted_thread: 123456, thread_count: 12)
63
+ @stats << event(:thread_deleted, :deleted_thread => 123456, :thread_count => 12)
64
64
  out, _ = capture_io do
65
65
  @display.show
66
66
  end
67
- assert_match(/^ *1000000 +A +thread_deleted +deleted_thread:B +thread_count:12$/, out)
67
+ assert_match(/^ *1000000 +A +thread_deleted( +deleted_thread:B| +thread_count:12){2}$/, out)
68
68
  end
69
69
 
70
70
  def test_thread_created
71
- @stats << event(:thread_created, new_thread: 123456, thread_count: 13)
71
+ @stats << event(:thread_created, :new_thread => 123456, :thread_count => 13)
72
72
  out, _ = capture_io do
73
73
  @display.show
74
74
  end
75
- assert_match(/^ *1000000 +A +thread_created +new_thread:B +thread_count:13$/, out)
75
+ assert_match(/^ *1000000 +A +thread_created( +new_thread:B| +thread_count:13){2}$/, out)
76
76
  end
77
77
 
78
78
  private
79
79
 
80
80
  def event(type, data={})
81
81
  result = {
82
- event: type,
83
- time: @time / 1_000_000.0,
84
- data: data,
85
- thread: Thread.current.object_id
82
+ :event => type,
83
+ :time => @time / 1_000_000.0,
84
+ :data => data,
85
+ :thread => Thread.current.object_id
86
86
  }
87
87
  @time += 1
88
88
  result
metadata CHANGED
@@ -1,27 +1,28 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rake
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.3.beta.3
5
4
  prerelease: 6
5
+ version: !binary |-
6
+ MC45LjMuYmV0YS40
6
7
  platform: ruby
7
8
  authors:
8
9
  - Jim Weirich
9
10
  autorequire:
10
11
  bindir: bin
11
12
  cert_chain: []
12
- date: 2012-10-25 00:00:00.000000000 Z
13
+ date: 2012-11-09 00:00:00.000000000 Z
13
14
  dependencies:
14
15
  - !ruby/object:Gem::Dependency
15
- name: minitest
16
- requirement: !ruby/object:Gem::Requirement
16
+ type: :development
17
+ version_requirements: !ruby/object:Gem::Requirement
17
18
  none: false
18
19
  requirements:
19
20
  - - ~>
20
21
  - !ruby/object:Gem::Version
21
22
  version: '2.1'
22
- type: :development
23
23
  prerelease: false
24
- version_requirements: !ruby/object:Gem::Requirement
24
+ name: minitest
25
+ requirement: !ruby/object:Gem::Requirement
25
26
  none: false
26
27
  requirements:
27
28
  - - ~>
@@ -62,6 +63,7 @@ extra_rdoc_files:
62
63
  - doc/release_notes/rake-0.8.7.rdoc
63
64
  - doc/release_notes/rake-0.9.0.rdoc
64
65
  - doc/release_notes/rake-0.9.1.rdoc
66
+ - doc/release_notes/rake-0.9.2.2.rdoc
65
67
  - doc/release_notes/rake-0.9.2.rdoc
66
68
  - doc/release_notes/rake-0.9.3.rdoc
67
69
  files:
@@ -107,6 +109,8 @@ files:
107
109
  - lib/rake/packagetask.rb
108
110
  - lib/rake/pathmap.rb
109
111
  - lib/rake/phony.rb
112
+ - lib/rake/private_reader.rb
113
+ - lib/rake/promise.rb
110
114
  - lib/rake/pseudo_status.rb
111
115
  - lib/rake/rake_module.rb
112
116
  - lib/rake/rake_test_loader.rb
@@ -126,6 +130,7 @@ files:
126
130
  - lib/rake/win32.rb
127
131
  - test/file_creation.rb
128
132
  - test/helper.rb
133
+ - test/test_private_reader.rb
129
134
  - test/test_rake.rb
130
135
  - test/test_rake_application.rb
131
136
  - test/test_rake_application_options.rb
@@ -201,6 +206,7 @@ files:
201
206
  - doc/release_notes/rake-0.8.7.rdoc
202
207
  - doc/release_notes/rake-0.9.0.rdoc
203
208
  - doc/release_notes/rake-0.9.1.rdoc
209
+ - doc/release_notes/rake-0.9.2.2.rdoc
204
210
  - doc/release_notes/rake-0.9.2.rdoc
205
211
  - doc/release_notes/rake-0.9.3.rdoc
206
212
  homepage: http://rake.rubyforge.org