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
