summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2025-02-17 00:12:20 +0200
committerPaul Buetow <paul@buetow.org>2025-02-17 00:12:20 +0200
commited8cf0c0c285abab24479b7af3bc73f2c7340822 (patch)
tree289b123d9da62d90ff8eda8fec5ae83aa5e2363f /lib
parentd64135e44904500d65b029fb31216a52d507a7be (diff)
can detect dependency loop
Diffstat (limited to 'lib')
-rw-r--r--lib/dslkeywords/resource.rb19
1 files changed, 15 insertions, 4 deletions
diff --git a/lib/dslkeywords/resource.rb b/lib/dslkeywords/resource.rb
index 1634061..2320077 100644
--- a/lib/dslkeywords/resource.rb
+++ b/lib/dslkeywords/resource.rb
@@ -40,14 +40,25 @@ module RCM
module DependencyEvaluator
attr_reader :evaluated
+ class DependencyLoop < StandardError; end
+ class UnresolvedDependency < StandardError; end
+
def evaluate!
return false if @evaluated
+ raise DependencyLoop, "Dependency loop detected for #{id}" if @loop_detection
+
+ @loop_detection = true
@depends_on = {} if @depends_on.nil?
- @depends_on.each_key do |id|
- dependency = Resource.find(id)
- end
+ # Try to evaluate all dependencies recursively.
+ @depends_on.each_key.map { Resource.find(_1) }.each(&:evaluate!)
+
+ # Raise an exception when there are still unresolved dependencies.
+ unresolved = @depends_on.each_key.map { Resource.find(_1) }.reject(&:evaluated)
+ raise UnresolvedDependency, "Unresolved dependencies: #{unresolved.map(&:id)}" if unresolved.count.positive?
+
+ @loop_detection = false
@evaluated = true
end
end
@@ -61,7 +72,7 @@ module RCM
def self.find(id)
klass = Object.const_get("RCM::#{id.split('(').first.capitalize}")
- resource = ObjectSpace.each_object(klass).find { |obj| obj.id == id }
+ resource = ObjectSpace.each_object(klass).find { _1.id == id }
raise NoSuchResourceObject, "Unable to find resource #{id}" if resource.nil?
resource