1module Rake 2 3 #################################################################### 4 # InvocationChain tracks the chain of task invocations to detect 5 # circular dependencies. 6 class InvocationChain 7 def initialize(value, tail) 8 @value = value 9 @tail = tail 10 end 11 12 def member?(obj) 13 @value == obj || @tail.member?(obj) 14 end 15 16 def append(value) 17 if member?(value) 18 fail RuntimeError, "Circular dependency detected: #{to_s} => #{value}" 19 end 20 self.class.new(value, self) 21 end 22 23 def to_s 24 "#{prefix}#{@value}" 25 end 26 27 def self.append(value, chain) 28 chain.append(value) 29 end 30 31 private 32 33 def prefix 34 "#{@tail.to_s} => " 35 end 36 37 class EmptyInvocationChain 38 def member?(obj) 39 false 40 end 41 def append(value) 42 InvocationChain.new(value, self) 43 end 44 def to_s 45 "TOP" 46 end 47 end 48 49 EMPTY = EmptyInvocationChain.new 50 end 51end 52