diff options
author | Valentin David <valentin.david@codethink.co.uk> | 2018-06-27 19:06:21 +0200 |
---|---|---|
committer | Valentin David <valentin.david@codethink.co.uk> | 2018-07-02 16:24:53 +0200 |
commit | 795df4e25aab328cc8830fa6093213f11a007314 (patch) | |
tree | 72a9b6ffe762c714db580c912c4ccb2b76eb9fc1 | |
parent | f06c2ce4c6c6a66e1e5ddcf3acc8d6cc218a0a38 (diff) | |
download | buildstream-795df4e25aab328cc8830fa6093213f11a007314.tar.gz |
Forbid inline tracking on fragments coming from junctions
-rw-r--r-- | buildstream/_includes.py | 10 | ||||
-rw-r--r-- | buildstream/_loader/loader.py | 2 | ||||
-rw-r--r-- | buildstream/_yaml.py | 21 | ||||
-rw-r--r-- | buildstream/source.py | 23 | ||||
-rw-r--r-- | tests/yaml/yaml.py | 2 |
5 files changed, 36 insertions, 22 deletions
diff --git a/buildstream/_includes.py b/buildstream/_includes.py index 3837c5d81..5b2c8aa66 100644 --- a/buildstream/_includes.py +++ b/buildstream/_includes.py @@ -26,15 +26,19 @@ class Includes: self._process_value(value) def _include_file(self, include): + shortname = include if ':' in include: junction, include = include.split(':', 1) junction_loader = self._loader._get_loader(junction, fetch_subprojects=True) - directory = junction_loader.project.directory + project = junction_loader.project else: - directory = self._loader.project.directory + project = self._loader.project + directory = project.directory file_path = os.path.join(directory, include) if file_path not in self._loaded: - self._loaded[file_path] = _yaml.load(os.path.join(directory, include)) + self._loaded[file_path] = _yaml.load(os.path.join(directory, include), + shortname=shortname, + project=project) return self._loaded[file_path] def _process_value(self, value): diff --git a/buildstream/_loader/loader.py b/buildstream/_loader/loader.py index 9c83f1e5f..b6221a29a 100644 --- a/buildstream/_loader/loader.py +++ b/buildstream/_loader/loader.py @@ -219,7 +219,7 @@ class Loader(): # Load the data and process any conditional statements therein fullpath = os.path.join(self._basedir, filename) try: - node = _yaml.load(fullpath, shortname=filename, copy_tree=rewritable) + node = _yaml.load(fullpath, shortname=filename, copy_tree=rewritable, project=self.project) except LoadError as e: if e.reason == LoadErrorReason.MISSING_FILE: # If we can't find the file, try to suggest plausible diff --git a/buildstream/_yaml.py b/buildstream/_yaml.py index 0e090e2e7..d975b1ede 100644 --- a/buildstream/_yaml.py +++ b/buildstream/_yaml.py @@ -37,6 +37,13 @@ RoundTripConstructor.add_constructor(u'tag:yaml.org,2002:float', RoundTripConstr PROVENANCE_KEY = '__bst_provenance_info' +class ProvenanceFile(): + def __init__(self, name, shortname, project): + self.name = name + self.shortname = shortname + self.project = project + + # Provenance tracks the origin of a given node in the parsed dictionary. # # Args: @@ -56,7 +63,7 @@ class Provenance(): # Convert a Provenance to a string for error reporting def __str__(self): - return "{} [line {:d} column {:d}]".format(self.filename, self.line, self.col) + return "{} [line {:d} column {:d}]".format(self.filename.shortname, self.line, self.col) # Abstract method def clone(self): @@ -174,13 +181,15 @@ class CompositeTypeError(CompositeError): # # Raises: LoadError # -def load(filename, shortname=None, copy_tree=False): +def load(filename, shortname=None, copy_tree=False, *, project=None): if not shortname: shortname = filename + file = ProvenanceFile(filename, shortname, project) + try: with open(filename) as f: - return load_data(f, shortname=shortname, copy_tree=copy_tree) + return load_data(f, file, copy_tree=copy_tree) except FileNotFoundError as e: raise LoadError(LoadErrorReason.MISSING_FILE, "Could not find file at {}".format(filename)) from e @@ -192,7 +201,7 @@ def load(filename, shortname=None, copy_tree=False): # Like load(), but doesnt require the data to be in a file # -def load_data(data, shortname=None, copy_tree=False): +def load_data(data, file=None, copy_tree=False): try: contents = yaml.load(data, yaml.loader.RoundTripLoader, preserve_quotes=True) @@ -207,9 +216,9 @@ def load_data(data, shortname=None, copy_tree=False): else: raise LoadError(LoadErrorReason.INVALID_YAML, "YAML file has content of type '{}' instead of expected type 'dict': {}" - .format(type(contents).__name__, shortname)) + .format(type(contents).__name__, file.name)) - return node_decorated_copy(shortname, contents, copy_tree=copy_tree) + return node_decorated_copy(file, contents, copy_tree=copy_tree) # Dumps a previously loaded YAML node to a file diff --git a/buildstream/source.py b/buildstream/source.py index c01993429..579e40513 100644 --- a/buildstream/source.py +++ b/buildstream/source.py @@ -524,6 +524,7 @@ class Source(Plugin): toplevel = context.get_toplevel_project() toplevel_refs = self._project_refs(toplevel) provenance = self._get_provenance() + assert provenance.filename.project is not None element_name = self.__element_name element_idx = self.__element_index @@ -558,24 +559,24 @@ class Source(Plugin): # # Step 3 - Apply the change in project data # - if project is toplevel: - if toplevel.ref_storage == ProjectRefStorage.PROJECT_REFS: - do_save_refs(toplevel_refs) - else: + if toplevel.ref_storage == ProjectRefStorage.PROJECT_REFS: + do_save_refs(toplevel_refs) + else: + if provenance.filename.project is toplevel: # Save the ref in the originating file # - fullname = os.path.join(toplevel.element_path, provenance.filename) try: - _yaml.dump(provenance.toplevel, fullname) + _yaml.dump(_yaml.node_sanitize(provenance.toplevel), provenance.filename.name) except OSError as e: raise SourceError("{}: Error saving source reference to '{}': {}" - .format(self, provenance.filename, e), + .format(self, provenance.filename.name, e), reason="save-ref-error") from e - else: - if toplevel.ref_storage == ProjectRefStorage.PROJECT_REFS: - do_save_refs(toplevel_refs) - else: + elif provenance.filename.project is project: self.warn("{}: Not persisting new reference in junctioned project".format(self)) + else: + raise SourceError("{}: Cannot track source in a fragment from a junction" + .format(provenance.filename.shortname), + reason="tracking-junction-fragment") return changed diff --git a/tests/yaml/yaml.py b/tests/yaml/yaml.py index 3b9f385ed..781763717 100644 --- a/tests/yaml/yaml.py +++ b/tests/yaml/yaml.py @@ -33,7 +33,7 @@ def assert_provenance(filename, line, col, node, key=None, indices=[]): else: assert(isinstance(provenance, _yaml.DictProvenance)) - assert(provenance.filename == filename) + assert(provenance.filename.shortname == filename) assert(provenance.line == line) assert(provenance.col == col) |