mirror of
				https://github.com/taigrr/yq
				synced 2025-01-18 04:53:17 -08:00 
			
		
		
		
	Dont create entries when selecting
This commit is contained in:
		
							parent
							
								
									c6efd5519b
								
							
						
					
					
						commit
						5c73132c8e
					
				| @ -1,18 +1,30 @@ | |||||||
| package yqlib | package yqlib | ||||||
| 
 | 
 | ||||||
| import "container/list" | import ( | ||||||
|  | 	"container/list" | ||||||
|  | 
 | ||||||
|  | 	"github.com/jinzhu/copier" | ||||||
|  | ) | ||||||
| 
 | 
 | ||||||
| type Context struct { | type Context struct { | ||||||
| 	MatchingNodes *list.List | 	MatchingNodes  *list.List | ||||||
| 	Variables     map[string]*list.List | 	Variables      map[string]*list.List | ||||||
|  | 	DontAutoCreate bool | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (n *Context) SingleChildContext(candidate *CandidateNode) Context { | func (n *Context) SingleChildContext(candidate *CandidateNode) Context { | ||||||
| 	elMap := list.New() | 	list := list.New() | ||||||
| 	elMap.PushBack(candidate) | 	list.PushBack(candidate) | ||||||
| 	return Context{MatchingNodes: elMap, Variables: n.Variables} | 	return n.ChildContext(list) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (n *Context) ChildContext(results *list.List) Context { | func (n *Context) ChildContext(results *list.List) Context { | ||||||
| 	return Context{MatchingNodes: results, Variables: n.Variables} | 	clone := Context{} | ||||||
|  | 	err := copier.Copy(&clone, n) | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Error("Error cloning context :(") | ||||||
|  | 		panic(err) | ||||||
|  | 	} | ||||||
|  | 	clone.MatchingNodes = results | ||||||
|  | 	return clone | ||||||
| } | } | ||||||
|  | |||||||
| @ -11,8 +11,9 @@ func selectOperator(d *dataTreeNavigator, context Context, expressionNode *Expre | |||||||
| 
 | 
 | ||||||
| 	for el := context.MatchingNodes.Front(); el != nil; el = el.Next() { | 	for el := context.MatchingNodes.Front(); el != nil; el = el.Next() { | ||||||
| 		candidate := el.Value.(*CandidateNode) | 		candidate := el.Value.(*CandidateNode) | ||||||
| 
 | 		childContext := context.SingleChildContext(candidate) | ||||||
| 		rhs, err := d.GetMatchingNodes(context.SingleChildContext(candidate), expressionNode.Rhs) | 		childContext.DontAutoCreate = true | ||||||
|  | 		rhs, err := d.GetMatchingNodes(childContext, expressionNode.Rhs) | ||||||
| 
 | 
 | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return Context{}, err | 			return Context{}, err | ||||||
|  | |||||||
| @ -14,6 +14,14 @@ var selectOperatorScenarios = []expressionScenario{ | |||||||
| 			"D0, P[1], (!!str)::goat\n", | 			"D0, P[1], (!!str)::goat\n", | ||||||
| 		}, | 		}, | ||||||
| 	}, | 	}, | ||||||
|  | 	{ | ||||||
|  | 		skipDoc:    true, | ||||||
|  | 		document:   `[{animal: cat, legs: {cool: true}}, {animal: fish}]`, | ||||||
|  | 		expression: `(.[] | select(.legs.cool == true).canWalk) = true | (.[] | .alive.things) = "yes"`, | ||||||
|  | 		expected: []string{ | ||||||
|  | 			"D0, P[], (doc)::[{animal: cat, legs: {cool: true}, canWalk: true, alive: {things: yes}}, {animal: fish, alive: {things: yes}}]\n", | ||||||
|  | 		}, | ||||||
|  | 	}, | ||||||
| 	{ | 	{ | ||||||
| 		skipDoc:    true, | 		skipDoc:    true, | ||||||
| 		document:   `[hot, fot, dog]`, | 		document:   `[hot, fot, dog]`, | ||||||
|  | |||||||
| @ -24,7 +24,7 @@ func traversePathOperator(d *dataTreeNavigator, context Context, expressionNode | |||||||
| 	var matches = list.New() | 	var matches = list.New() | ||||||
| 
 | 
 | ||||||
| 	for el := context.MatchingNodes.Front(); el != nil; el = el.Next() { | 	for el := context.MatchingNodes.Front(); el != nil; el = el.Next() { | ||||||
| 		newNodes, err := traverse(d, el.Value.(*CandidateNode), expressionNode.Operation) | 		newNodes, err := traverse(d, context, el.Value.(*CandidateNode), expressionNode.Operation) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return Context{}, err | 			return Context{}, err | ||||||
| 		} | 		} | ||||||
| @ -34,7 +34,7 @@ func traversePathOperator(d *dataTreeNavigator, context Context, expressionNode | |||||||
| 	return context.ChildContext(matches), nil | 	return context.ChildContext(matches), nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func traverse(d *dataTreeNavigator, matchingNode *CandidateNode, operation *Operation) (*list.List, error) { | func traverse(d *dataTreeNavigator, context Context, matchingNode *CandidateNode, operation *Operation) (*list.List, error) { | ||||||
| 	log.Debug("Traversing %v", NodeToString(matchingNode)) | 	log.Debug("Traversing %v", NodeToString(matchingNode)) | ||||||
| 	value := matchingNode.Node | 	value := matchingNode.Node | ||||||
| 
 | 
 | ||||||
| @ -55,7 +55,7 @@ func traverse(d *dataTreeNavigator, matchingNode *CandidateNode, operation *Oper | |||||||
| 	switch value.Kind { | 	switch value.Kind { | ||||||
| 	case yaml.MappingNode: | 	case yaml.MappingNode: | ||||||
| 		log.Debug("its a map with %v entries", len(value.Content)/2) | 		log.Debug("its a map with %v entries", len(value.Content)/2) | ||||||
| 		return traverseMap(matchingNode, operation.StringValue, operation.Preferences.(traversePreferences), false) | 		return traverseMap(context, matchingNode, operation.StringValue, operation.Preferences.(traversePreferences), false) | ||||||
| 
 | 
 | ||||||
| 	case yaml.SequenceNode: | 	case yaml.SequenceNode: | ||||||
| 		log.Debug("its a sequence of %v things!", len(value.Content)) | 		log.Debug("its a sequence of %v things!", len(value.Content)) | ||||||
| @ -64,11 +64,11 @@ func traverse(d *dataTreeNavigator, matchingNode *CandidateNode, operation *Oper | |||||||
| 	case yaml.AliasNode: | 	case yaml.AliasNode: | ||||||
| 		log.Debug("its an alias!") | 		log.Debug("its an alias!") | ||||||
| 		matchingNode.Node = matchingNode.Node.Alias | 		matchingNode.Node = matchingNode.Node.Alias | ||||||
| 		return traverse(d, matchingNode, operation) | 		return traverse(d, context, matchingNode, operation) | ||||||
| 	case yaml.DocumentNode: | 	case yaml.DocumentNode: | ||||||
| 		log.Debug("digging into doc node") | 		log.Debug("digging into doc node") | ||||||
| 
 | 
 | ||||||
| 		return traverse(d, matchingNode.CreateChild(nil, matchingNode.Node.Content[0]), operation) | 		return traverse(d, context, matchingNode.CreateChild(nil, matchingNode.Node.Content[0]), operation) | ||||||
| 	default: | 	default: | ||||||
| 		return list.New(), nil | 		return list.New(), nil | ||||||
| 	} | 	} | ||||||
| @ -90,7 +90,7 @@ func traverseNodesWithArrayIndices(context Context, indicesToTraverse []*yaml.No | |||||||
| 	var matchingNodeMap = list.New() | 	var matchingNodeMap = list.New() | ||||||
| 	for el := context.MatchingNodes.Front(); el != nil; el = el.Next() { | 	for el := context.MatchingNodes.Front(); el != nil; el = el.Next() { | ||||||
| 		candidate := el.Value.(*CandidateNode) | 		candidate := el.Value.(*CandidateNode) | ||||||
| 		newNodes, err := traverseArrayIndices(candidate, indicesToTraverse, prefs) | 		newNodes, err := traverseArrayIndices(context, candidate, indicesToTraverse, prefs) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return Context{}, err | 			return Context{}, err | ||||||
| 		} | 		} | ||||||
| @ -100,7 +100,7 @@ func traverseNodesWithArrayIndices(context Context, indicesToTraverse []*yaml.No | |||||||
| 	return context.ChildContext(matchingNodeMap), nil | 	return context.ChildContext(matchingNodeMap), nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func traverseArrayIndices(matchingNode *CandidateNode, indicesToTraverse []*yaml.Node, prefs traversePreferences) (*list.List, error) { // call this if doc / alias like the other traverse | func traverseArrayIndices(context Context, matchingNode *CandidateNode, indicesToTraverse []*yaml.Node, prefs traversePreferences) (*list.List, error) { // call this if doc / alias like the other traverse | ||||||
| 	node := matchingNode.Node | 	node := matchingNode.Node | ||||||
| 	if node.Tag == "!!null" { | 	if node.Tag == "!!null" { | ||||||
| 		log.Debugf("OperatorArrayTraverse got a null - turning it into an empty array") | 		log.Debugf("OperatorArrayTraverse got a null - turning it into an empty array") | ||||||
| @ -111,28 +111,28 @@ func traverseArrayIndices(matchingNode *CandidateNode, indicesToTraverse []*yaml | |||||||
| 
 | 
 | ||||||
| 	if node.Kind == yaml.AliasNode { | 	if node.Kind == yaml.AliasNode { | ||||||
| 		matchingNode.Node = node.Alias | 		matchingNode.Node = node.Alias | ||||||
| 		return traverseArrayIndices(matchingNode, indicesToTraverse, prefs) | 		return traverseArrayIndices(context, matchingNode, indicesToTraverse, prefs) | ||||||
| 	} else if node.Kind == yaml.SequenceNode { | 	} else if node.Kind == yaml.SequenceNode { | ||||||
| 		return traverseArrayWithIndices(matchingNode, indicesToTraverse) | 		return traverseArrayWithIndices(matchingNode, indicesToTraverse) | ||||||
| 	} else if node.Kind == yaml.MappingNode { | 	} else if node.Kind == yaml.MappingNode { | ||||||
| 		return traverseMapWithIndices(matchingNode, indicesToTraverse, prefs) | 		return traverseMapWithIndices(context, matchingNode, indicesToTraverse, prefs) | ||||||
| 	} else if node.Kind == yaml.DocumentNode { | 	} else if node.Kind == yaml.DocumentNode { | ||||||
| 		return traverseArrayIndices(matchingNode.CreateChild(nil, matchingNode.Node.Content[0]), indicesToTraverse, prefs) | 		return traverseArrayIndices(context, matchingNode.CreateChild(nil, matchingNode.Node.Content[0]), indicesToTraverse, prefs) | ||||||
| 	} | 	} | ||||||
| 	log.Debugf("OperatorArrayTraverse skipping %v as its a %v", matchingNode, node.Tag) | 	log.Debugf("OperatorArrayTraverse skipping %v as its a %v", matchingNode, node.Tag) | ||||||
| 	return list.New(), nil | 	return list.New(), nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func traverseMapWithIndices(candidate *CandidateNode, indices []*yaml.Node, prefs traversePreferences) (*list.List, error) { | func traverseMapWithIndices(context Context, candidate *CandidateNode, indices []*yaml.Node, prefs traversePreferences) (*list.List, error) { | ||||||
| 	if len(indices) == 0 { | 	if len(indices) == 0 { | ||||||
| 		return traverseMap(candidate, "", prefs, true) | 		return traverseMap(context, candidate, "", prefs, true) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	var matchingNodeMap = list.New() | 	var matchingNodeMap = list.New() | ||||||
| 
 | 
 | ||||||
| 	for _, indexNode := range indices { | 	for _, indexNode := range indices { | ||||||
| 		log.Debug("traverseMapWithIndices: %v", indexNode.Value) | 		log.Debug("traverseMapWithIndices: %v", indexNode.Value) | ||||||
| 		newNodes, err := traverseMap(candidate, indexNode.Value, prefs, false) | 		newNodes, err := traverseMap(context, candidate, indexNode.Value, prefs, false) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return nil, err | 			return nil, err | ||||||
| 		} | 		} | ||||||
| @ -187,7 +187,7 @@ func keyMatches(key *yaml.Node, wantedKey string) bool { | |||||||
| 	return matchKey(key.Value, wantedKey) | 	return matchKey(key.Value, wantedKey) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func traverseMap(matchingNode *CandidateNode, key string, prefs traversePreferences, splat bool) (*list.List, error) { | func traverseMap(context Context, matchingNode *CandidateNode, key string, prefs traversePreferences, splat bool) (*list.List, error) { | ||||||
| 	var newMatches = orderedmap.NewOrderedMap() | 	var newMatches = orderedmap.NewOrderedMap() | ||||||
| 	err := doTraverseMap(newMatches, matchingNode, key, prefs, splat) | 	err := doTraverseMap(newMatches, matchingNode, key, prefs, splat) | ||||||
| 
 | 
 | ||||||
| @ -195,7 +195,7 @@ func traverseMap(matchingNode *CandidateNode, key string, prefs traversePreferen | |||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if !prefs.DontAutoCreate && newMatches.Len() == 0 { | 	if !prefs.DontAutoCreate && !context.DontAutoCreate && newMatches.Len() == 0 { | ||||||
| 		//no matches, create one automagically | 		//no matches, create one automagically | ||||||
| 		valueNode := &yaml.Node{Tag: "!!null", Kind: yaml.ScalarNode, Value: "null"} | 		valueNode := &yaml.Node{Tag: "!!null", Kind: yaml.ScalarNode, Value: "null"} | ||||||
| 		node := matchingNode.Node | 		node := matchingNode.Node | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user