diff options
Diffstat (limited to 'morphlib/sourceresolver.py')
-rw-r--r-- | morphlib/sourceresolver.py | 84 |
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 |