yq/pkg/yqlib/candidate_node.go

132 lines
3.5 KiB
Go
Raw Normal View History

2020-11-03 23:48:43 +00:00
package yqlib
2020-10-13 01:51:37 +00:00
import (
"fmt"
"strconv"
"strings"
2020-10-21 02:54:51 +00:00
"github.com/jinzhu/copier"
2020-11-20 04:50:15 +00:00
yaml "gopkg.in/yaml.v3"
2020-10-13 01:51:37 +00:00
)
type CandidateNode struct {
2020-11-20 04:50:15 +00:00
Node *yaml.Node // the actual node
Path []interface{} /// the path we took to get to this node
Document uint // the document index of this node
Filename string
FileIndex int
2021-01-17 23:15:31 +00:00
// when performing op against all nodes given, this will treat all the nodes as one
// (e.g. top level cross document merge). This property does not propegate to child nodes.
EvaluateTogether bool
2020-10-13 01:51:37 +00:00
}
func (n *CandidateNode) GetKey() string {
2020-10-30 01:00:48 +00:00
return fmt.Sprintf("%v - %v", n.Document, n.Path)
2020-10-13 01:51:37 +00:00
}
func (n *CandidateNode) CreateChild(path interface{}, node *yaml.Node) *CandidateNode {
return &CandidateNode{
Node: node,
Path: n.createChildPath(path),
Document: n.Document,
Filename: n.Filename,
FileIndex: n.FileIndex,
}
}
func (n *CandidateNode) createChildPath(path interface{}) []interface{} {
if path == nil {
newPath := make([]interface{}, len(n.Path))
copy(newPath, n.Path)
return newPath
}
2020-12-25 01:46:08 +00:00
//don't use append as they may actually modify the path of the orignal node!
newPath := make([]interface{}, len(n.Path)+1)
copy(newPath, n.Path)
newPath[len(n.Path)] = path
return newPath
}
2020-11-13 03:07:11 +00:00
func (n *CandidateNode) Copy() (*CandidateNode, error) {
2020-10-21 02:54:51 +00:00
clone := &CandidateNode{}
2020-11-13 03:07:11 +00:00
err := copier.Copy(clone, n)
if err != nil {
return nil, err
}
return clone, nil
2020-10-21 02:54:51 +00:00
}
2020-10-16 01:29:26 +00:00
// updates this candidate from the given candidate node
func (n *CandidateNode) UpdateFrom(other *CandidateNode) {
2021-01-01 23:27:32 +00:00
2020-10-19 05:36:46 +00:00
n.UpdateAttributesFrom(other)
2020-10-16 01:29:26 +00:00
n.Node.Content = other.Node.Content
n.Node.Value = other.Node.Value
2020-10-29 23:56:45 +00:00
n.Node.Alias = other.Node.Alias
2021-01-12 22:21:16 +00:00
n.Node.Anchor = other.Node.Anchor
2020-10-19 05:14:29 +00:00
}
func (n *CandidateNode) UpdateAttributesFrom(other *CandidateNode) {
2020-10-19 05:36:46 +00:00
if n.Node.Kind != other.Node.Kind {
// clear out the contents when switching to a different type
// e.g. map to array
n.Node.Content = make([]*yaml.Node, 0)
n.Node.Value = ""
}
2020-10-16 01:29:26 +00:00
n.Node.Kind = other.Node.Kind
n.Node.Tag = other.Node.Tag
2020-10-28 00:34:01 +00:00
// merge will pickup the style of the new thing
// when autocreating nodes
if n.Node.Style == 0 {
n.Node.Style = other.Node.Style
}
2020-10-30 01:40:44 +00:00
n.Node.FootComment = n.Node.FootComment + other.Node.FootComment
n.Node.HeadComment = n.Node.HeadComment + other.Node.HeadComment
n.Node.LineComment = n.Node.LineComment + other.Node.LineComment
2020-10-16 01:29:26 +00:00
}
2020-10-13 01:51:37 +00:00
func (n *CandidateNode) PathStackToString() string {
return mergePathStackToString(n.Path)
}
func mergePathStackToString(pathStack []interface{}) string {
var sb strings.Builder
for index, path := range pathStack {
switch path.(type) {
case int, int64:
// if arrayMergeStrategy == AppendArrayMergeStrategy {
// sb.WriteString("[+]")
// } else {
sb.WriteString(fmt.Sprintf("[%v]", path))
// }
default:
s := fmt.Sprintf("%v", path)
var _, errParsingInt = strconv.ParseInt(s, 10, 64) // nolint
hasSpecial := strings.Contains(s, ".") || strings.Contains(s, "[") || strings.Contains(s, "]") || strings.Contains(s, "\"")
hasDoubleQuotes := strings.Contains(s, "\"")
wrappingCharacterStart := "\""
wrappingCharacterEnd := "\""
if hasDoubleQuotes {
wrappingCharacterStart = "("
wrappingCharacterEnd = ")"
}
if hasSpecial || errParsingInt == nil {
sb.WriteString(wrappingCharacterStart)
}
sb.WriteString(s)
if hasSpecial || errParsingInt == nil {
sb.WriteString(wrappingCharacterEnd)
}
}
if index < len(pathStack)-1 {
sb.WriteString(".")
}
}
return sb.String()
}