diff --git a/cdist/core/cdist_object.py b/cdist/core/cdist_object.py
index cb34f521..1844aabf 100644
--- a/cdist/core/cdist_object.py
+++ b/cdist/core/cdist_object.py
@@ -213,3 +213,172 @@ class CdistObject(object):
def satisfied_requirements(self):
+
+# -*- coding: utf-8 -*-
+#
+# 2011 Steven Armstrong (steven-cdist at armstrong.cc)
+#
+# This file is part of cdist.
+#
+# cdist is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# cdist is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with cdist. If not, see .
+#
+#
+
+import logging
+import os
+import itertools
+import fnmatch
+
+import cdist
+
+log = logging.getLogger(__name__)
+
+
+class CircularReferenceError(cdist.Error):
+ def __init__(self, cdist_object, required_object):
+ self.cdist_object = cdist_object
+ self.required_object = required_object
+
+ def __str__(self):
+ return 'Circular reference detected: %s -> %s' % (self.cdist_object.name, self.required_object.name)
+
+
+class RequirementNotFoundError(cdist.Error):
+ def __init__(self, requirement):
+ self.requirement = requirement
+
+ def __str__(self):
+ return 'Requirement could not be found: %s' % self.requirement
+
+
+class DependencyResolver(object):
+ """Cdist's dependency resolver.
+
+ Usage:
+ >> resolver = DependencyResolver(list_of_objects)
+ # Easy access to the objects we are working with
+ >> resolver.objects['__some_type/object_id']
+
+ # Easy access to a specific objects dependencies
+ >> resolver.dependencies['__some_type/object_id']
+ [, ]
+ # Pretty print the dependency graph
+ >> from pprint import pprint
+ >> pprint(resolver.dependencies)
+ # Iterate over all existing objects in the correct order
+ >> for cdist_object in resolver:
+ >> do_something_with(cdist_object)
+ """
+ def __init__(self, objects, logger=None):
+ self.objects = dict((o.name, o) for o in objects)
+ self._dependencies = None
+ self.log = logger or log
+
+ @property
+ def dependencies(self):
+ """Build the dependency graph.
+
+ Returns a dict where the keys are the object names and the values are
+ lists of all dependencies including the key object itself.
+ """
+ if self._dependencies is None:
+ log.info("Resolving dependencies...")
+ self._dependencies = d = {}
+ self._preprocess_requirements()
+ for name,cdist_object in self.objects.items():
+ resolved = []
+ unresolved = []
+ self._resolve_object_dependencies(cdist_object, resolved, unresolved)
+ d[name] = resolved
+ return self._dependencies
+
+ def find_requirements_by_name(self, requirements):
+ """Takes a list of requirement patterns and returns a list of matching object instances.
+
+ Patterns are expected to be Unix shell-style wildcards for use with fnmatch.filter.
+
+ find_requirements_by_name(['__type/object_id', '__other_type/*']) ->
+ [