summaryrefslogtreecommitdiff
path: root/lib/rake/invocation_chain.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/rake/invocation_chain.rb')
-rw-r--r--lib/rake/invocation_chain.rb51
1 files changed, 51 insertions, 0 deletions
diff --git a/lib/rake/invocation_chain.rb b/lib/rake/invocation_chain.rb
new file mode 100644
index 0000000000..8a01ab4c29
--- /dev/null
+++ b/lib/rake/invocation_chain.rb
@@ -0,0 +1,51 @@
+module Rake
+
+ ####################################################################
+ # InvocationChain tracks the chain of task invocations to detect
+ # circular dependencies.
+ class InvocationChain
+ def initialize(value, tail)
+ @value = value
+ @tail = tail
+ end
+
+ def member?(obj)
+ @value == obj || @tail.member?(obj)
+ end
+
+ def append(value)
+ if member?(value)
+ fail RuntimeError, "Circular dependency detected: #{to_s} => #{value}"
+ end
+ self.class.new(value, self)
+ end
+
+ def to_s
+ "#{prefix}#{@value}"
+ end
+
+ def self.append(value, chain)
+ chain.append(value)
+ end
+
+ private
+
+ def prefix
+ "#{@tail.to_s} => "
+ end
+
+ class EmptyInvocationChain
+ def member?(obj)
+ false
+ end
+ def append(value)
+ InvocationChain.new(value, self)
+ end
+ def to_s
+ "TOP"
+ end
+ end
+
+ EMPTY = EmptyInvocationChain.new
+ end
+end