module Rake #:nodoc: class Task def invoke #:nodoc: if stack.include?(name) fail "Circular dependency " + (stack + [name]).join("=>") end @lock.synchronize do if application.options.trace puts "** Invoke #{name} #{format_trace_flags}" end return if @already_invoked begin stack.push name @already_invoked = true invoke_prerequisites execute if needed? ensure stack.pop end end end def invoke_prerequisites() #:nodoc: prerequisites.each { |n| application[n, @scope].invoke } end protected def stack() Thread.current[:rake_stack] ||= [] end end class MultiTask def invoke_prerequisites threads = @prerequisites.collect do |p| copy = stack.dup Thread.new(p) { |r| stack.replace copy ; application[r].invoke } end threads.each { |t| t.join } end end class Application #:nodoc: def in_namespace_with_global_scope(name, &block) if name =~ /^:/ begin scope, @scope = @scope, name.split(":")[1...-1] in_namespace_without_global_scope name.split(":").last, &block ensure @scope = scope end else in_namespace_without_global_scope name, &block end end alias_method_chain :in_namespace, :global_scope end class CheckTask < Rake::Task def execute() @warnings = [] super report if verbose end def note(*msg) @warnings += msg end def report() if @warnings.empty? puts HighLine.new.color("No warnings", :green) else warn "These are possible problems with your Rakefile" @warnings.each { |msg| warn " #{msg}" } end end end desc "Check your Rakefile for common errors" CheckTask.define_task "check" # Check for circular dependencies task "check" do # Keep track of tasks we already checked, to avoid death circles. checked = {} # The stack keeps track of all the tasks we visit, so we can display the tasks # involved in the circular dependency. expand = lambda do |stack, task| # Already been here, no need to check again, but make sure we're not seeing # the same task twice due to a circular dependency. fail "Circular " + (stack + [task]).join("=>") if stack.include?(task) unless checked[task] checked[task] = true # Variable task may be a Task, but may also be a task name. In the later # case, we need to resolve it into a Task. But it may also be a filename, # pointing to a file that may exist, just not during the check, so we need # this check to avoid dying on "Don't know how to build ..." if real_task = Rake.application.lookup(task, []) one_deeper = stack + [task.to_s] real_task.prerequisites.each { |prereq| expand[one_deeper, prereq.to_s] } end end end Rake.application.tasks.each do |task| expand[ [], task.to_s ] end end end