summaryrefslogtreecommitdiff
path: root/morphlib/sourceresolver.py
diff options
context:
space:
mode:
Diffstat (limited to 'morphlib/sourceresolver.py')
-rw-r--r--morphlib/sourceresolver.py84
1 files changed, 70 insertions, 14 deletions
diff --git a/morphlib/sourceresolver.py b/morphlib/sourceresolver.py
index d2b47d35..771e81e3 100644
--- a/morphlib/sourceresolver.py
+++ b/morphlib/sourceresolver.py
@@ -31,7 +31,7 @@ tree_cache_filename = 'trees.cache.pickle'
buildsystem_cache_size = 10000
buildsystem_cache_filename = 'detected-chunk-buildsystems.cache.pickle'
-not_supported_versions = []
+supported_versions = [0, 1, 2]
class PickleCacheManager(object): # pragma: no cover
'''Cache manager for PyLRU that reads and writes to Pickle files.
@@ -90,12 +90,26 @@ class MorphologyNotFoundError(SourceResolverError): # pragma: no cover
SourceResolverError.__init__(
self, "Couldn't find morphology: %s" % filename)
+
+class MorphologyReferenceNotFoundError(SourceResolverError): # pragma: no cover
+ def __init__(self, filename, reference_file):
+ SourceResolverError.__init__(self,
+ "Couldn't find morphology: %s "
+ "referenced in %s"
+ % (filename, reference_file))
+
+
class UnknownVersionError(SourceResolverError): # pragma: no cover
def __init__(self, version):
SourceResolverError.__init__(
self, "Definitions format version %s is not supported" % version)
+class InvalidVersionFileError(SourceResolverError): #pragma: no cover
+ def __init__(self):
+ SourceResolverError.__init__(self, "invalid VERSION file")
+
+
class SourceResolver(object):
'''Provides a way of resolving the set of sources for a given system.
@@ -286,7 +300,7 @@ class SourceResolver(object):
loader = morphlib.morphloader.MorphologyLoader()
text = self._get_file_contents(reponame, sha1, filename)
- morph = loader.load_from_string(text)
+ morph = loader.load_from_string(text, filename)
if morph is not None:
self._resolved_morphologies[key] = morph
@@ -346,22 +360,45 @@ class SourceResolver(object):
loader.set_defaults(morph)
return morph
- def _check_version_file(self,definitions_repo,
+ def _parse_version_file(self, version_file): # pragma : no cover
+ '''Parse VERSION file and return the version of the format if:
+
+ VERSION is a YAML file
+ and it's a dict
+ and has the key 'version'
+ and the type stored in the 'version' key is an int
+
+ otherwise returns None
+
+ '''
+
+ yaml_obj = yaml.safe_load(version_file)
+
+ return (yaml_obj['version'] if yaml_obj is not None
+ and isinstance(yaml_obj, dict)
+ and 'version' in yaml_obj
+ and isinstance(yaml_obj['version'], int)
+
+ else None)
+
+ def _check_version_file(self, definitions_repo,
definitions_absref): # pragma: no cover
- version_file = self._get_file_contents(
- definitions_repo, definitions_absref, 'VERSION')
+ version_file = self._get_file_contents(definitions_repo,
+ definitions_absref, 'VERSION')
- if version_file is None:
- return
+ if version_file == None:
+ return 0 # Assume version 0 if no version file
- try:
- version = yaml.safe_load(version_file)['version']
- except (yaml.error.YAMLError, KeyError, TypeError):
- version = 0
+ version = self._parse_version_file(version_file)
- if version in not_supported_versions:
+ if version == None:
+ raise InvalidVersionFileError()
+
+ if version not in supported_versions:
raise UnknownVersionError(version)
+ return version
+
def _process_definitions_with_children(self, system_filenames,
definitions_repo,
definitions_ref,
@@ -371,7 +408,8 @@ class SourceResolver(object):
definitions_queue = collections.deque(system_filenames)
chunk_queue = set()
- self._check_version_file(definitions_repo, definitions_absref)
+ definitions_version = self._check_version_file(definitions_repo,
+ definitions_absref)
while definitions_queue:
filename = definitions_queue.popleft()
@@ -410,9 +448,27 @@ class SourceResolver(object):
# code path should be removed.
path = morphlib.util.sanitise_morphology_path(
c.get('morph', c['name']))
+
chunk_queue.add((c['repo'], c['ref'], path))
else:
- chunk_queue.add((c['repo'], c['ref'], c['morph']))
+ # Now, does this path actually exist?
+ path = c['morph']
+
+ morphology = self._get_morphology(definitions_repo,
+ definitions_absref,
+ path)
+ if morphology is None:
+ if definitions_version > 1:
+ raise MorphologyReferenceNotFoundError(
+ path, filename)
+ else:
+ self.status(
+ msg="Warning! `%(path)s' referenced in "
+ "`%(stratum)s' does not exist",
+ path=path,
+ stratum=filename)
+
+ chunk_queue.add((c['repo'], c['ref'], path))
return chunk_queue