prevent requirements from leaking into autorequired objects and creating circular references

Signed-off-by: Steven Armstrong <steven@icarus.ethz.ch>

Conflicts:
	cdist/test/autorequire/__init__.py
This commit is contained in:
Steven Armstrong 2013-01-18 15:02:43 +01:00 committed by Nico Schottelius
parent cb829ec8d0
commit 06fb7491fa
4 changed files with 23 additions and 7 deletions

View File

@ -23,6 +23,7 @@ import logging
import os
import itertools
import fnmatch
import pprint
import cdist
@ -77,14 +78,15 @@ class DependencyResolver(object):
lists of all dependencies including the key object itself.
"""
if self._dependencies is None:
log.info("Resolving dependencies...")
self._dependencies = d = {}
self.log.info("Resolving dependencies...")
self._dependencies = {}
self._preprocess_requirements()
for name,cdist_object in self.objects.items():
resolved = []
unresolved = []
self._resolve_object_dependencies(cdist_object, resolved, unresolved)
d[name] = resolved
self._dependencies[name] = resolved
self.log.debug(self._dependencies)
return self._dependencies
def find_requirements_by_name(self, requirements):
@ -120,9 +122,12 @@ class DependencyResolver(object):
# that the parent has so that user defined requirements are
# fullfilled and processed in the expected order.
for auto_requirement in self.find_requirements_by_name(cdist_object.autorequire):
for requirement in cdist_object.requirements:
if requirement not in auto_requirement.requirements:
auto_requirement.requirements.append(requirement)
for requirement in self.find_requirements_by_name(cdist_object.requirements):
requirement_object_all_requirements = list(requirement.requirements) + list(requirement.autorequire)
if (requirement.name not in auto_requirement.requirements
and auto_requirement.name not in requirement_object_all_requirements):
self.log.debug('Adding %s to %s.requirements', requirement.name, auto_requirement)
auto_requirement.requirements.append(requirement.name)
# On the other hand the parent shall depend on all the children
# it created so that the user can setup dependencies on it as a
# whole without having to know anything about the parents
@ -149,7 +154,9 @@ class DependencyResolver(object):
self.log.debug("Object %s requires %s", cdist_object, required_object)
if required_object not in resolved:
if required_object in unresolved:
raise CircularReferenceError(cdist_object, required_object)
error = CircularReferenceError(cdist_object, required_object)
self.log.error('%s: %s', error, pprint.pformat(self._dependencies))
raise error
self._resolve_object_dependencies(required_object, resolved, unresolved)
resolved.append(cdist_object)
unresolved.remove(cdist_object)

View File

@ -83,3 +83,9 @@ class AutorequireTestCase(test.CdistTestCase):
self.config.stage_prepare()
# raises CircularDependecyError
self.config.stage_run()
def test_recursive_type(self):
self.context.initial_manifest = os.path.join(self.config.local.manifest_path, 'recursive_type')
self.config.stage_prepare()
# raises CircularDependecyError
self.config.stage_run()

View File

@ -0,0 +1,2 @@
__git foo
require="__git/foo" __git bar

View File

@ -0,0 +1 @@
__package git