-
Notifications
You must be signed in to change notification settings - Fork 18
/
finder.go
73 lines (57 loc) · 1.6 KB
/
finder.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
package node
// DeepFindChild recursively traverses node's children
// and returns the first node found named name.
func (node *Node) DeepFindChild(name string) *Node {
for _, child := range node.Children {
if child.Name == name {
return child
}
if found := child.DeepFindChild(name); found != nil {
return found
}
}
return nil
}
func (node *Node) DeepFindCollectible(name string) *Node {
var fulfilledAtLeastOnce bool
var virtualNode Node
// Accumulate collectible nodes in descending order of priority
// (e.g. "env" field from the root YAML map comes first, then "env" field from the task's map, etc.)
var traverseChain []*Node
for current := node; current != nil; current = current.Parent {
for i := len(current.Children) - 1; i >= 0; i-- {
child := current.Children[i]
if child.Name == name {
traverseChain = append(traverseChain, child)
}
}
}
// Starting from the lowest priority node,
// merge the rest of the nodes into it
for i := len(traverseChain) - 1; i >= 0; i-- {
child := traverseChain[i]
virtualNode.MergeFrom(child)
if !fulfilledAtLeastOnce {
fulfilledAtLeastOnce = true
}
}
if !fulfilledAtLeastOnce {
return nil
}
// Simulate Cirrus Cloud parser behavior
virtualNode.Deduplicate()
// Link to the tree so collectible sub-fields will know about to the tree
virtualNode.Parent = node
return &virtualNode
}
func (node *Node) HasChild(name string) bool {
return node.FindChild(name) != nil
}
func (node *Node) FindChild(name string) *Node {
for _, child := range node.Children {
if child.Name == name {
return child
}
}
return nil
}