From 3f58c4bc38058a47d1e84f55bc2fd9d9bdf7eea5 Mon Sep 17 00:00:00 2001 From: Mike Farah Date: Wed, 6 Jan 2021 20:30:48 +1100 Subject: [PATCH] Can assign-update aliases and anchors --- pkg/yqlib/doc/Anchor and Alias Operators.md | 33 +++++++++++++ pkg/yqlib/operator_anchors_aliases.go | 54 ++++++++++++++++----- pkg/yqlib/operator_anchors_aliases_test.go | 16 ++++++ 3 files changed, 90 insertions(+), 13 deletions(-) diff --git a/pkg/yqlib/doc/Anchor and Alias Operators.md b/pkg/yqlib/doc/Anchor and Alias Operators.md index b7a6c707..ea04f11e 100644 --- a/pkg/yqlib/doc/Anchor and Alias Operators.md +++ b/pkg/yqlib/doc/Anchor and Alias Operators.md @@ -31,6 +31,22 @@ will output a: &foobar cat ``` +## Set anchor relatively using assign-update +Given a sample.yml file of: +```yaml +a: + b: cat +``` +then +```bash +yq eval '.a anchor |= .b' sample.yml +``` +will output +```yaml +a: &cat + b: cat +``` + ## Get alias Given a sample.yml file of: ```yaml @@ -62,6 +78,23 @@ b: &meow purr a: *meow ``` +## Set alias relatively using assign-update +Given a sample.yml file of: +```yaml +b: &meow purr +a: + f: meow +``` +then +```bash +yq eval '.a alias |= .f' sample.yml +``` +will output +```yaml +b: &meow purr +a: *meow +``` + ## Explode alias and anchor Given a sample.yml file of: ```yaml diff --git a/pkg/yqlib/operator_anchors_aliases.go b/pkg/yqlib/operator_anchors_aliases.go index d1ae0ea1..e558c222 100644 --- a/pkg/yqlib/operator_anchors_aliases.go +++ b/pkg/yqlib/operator_anchors_aliases.go @@ -3,20 +3,22 @@ package yqlib import ( "container/list" - "gopkg.in/yaml.v3" + yaml "gopkg.in/yaml.v3" ) func AssignAliasOperator(d *dataTreeNavigator, matchingNodes *list.List, pathNode *PathTreeNode) (*list.List, error) { log.Debugf("AssignAlias operator!") - rhs, err := d.GetMatchingNodes(matchingNodes, pathNode.Rhs) - if err != nil { - return nil, err - } aliasName := "" - if rhs.Front() != nil { - aliasName = rhs.Front().Value.(*CandidateNode).Node.Value + if !pathNode.Operation.UpdateAssign { + rhs, err := d.GetMatchingNodes(matchingNodes, pathNode.Rhs) + if err != nil { + return nil, err + } + if rhs.Front() != nil { + aliasName = rhs.Front().Value.(*CandidateNode).Node.Value + } } lhs, err := d.GetMatchingNodes(matchingNodes, pathNode.Lhs) @@ -28,6 +30,17 @@ func AssignAliasOperator(d *dataTreeNavigator, matchingNodes *list.List, pathNod for el := lhs.Front(); el != nil; el = el.Next() { candidate := el.Value.(*CandidateNode) log.Debugf("Setting aliasName : %v", candidate.GetKey()) + + if pathNode.Operation.UpdateAssign { + rhs, err := d.GetMatchingNodes(nodeToMap(candidate), pathNode.Rhs) + if err != nil { + return nil, err + } + if rhs.Front() != nil { + aliasName = rhs.Front().Value.(*CandidateNode).Node.Value + } + } + candidate.Node.Kind = yaml.AliasNode candidate.Node.Value = aliasName } @@ -51,13 +64,16 @@ func AssignAnchorOperator(d *dataTreeNavigator, matchingNodes *list.List, pathNo log.Debugf("AssignAnchor operator!") - rhs, err := d.GetMatchingNodes(matchingNodes, pathNode.Rhs) - if err != nil { - return nil, err - } anchorName := "" - if rhs.Front() != nil { - anchorName = rhs.Front().Value.(*CandidateNode).Node.Value + if !pathNode.Operation.UpdateAssign { + rhs, err := d.GetMatchingNodes(matchingNodes, pathNode.Rhs) + if err != nil { + return nil, err + } + + if rhs.Front() != nil { + anchorName = rhs.Front().Value.(*CandidateNode).Node.Value + } } lhs, err := d.GetMatchingNodes(matchingNodes, pathNode.Lhs) @@ -69,6 +85,18 @@ func AssignAnchorOperator(d *dataTreeNavigator, matchingNodes *list.List, pathNo for el := lhs.Front(); el != nil; el = el.Next() { candidate := el.Value.(*CandidateNode) log.Debugf("Setting anchorName of : %v", candidate.GetKey()) + + if pathNode.Operation.UpdateAssign { + rhs, err := d.GetMatchingNodes(nodeToMap(candidate), pathNode.Rhs) + if err != nil { + return nil, err + } + + if rhs.Front() != nil { + anchorName = rhs.Front().Value.(*CandidateNode).Node.Value + } + } + candidate.Node.Anchor = anchorName } return matchingNodes, nil diff --git a/pkg/yqlib/operator_anchors_aliases_test.go b/pkg/yqlib/operator_anchors_aliases_test.go index 7cbde50a..2af815d3 100644 --- a/pkg/yqlib/operator_anchors_aliases_test.go +++ b/pkg/yqlib/operator_anchors_aliases_test.go @@ -21,6 +21,14 @@ var anchorOperatorScenarios = []expressionScenario{ "D0, P[], (doc)::a: &foobar cat\n", }, }, + { + description: "Set anchor relatively using assign-update", + document: `a: {b: cat}`, + expression: `.a anchor |= .b`, + expected: []string{ + "D0, P[], (doc)::a: &cat {b: cat}\n", + }, + }, { description: "Get alias", document: `{b: &billyBob meow, a: *billyBob}`, @@ -37,6 +45,14 @@ var anchorOperatorScenarios = []expressionScenario{ "D0, P[], (doc)::{b: &meow purr, a: *meow}\n", }, }, + { + description: "Set alias relatively using assign-update", + document: `{b: &meow purr, a: {f: meow}}`, + expression: `.a alias |= .f`, + expected: []string{ + "D0, P[], (doc)::{b: &meow purr, a: *meow}\n", + }, + }, { description: "Explode alias and anchor", document: `{f : {a: &a cat, b: *a}}`,