summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTristan van Berkom <tristan.vanberkom@codethink.co.uk>2020-07-24 15:52:05 +0900
committerTristan van Berkom <tristan.vanberkom@codethink.co.uk>2020-07-29 19:04:23 +0900
commit24703a8434b48ebe58326f990e2d5a0474fe76da (patch)
treebf66afc17c092f9a14126f6a2bba956c2576a471
parentfecf3534d887e52b5bf5bbc5ef6861a54d858d12 (diff)
downloadbuildstream-24703a8434b48ebe58326f990e2d5a0474fe76da.tar.gz
node.pyx: Support merging of conditional sequences
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 sequences, 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 sequences, 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--src/buildstream/node.pyx18
1 files changed, 13 insertions, 5 deletions
diff --git a/src/buildstream/node.pyx b/src/buildstream/node.pyx
index 394138311..9a0bd2eb6 100644
--- a/src/buildstream/node.pyx
+++ b/src/buildstream/node.pyx
@@ -214,7 +214,7 @@ cdef class Node:
# _is_composite_list
#
- # Checks if the node is a Mapping with array composition
+ # Checks if the node is a Mapping with list composition
# directives.
#
# Returns:
@@ -1070,14 +1070,14 @@ cdef class MappingNode(Node):
cdef str key
for key in self.value.keys():
- if key in ['(>)', '(<)', '(=)']:
+ if key in ["(>)", "(<)", "(=)"]:
has_directives = True
else:
has_keys = True
if has_keys and has_directives:
provenance = self.get_provenance()
- raise LoadError("{}: Dictionary contains array composition directives and arbitrary keys"
+ raise LoadError("{}: Dictionary contains list composition directives and arbitrary keys"
.format(provenance), LoadErrorReason.INVALID_DATA)
return has_directives
@@ -1412,8 +1412,16 @@ cdef class SequenceNode(Node):
.format(self.get_provenance(),
key,
target_value.get_provenance()))
- # Looks good, clobber it
- target.value[key] = self
+
+ # If the target is a list of conditional statements, then we are
+ # also conditional statements, and we need to append ourselves
+ # to that list instead of overwriting it in order to preserve the
+ # conditional for later evaluation.
+ if type(target_value) is SequenceNode and key == "(?)":
+ (<SequenceNode> target.value[key]).value.extend(self.value)
+ else:
+ # Looks good, clobber it
+ target.value[key] = self
cdef bint _is_composite_list(self) except *:
return False