require "highline" module Kernel def warn_with_color(message) warn_without_color HighLine.new.color(message.to_s, :red) end alias_method_chain :warn, :color end module Buildr module Attributes def self.included(mod) mod.extend(self) end # An inherited attribute gets it value from an instance variable # with the same name. If the value is not set it will defer to the # parent object. If there is no parent object, it will use the # default value; with a block, it evaluates the block by calling # instance_eval on the object. # # For example: # inherited_attr :version # inherited_attr :src_dir, "src" # inherited_attr :java_src_dir do src_dir + "/main/java" def inherited_attr(symbol, default = nil, &block) block ||= proc { default } attr_accessor symbol define_method "#{symbol}_with_inheritence" do unless value = send("#{symbol}_without_inheritence") value = parent ? parent.send(symbol) : self.instance_eval(&block) send "#{symbol}=", value end value end alias_method_chain symbol, :inheritence end end end class Rake::Task def invoke tasks = (Thread.current[:tasks] || []) if tasks.include?(name) fail "Circular dependency " + (tasks + [name]).join("=>") end @lock.synchronize do if application.options.trace puts "** Invoke #{name} #{format_trace_flags}" end return if @already_invoked begin Thread.current[:tasks] = tasks + [name] @already_invoked = true invoke_prerequisites execute if needed? ensure Thread.current[:tasks] = tasks end end end end class Rake::Task # Access the base directory. The base directory is set when the class # is defined from the current directory. The current directory is set # to the base directory when the class is executed. attr_accessor :base_dir # :nodoc: def invoke_with_base_dir() Dir.chdir(@base_dir || Dir.pwd) { invoke_without_base_dir } end alias_method_chain :invoke, :base_dir # :nodoc: def initialize_with_base_dir(*args) @base_dir = Dir.pwd initialize_without_base_dir *args end alias_method_chain :initialize, :base_dir end class Rake::Application 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 depends = {} expand = lambda do |stack, checking| if depends[checking] if stack.include?(checking) fail "Circular " + (stack + [checking]).join("=>") end else depends[checking] = [] depends[checking] |= Rake.application[checking].prerequisites. map { |prereq| expand[stack + [checking.to_s], prereq.to_s] }.flatten.map(&:to_s) end depends[checking] end Rake.application.tasks.each do |checking| expand[ [], checking.to_s ] end end