You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@buildstream.apache.org by gi...@apache.org on 2020/12/29 13:13:57 UTC

[buildstream] 12/30: Forbid inline tracking on fragments coming from junctions

This is an automated email from the ASF dual-hosted git repository.

github-bot pushed a commit to branch valentindavid/flatpak-demo
in repository https://gitbox.apache.org/repos/asf/buildstream.git

commit 795df4e25aab328cc8830fa6093213f11a007314
Author: Valentin David <va...@codethink.co.uk>
AuthorDate: Wed Jun 27 19:06:21 2018 +0200

    Forbid inline tracking on fragments coming from junctions
---
 buildstream/_includes.py      | 10 +++++++---
 buildstream/_loader/loader.py |  2 +-
 buildstream/_yaml.py          | 21 +++++++++++++++------
 buildstream/source.py         | 23 ++++++++++++-----------
 tests/yaml/yaml.py            |  2 +-
 5 files changed, 36 insertions(+), 22 deletions(-)

diff --git a/buildstream/_includes.py b/buildstream/_includes.py
index 3837c5d..5b2c8aa 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 9c83f1e..b6221a2 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 0e090e2..d975b1e 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 c019934..579e405 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 3b9f385..7817637 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)