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

View file

@ -83,3 +83,9 @@ class AutorequireTestCase(test.CdistTestCase):
self.config.stage_prepare() self.config.stage_prepare()
# raises CircularDependecyError # raises CircularDependecyError
self.config.stage_run() 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