From 34ba445fd1963acada0733c196483c98a57fd753 Mon Sep 17 00:00:00 2001 From: Sam Thursfield Date: Tue, 7 Nov 2017 17:55:22 +0000 Subject: Allow overwriting a list with an empty list using (=) operator I found myself writing the following split rules for an element: public: bst: split-rules: runtime: (=): [] devel: (>): - | %{bindir}/* The aim was to put all of this element's binaries into the 'devel' domain, and make sure nothing went into the 'runtime' domain by replacing the built-in rules for that domain with an empty list. That wasn't working though because BuildStream was using [] (empty list) as a sentinel to mean "do nothing", which is fine for the prepend and append operators (prepending an empty list to a list has no effect) but is not really correct for the overwrite operator. This commit fixes that issue and adds a test. --- buildstream/_yaml.py | 6 ++++-- tests/yaml/data/listoverwriteempty.yaml | 3 +++ tests/yaml/yaml.py | 14 ++++++++++++++ 3 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 tests/yaml/data/listoverwriteempty.yaml diff --git a/buildstream/_yaml.py b/buildstream/_yaml.py index 153e744f4..11b5fd219 100644 --- a/buildstream/_yaml.py +++ b/buildstream/_yaml.py @@ -552,8 +552,10 @@ def composite_list_append(target_node, target_key, source_node, source_key): # def composite_list_overwrite(target_node, target_key, source_node, source_key): - source_list = node_get(source_node, list, source_key, default_value=[]) - if not source_list: + # We need to handle the legitimate case of overwriting a list with an empty + # list, hence the slightly odd default_value of [None] rather than []. + source_list = node_get(source_node, list, source_key, default_value=[None]) + if source_list == [None]: return False target_provenance = node_get_provenance(target_node) diff --git a/tests/yaml/data/listoverwriteempty.yaml b/tests/yaml/data/listoverwriteempty.yaml new file mode 100644 index 000000000..f97a1eafe --- /dev/null +++ b/tests/yaml/data/listoverwriteempty.yaml @@ -0,0 +1,3 @@ +# Composited on top of basics.yaml, effectively deleting its children list +children: + (=): [] diff --git a/tests/yaml/yaml.py b/tests/yaml/yaml.py index 0aae28f08..a462e18df 100644 --- a/tests/yaml/yaml.py +++ b/tests/yaml/yaml.py @@ -213,6 +213,20 @@ def test_list_composition(datafiles, filename, assert_provenance(prov_file, prov_line, prov_col, child, 'mood') +# Test that overwriting a list with an empty list works as expected. +@pytest.mark.datafiles(os.path.join(DATA_DIR)) +def test_list_deletion(datafiles): + base = os.path.join(datafiles.dirname, datafiles.basename, 'basics.yaml') + overlay = os.path.join(datafiles.dirname, datafiles.basename, 'listoverwriteempty.yaml') + + base = _yaml.load(base, shortname='basics.yaml') + overlay = _yaml.load(overlay, shortname='listoverwriteempty.yaml') + _yaml.composite_dict(base, overlay) + + children = _yaml.node_get(base, list, 'children') + assert len(children) == 0 + + # Tests for deep list composition # # Same as test_list_composition(), but adds an additional file -- cgit v1.2.1