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 4789c0fde87c6d989142c8d6ee473b58f13d38be
Author: Valentin David <[email protected]>
AuthorDate: Thu Jun 28 13:58:14 2018 +0200

    Detect recursive includes.
---
 buildstream/_exceptions.py                     |  3 +++
 buildstream/_includes.py                       | 28 +++++++++++++++++---------
 tests/format/include.py                        | 12 +++++++++++
 tests/format/include/recursive/extra_conf.yml  |  2 ++
 tests/format/include/recursive/extra_conf2.yml |  2 ++
 tests/format/include/recursive/project.conf    |  4 ++++
 6 files changed, 41 insertions(+), 10 deletions(-)

diff --git a/buildstream/_exceptions.py b/buildstream/_exceptions.py
index 3779632..020ed88 100644
--- a/buildstream/_exceptions.py
+++ b/buildstream/_exceptions.py
@@ -200,6 +200,9 @@ class LoadErrorReason(Enum):
     # Try to load a directory not a yaml file
     LOADING_DIRECTORY = 18
 
+    # A recursive include has been encountered.
+    RECURSIVE_INCLUDE = 19
+
 
 # LoadError
 #
diff --git a/buildstream/_includes.py b/buildstream/_includes.py
index 5b2c8aa..2bd885a 100644
--- a/buildstream/_includes.py
+++ b/buildstream/_includes.py
@@ -1,6 +1,7 @@
 import os
 from collections import Mapping
 from . import _yaml
+from ._exceptions import LoadError, LoadErrorReason
 
 
 class Includes:
@@ -9,17 +10,24 @@ class Includes:
         self._loader = loader
         self._loaded = {}
 
-    def process(self, node):
-        while True:
-            includes = _yaml.node_get(node, list, '(@)', default_value=None)
-            if '(@)' in node:
-                del node['(@)']
-
-            if not includes:
-                break
+    def process(self, node, *, included=set()):
+        includes = _yaml.node_get(node, list, '(@)', default_value=None)
+        if '(@)' in node:
+            del node['(@)']
 
+        if includes:
             for include in includes:
-                include_node = self._include_file(include)
+                include_node, file_path = self._include_file(include)
+                if file_path in included:
+                    provenance = _yaml.node_get_provenance(node)
+                    raise LoadError(LoadErrorReason.RECURSIVE_INCLUDE,
+                                    "{}: trying to recursively include {}". 
format(provenance,
+                                                                               
    file_path))
+                try:
+                    included.add(file_path)
+                    self.process(include_node, included=included)
+                finally:
+                    included.remove(file_path)
                 _yaml.composite(node, include_node)
 
         for _, value in _yaml.node_items(node):
@@ -39,7 +47,7 @@ class Includes:
             self._loaded[file_path] = _yaml.load(os.path.join(directory, 
include),
                                                  shortname=shortname,
                                                  project=project)
-        return self._loaded[file_path]
+        return self._loaded[file_path], file_path
 
     def _process_value(self, value):
         if isinstance(value, Mapping):
diff --git a/tests/format/include.py b/tests/format/include.py
index 7a1a15a..8a79ed9 100644
--- a/tests/format/include.py
+++ b/tests/format/include.py
@@ -203,3 +203,15 @@ def test_conditional_in_fragment(cli, tmpdir, datafiles):
     loaded = _yaml.load_data(result.output)
     assert 'size' in loaded
     assert loaded['size'] == '8'
+
+
[email protected](DATA_DIR)
+def test_recusive_include(cli, tmpdir, datafiles):
+    project = os.path.join(str(datafiles), 'recursive')
+
+    result = cli.run(project=project, args=[
+        'show',
+        '--deps', 'none',
+        '--format', '%{vars}',
+        'element.bst'])
+    result.assert_main_error(ErrorDomain.LOAD, 
LoadErrorReason.RECURSIVE_INCLUDE)
diff --git a/tests/format/include/recursive/extra_conf.yml 
b/tests/format/include/recursive/extra_conf.yml
new file mode 100644
index 0000000..57db0d3
--- /dev/null
+++ b/tests/format/include/recursive/extra_conf.yml
@@ -0,0 +1,2 @@
+(@):
+  - extra_conf2.yml
diff --git a/tests/format/include/recursive/extra_conf2.yml 
b/tests/format/include/recursive/extra_conf2.yml
new file mode 100644
index 0000000..e8dd5e2
--- /dev/null
+++ b/tests/format/include/recursive/extra_conf2.yml
@@ -0,0 +1,2 @@
+(@):
+  - extra_conf.yml
diff --git a/tests/format/include/recursive/project.conf 
b/tests/format/include/recursive/project.conf
new file mode 100644
index 0000000..a7791a4
--- /dev/null
+++ b/tests/format/include/recursive/project.conf
@@ -0,0 +1,4 @@
+name: test
+
+(@):
+  - extra_conf.yml

Reply via email to