summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorValentin David <valentin.david@codethink.co.uk>2018-06-27 19:06:21 +0200
committerValentin David <valentin.david@codethink.co.uk>2018-07-02 16:24:53 +0200
commit795df4e25aab328cc8830fa6093213f11a007314 (patch)
tree72a9b6ffe762c714db580c912c4ccb2b76eb9fc1
parentf06c2ce4c6c6a66e1e5ddcf3acc8d6cc218a0a38 (diff)
downloadbuildstream-795df4e25aab328cc8830fa6093213f11a007314.tar.gz
Forbid inline tracking on fragments coming from junctions
-rw-r--r--buildstream/_includes.py10
-rw-r--r--buildstream/_loader/loader.py2
-rw-r--r--buildstream/_yaml.py21
-rw-r--r--buildstream/source.py23
-rw-r--r--tests/yaml/yaml.py2
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)