lib/rake.rb in drake-0.8.2.1.0.4 vs lib/rake.rb in drake-0.8.2.1.0.5
- old
+ new
@@ -27,11 +27,11 @@
#
# This is the main file for the Rake application. Normally it is referenced
# as a library via a require statement, but it can be distributed
# independently as an application.
-RAKEVERSION = '0.8.2.1.0.4'
+RAKEVERSION = '0.8.2.1.0.5'
require 'rbconfig'
require 'getoptlong'
require 'fileutils'
require 'singleton'
@@ -561,27 +561,27 @@
def clear_actions
actions.clear
self
end
+ def base_invoke(*args) #:nodoc:
+ invoke_with_call_chain(
+ TaskArguments.new(arg_names, args),
+ InvocationChain::EMPTY)
+ end
+
# Invoke the task if it is needed. Prerequites are invoked first.
def invoke(*args)
- run_invoke = lambda {
- invoke_with_call_chain(
- TaskArguments.new(arg_names, args),
- InvocationChain::EMPTY)
- }
-
if application.num_threads == 1
- run_invoke.call
+ base_invoke(*args)
else
if application.parallel_lock.locked?
raise "Calling Task#invoke within a task is not allowed."
end
application.parallel_lock.synchronize {
application.parallel_tasks.clear
- run_invoke.call
+ base_invoke(*args)
application.invoke_parallel_tasks
}
end
end
@@ -593,12 +593,17 @@
if application.options.trace and application.num_threads == 1
puts "** Invoke #{name} #{format_trace_flags}"
end
return if @already_invoked
@already_invoked = true
- prereqs = application.num_threads == 1 ? nil : Array.new
- invoke_prerequisites(task_args, new_chain, prereqs)
+ prereqs =
+ if application.num_threads == 1
+ invoke_prerequisites(task_args, new_chain)
+ nil
+ else
+ invoke_prerequisites_parallel(task_args, new_chain)
+ end
if needed?
if application.num_threads == 1
execute(task_args)
else
# gather tasks for batch execution
@@ -607,20 +612,32 @@
end
end
end
protected :invoke_with_call_chain
+ def invoke_prerequisite(prereq_name, task_args, invocation_chain) #:nodoc:
+ prereq = application[prereq_name, @scope]
+ prereq_args = task_args.new_scope(prereq.arg_names)
+ prereq.invoke_with_call_chain(prereq_args, invocation_chain)
+ prereq
+ end
+
# Invoke all the prerequisites of a task.
- def invoke_prerequisites(task_args, invocation_chain, accum=nil) #:nodoc:
+ def invoke_prerequisites(task_args, invocation_chain) # :nodoc:
@prerequisites.each { |n|
- prereq = application[n, @scope]
- prereq_args = task_args.new_scope(prereq.arg_names)
- prereq.invoke_with_call_chain(prereq_args, invocation_chain)
- accum << prereq if accum
+ invoke_prerequisite(n, task_args, invocation_chain)
}
end
+ # Parallel dry-run accumulator.
+ # This also serves to circumvent MultiTask#invoke_prerequisites.
+ def invoke_prerequisites_parallel(task_args, invocation_chain) #:nodoc:
+ @prerequisites.map { |n|
+ invoke_prerequisite(n, task_args, invocation_chain)
+ }
+ end
+
# Format the trace flags for display.
def format_trace_flags
flags = []
flags << "first_time" unless @already_invoked
flags << "not_needed" unless needed?
@@ -765,14 +782,10 @@
end
end # class << Rake::Task
end # class Rake::Task
- #
- # DEPRECATED: do not use MultiTask
- #
- MultiTask = Task
# #########################################################################
# A FileTask is a task that includes time based dependencies. If any of a
# FileTask's prerequisites have a timestamp that is later than the file
# represented by this task, then the file must be rebuilt (using the
@@ -832,10 +845,23 @@
# than any other time stamp.
def timestamp
Rake::EARLY
end
end
+
+ # #########################################################################
+ # Same as a regular task, but the immediate prerequisites are done in
+ # parallel using Ruby threads.
+ #
+ class MultiTask < Task
+ def invoke_prerequisites(args, invocation_chain)
+ threads = @prerequisites.collect { |p|
+ Thread.new(p) { |r| application[r].invoke_with_call_chain(args, invocation_chain) }
+ }
+ threads.each { |t| t.join }
+ end
+ end
end # module Rake
# ###########################################################################
# Task Definition Functions ...
@@ -848,16 +874,10 @@
#
def task(*args, &block)
Rake::Task.define_task(*args, &block)
end
-#
-# DEPRECATED: Do not use 'multitask'
-#
-def multitask(*args, &block)
- task(*args, &block)
-end
# Declare a file task.
#
# Example:
# file "config.cfg" => ["config.template"] do
@@ -891,10 +911,21 @@
mkdir_p t.name if ! File.exist?(t.name)
end
end
end
+# Declare a task that performs its prerequisites in parallel. Multitasks does
+# *not* guarantee that its prerequisites will execute in any given order
+# (which is obvious when you think about it)
+#
+# Example:
+# multitask :deploy => [:deploy_gem, :deploy_rdoc]
+#
+def multitask(args, &block)
+ Rake::MultiTask.define_task(args, &block)
+end
+
# Create a new rake namespace and use it for evaluating the given block.
# Returns a NameSpace object that can be used to lookup tasks defined in the
# namespace.
#
# E.g.
@@ -1999,25 +2030,9 @@
@top_level_tasks = []
add_loader('rb', DefaultLoader.new)
add_loader('rf', DefaultLoader.new)
add_loader('rake', DefaultLoader.new)
@tty_output = STDOUT.tty?
- end
-
- #
- # Check for circular dependencies, without invoking.
- #
- def check_circular(task_name)
- helper = lambda { |name, chain|
- if chain.include? name
- raise "Circular dependency detected: " +
- "#{name} => #{chain.last} => #{name}"
- end
- Rake::Task[name].prerequisites.each { |prereq_name|
- helper.call(prereq_name, chain + [name])
- }
- }
- helper.call(task_name, [])
end
# Run the Rake application. The run method performs the following three steps:
#
# * Initialize the command line options (+init+).