summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTristan van Berkom <tristan.vanberkom@codethink.co.uk>2020-07-24 18:21:49 +0900
committerTristan van Berkom <tristan.vanberkom@codethink.co.uk>2020-07-24 19:35:28 +0900
commitf9c82abb547aa0155ab07b7744800790ff3f13a3 (patch)
treef2955f9346d40a778d1420b10e652e7399c472ab
parentd300a7621403e0ddbeeea2e0fa5446f166736b3e (diff)
downloadbuildstream-f9c82abb547aa0155ab07b7744800790ff3f13a3.tar.gz
_yaml.py: Support merging of conditional lists
During composition of project.conf, it can happen that we are including and composing node hierarchies before options are resolved and before we are ready to evaluate conditional statements. Without this patch, conditional statements are treated like regular lists, causing existing conditional statements to be overwritten by subsequently composited conditional statements without ever having been resolved. This patch introduces a special case for composing lists, when composing a sequence that is a conditional statement, the sequence is appended instead of overwriting the underlying list. Note that precedence of declarations in including vs included yaml fragments did raise some concern, and a test in the following commit is added to cover this case. Composition of conditional lists on top of other conditional lists are unconditionally appended, however the semantics of includes ensures that the including fragment's conditionals is always composited *on top* over the included fragment, ensuring that we have the correct pecedence even when compositing yet to be resolved conditional directives.
-rw-r--r--buildstream/_yaml.py15
1 files changed, 14 insertions, 1 deletions
diff --git a/buildstream/_yaml.py b/buildstream/_yaml.py
index 4f2f88329..405a10ec8 100644
--- a/buildstream/_yaml.py
+++ b/buildstream/_yaml.py
@@ -738,7 +738,20 @@ def composite_list(target_node, source_node, key):
"{}: List cannot overwrite value at: {}"
.format(source_key_provenance, target_key_provenance))
- composite_list_overwrite(target_node, key, source_node, key)
+ # Special case: The `project.conf` in some cases needs to composite
+ # include files before having resolved options, so there can be
+ # conditionals that need to be merged at this point.
+ #
+ # This unconditionally appends conditional statements to a matching
+ # conditional in the target so as to preserve them. The precedence
+ # of include files is preserved regardless due to the order in which
+ # included dictionaries are composited.
+ #
+ if key == "(?)":
+ composite_list_append(target_node, key, source_node, key)
+ else:
+ composite_list_overwrite(target_node, key, source_node, key)
+
return True
# When a composite list is encountered in the source, then