This commit is contained in:
Mike Farah 2023-04-15 14:48:35 +10:00
parent 4ef84278a3
commit 49acb79ff1
3 changed files with 481 additions and 188 deletions

View File

@ -54,10 +54,8 @@ func (o *CandidateNode) copyFromYamlNode(node *yaml.Node, anchorMap map[string]*
log.Debug("set anchor %v to %v", o.Anchor, NodeToString(o)) log.Debug("set anchor %v to %v", o.Anchor, NodeToString(o))
} }
// o.Alias = TODO - find Alias in our own structure // its a single alias
// might need to be a post process thing if node.Alias != nil && node.Alias.Anchor != "" {
if node.Alias != nil && node.Alias.Value != "" {
o.Alias = anchorMap[node.Alias.Anchor] o.Alias = anchorMap[node.Alias.Anchor]
log.Debug("set alias to %v", NodeToString(anchorMap[node.Alias.Anchor])) log.Debug("set alias to %v", NodeToString(anchorMap[node.Alias.Anchor]))
} }

View File

@ -5,3 +5,299 @@ Use the `alias` and `anchor` operators to read and write yaml aliases and anchor
`yq` supports merge aliases (like `<<: *blah`) however this is no longer in the standard yaml spec (1.2) and so `yq` will automatically add the `!!merge` tag to these nodes as it is effectively a custom tag. `yq` supports merge aliases (like `<<: *blah`) however this is no longer in the standard yaml spec (1.2) and so `yq` will automatically add the `!!merge` tag to these nodes as it is effectively a custom tag.
## Merge one map
see https://yaml.org/type/merge.html
Given a sample.yml file of:
```yaml
- &CENTER
x: 1
y: 2
- &LEFT
x: 0
y: 2
- &BIG
r: 10
- &SMALL
r: 1
- !!merge <<: *CENTER
r: 10
```
then
```bash
yq '.[4] | explode(.)' sample.yml
```
will output
```yaml
x: 1
y: 2
r: 10
```
## Merge multiple maps
see https://yaml.org/type/merge.html
Given a sample.yml file of:
```yaml
- &CENTER
x: 1
y: 2
- &LEFT
x: 0
y: 2
- &BIG
r: 10
- &SMALL
r: 1
- !!merge <<:
- *CENTER
- *BIG
```
then
```bash
yq '.[4] | explode(.)' sample.yml
```
will output
```yaml
r: 10
x: 1
y: 2
```
## Override
see https://yaml.org/type/merge.html
Given a sample.yml file of:
```yaml
- &CENTER
x: 1
y: 2
- &LEFT
x: 0
y: 2
- &BIG
r: 10
- &SMALL
r: 1
- !!merge <<:
- *BIG
- *LEFT
- *SMALL
x: 1
```
then
```bash
yq '.[4] | explode(.)' sample.yml
```
will output
```yaml
r: 10
x: 1
y: 2
```
## Get anchor
Given a sample.yml file of:
```yaml
a: &billyBob cat
```
then
```bash
yq '.a | anchor' sample.yml
```
will output
```yaml
billyBob
```
## Set anchor
Given a sample.yml file of:
```yaml
a: cat
```
then
```bash
yq '.a anchor = "foobar"' sample.yml
```
will output
```yaml
a: &foobar cat
```
## Set anchor relatively using assign-update
Given a sample.yml file of:
```yaml
a:
b: cat
```
then
```bash
yq '.a anchor |= .b' sample.yml
```
will output
```yaml
a: &cat
b: cat
```
## Get alias
Given a sample.yml file of:
```yaml
b: &billyBob meow
a: *billyBob
```
then
```bash
yq '.a | alias' sample.yml
```
will output
```yaml
billyBob
```
## Set alias
Given a sample.yml file of:
```yaml
b: &meow purr
a: cat
```
then
```bash
yq '.a alias = "meow"' sample.yml
```
will output
```yaml
b: &meow purr
a: *meow
```
## Set alias to blank does nothing
Given a sample.yml file of:
```yaml
b: &meow purr
a: cat
```
then
```bash
yq '.a alias = ""' sample.yml
```
will output
```yaml
b: &meow purr
a: cat
```
## Set alias relatively using assign-update
Given a sample.yml file of:
```yaml
b: &meow purr
a:
f: meow
```
then
```bash
yq '.a alias |= .f' sample.yml
```
will output
```yaml
b: &meow purr
a: *meow
```
## Explode alias and anchor
Given a sample.yml file of:
```yaml
f:
a: &a cat
b: *a
```
then
```bash
yq 'explode(.f)' sample.yml
```
will output
```yaml
f:
a: cat
b: cat
```
## Explode with no aliases or anchors
Given a sample.yml file of:
```yaml
a: mike
```
then
```bash
yq 'explode(.a)' sample.yml
```
will output
```yaml
a: mike
```
## Explode with alias keys
Given a sample.yml file of:
```yaml
f:
a: &a cat
*a: b
```
then
```bash
yq 'explode(.f)' sample.yml
```
will output
```yaml
f:
a: cat
cat: b
```
## Explode with merge anchors
Given a sample.yml file of:
```yaml
foo: &foo
a: foo_a
thing: foo_thing
c: foo_c
bar: &bar
b: bar_b
thing: bar_thing
c: bar_c
foobarList:
b: foobarList_b
!!merge <<:
- *foo
- *bar
c: foobarList_c
foobar:
c: foobar_c
!!merge <<: *foo
thing: foobar_thing
```
then
```bash
yq 'explode(.)' sample.yml
```
will output
```yaml
foo:
a: foo_a
thing: foo_thing
c: foo_c
bar:
b: bar_b
thing: bar_thing
c: bar_c
foobarList:
b: bar_b
thing: foo_thing
c: foobarList_c
a: foo_a
foobar:
c: foo_c
a: foo_a
thing: foobar_thing
```

View File

@ -38,174 +38,173 @@ var anchorOperatorScenarios = []expressionScenario{
{ {
skipDoc: true, skipDoc: true,
description: "merge anchor not map", description: "merge anchor not map",
document: "a: &a\n - 0\nc:\n <<: [*a]\n", document: "a: &a\n - 500\nc:\n <<: [*a]\n",
expectedError: "merge anchor only supports maps, got !!seq instead", expectedError: "merge anchor only supports maps, got !!seq instead",
expression: "explode(.)", expression: "explode(.)",
}, },
// { {
// description: "Merge one map", description: "Merge one map",
// subdescription: "see https://yaml.org/type/merge.html", subdescription: "see https://yaml.org/type/merge.html",
// document: specDocument + "- << : *CENTER\n r: 10\n", document: specDocument + "- << : *CENTER\n r: 10\n",
// expression: ".[4] | explode(.)", expression: ".[4] | explode(.)",
// expected: []string{expectedSpecResult}, expected: []string{expectedSpecResult},
// }, },
// { {
// description: "Merge multiple maps", description: "Merge multiple maps",
// subdescription: "see https://yaml.org/type/merge.html", subdescription: "see https://yaml.org/type/merge.html",
// document: specDocument + "- << : [ *CENTER, *BIG ]\n", document: specDocument + "- << : [ *CENTER, *BIG ]\n",
// expression: ".[4] | explode(.)", expression: ".[4] | explode(.)",
// expected: []string{"D0, P[4], (!!map)::r: 10\nx: 1\ny: 2\n"}, expected: []string{"D0, P[4], (!!map)::r: 10\nx: 1\ny: 2\n"},
// }, },
// { {
// description: "Override", description: "Override",
// subdescription: "see https://yaml.org/type/merge.html", subdescription: "see https://yaml.org/type/merge.html",
// document: specDocument + "- << : [ *BIG, *LEFT, *SMALL ]\n x: 1\n", document: specDocument + "- << : [ *BIG, *LEFT, *SMALL ]\n x: 1\n",
// expression: ".[4] | explode(.)", expression: ".[4] | explode(.)",
// expected: []string{"D0, P[4], (!!map)::r: 10\nx: 1\ny: 2\n"}, expected: []string{"D0, P[4], (!!map)::r: 10\nx: 1\ny: 2\n"},
// }, },
// { {
// description: "Get anchor", description: "Get anchor",
// document: `a: &billyBob cat`, document: `a: &billyBob cat`,
// expression: `.a | anchor`, expression: `.a | anchor`,
// expected: []string{ expected: []string{
// "D0, P[a], (!!str)::billyBob\n", "D0, P[a], (!!str)::billyBob\n",
// }, },
// }, },
// { {
// description: "Set anchor", description: "Set anchor",
// document: `a: cat`, document: `a: cat`,
// expression: `.a anchor = "foobar"`, expression: `.a anchor = "foobar"`,
// expected: []string{ expected: []string{
// "D0, P[], (doc)::a: &foobar cat\n", "D0, P[], (doc)::a: &foobar cat\n",
// }, },
// }, },
// { {
// description: "Set anchor relatively using assign-update", description: "Set anchor relatively using assign-update",
// document: `a: {b: cat}`, document: `a: {b: cat}`,
// expression: `.a anchor |= .b`, expression: `.a anchor |= .b`,
// expected: []string{ expected: []string{
// "D0, P[], (doc)::a: &cat {b: cat}\n", "D0, P[], (doc)::a: &cat {b: cat}\n",
// }, },
// }, },
// { {
// skipDoc: true, skipDoc: true,
// document: `a: {c: cat}`, document: `a: {c: cat}`,
// expression: `.a anchor |= .b`, expression: `.a anchor |= .b`,
// expected: []string{ expected: []string{
// "D0, P[], (doc)::a: {c: cat}\n", "D0, P[], (doc)::a: {c: cat}\n",
// }, },
// }, },
// { {
// skipDoc: true, skipDoc: true,
// document: `a: {c: cat}`, document: `a: {c: cat}`,
// expression: `.a anchor = .b`, expression: `.a anchor = .b`,
// expected: []string{ expected: []string{
// "D0, P[], (doc)::a: {c: cat}\n", "D0, P[], (doc)::a: {c: cat}\n",
// }, },
// }, },
// { {
// description: "Get alias", description: "Get alias",
// document: `{b: &billyBob meow, a: *billyBob}`, document: `{b: &billyBob meow, a: *billyBob}`,
// expression: `.a | alias`, expression: `.a | alias`,
// expected: []string{ expected: []string{
// "D0, P[a], (!!str)::billyBob\n", "D0, P[a], (!!str)::billyBob\n",
// }, },
// }, },
// { {
// description: "Set alias", description: "Set alias",
// document: `{b: &meow purr, a: cat}`, document: `{b: &meow purr, a: cat}`,
// expression: `.a alias = "meow"`, expression: `.a alias = "meow"`,
// expected: []string{ expected: []string{
// "D0, P[], (doc)::{b: &meow purr, a: *meow}\n", "D0, P[], (doc)::{b: &meow purr, a: *meow}\n",
// }, },
// }, },
// { {
// description: "Set alias to blank does nothing", description: "Set alias to blank does nothing",
// document: `{b: &meow purr, a: cat}`, document: `{b: &meow purr, a: cat}`,
// expression: `.a alias = ""`, expression: `.a alias = ""`,
// expected: []string{ expected: []string{
// "D0, P[], (doc)::{b: &meow purr, a: cat}\n", "D0, P[], (doc)::{b: &meow purr, a: cat}\n",
// }, },
// }, },
// { {
// skipDoc: true, skipDoc: true,
// document: `{b: &meow purr, a: cat}`, document: `{b: &meow purr, a: cat}`,
// expression: `.a alias = .c`, expression: `.a alias = .c`,
// expected: []string{ expected: []string{
// "D0, P[], (doc)::{b: &meow purr, a: cat}\n", "D0, P[], (doc)::{b: &meow purr, a: cat}\n",
// }, },
// }, },
// { {
// skipDoc: true, skipDoc: true,
// document: `{b: &meow purr, a: cat}`, document: `{b: &meow purr, a: cat}`,
// expression: `.a alias |= .c`, expression: `.a alias |= .c`,
// expected: []string{ expected: []string{
// "D0, P[], (doc)::{b: &meow purr, a: cat}\n", "D0, P[], (doc)::{b: &meow purr, a: cat}\n",
// }, },
// }, },
// { {
// description: "Set alias relatively using assign-update", description: "Set alias relatively using assign-update",
// document: `{b: &meow purr, a: {f: meow}}`, document: `{b: &meow purr, a: {f: meow}}`,
// expression: `.a alias |= .f`, expression: `.a alias |= .f`,
// expected: []string{ expected: []string{
// "D0, P[], (doc)::{b: &meow purr, a: *meow}\n", "D0, P[], (doc)::{b: &meow purr, a: *meow}\n",
// }, },
// }, },
// { {
// description: "Explode alias and anchor", description: "Explode alias and anchor",
// document: `{f : {a: &a cat, b: *a}}`, document: `{f : {a: &a cat, b: *a}}`,
// expression: `explode(.f)`, expression: `explode(.f)`,
// expected: []string{ expected: []string{
// "D0, P[], (doc)::{f: {a: cat, b: cat}}\n", "D0, P[], (doc)::{f: {a: cat, b: cat}}\n",
// }, },
// }, },
// { {
// description: "Explode with no aliases or anchors", description: "Explode with no aliases or anchors",
// document: `a: mike`, document: `a: mike`,
// expression: `explode(.a)`, expression: `explode(.a)`,
// expected: []string{ expected: []string{
// "D0, P[], (doc)::a: mike\n", "D0, P[], (doc)::a: mike\n",
// }, },
// }, },
// { {
// description: "Explode with alias keys", description: "Explode with alias keys",
// document: `{f : {a: &a cat, *a: b}}`, document: `{f : {a: &a cat, *a: b}}`,
// expression: `explode(.f)`, expression: `explode(.f)`,
// expected: []string{ expected: []string{
// "D0, P[], (doc)::{f: {a: cat, cat: b}}\n", "D0, P[], (doc)::{f: {a: cat, cat: b}}\n",
// }, },
// }, },
// { {
// description: "Explode with merge anchors", description: "Explode with merge anchors",
// document: mergeDocSample, document: mergeDocSample,
// expression: `explode(.)`, expression: `explode(.)`,
// expected: []string{`D0, P[], (doc)::foo: expected: []string{`D0, P[], (doc)::foo:
// a: foo_a a: foo_a
// thing: foo_thing thing: foo_thing
// c: foo_c c: foo_c
//
// bar: bar:
//
// b: bar_b b: bar_b
// thing: bar_thing thing: bar_thing
// c: bar_c c: bar_c
//
// foobarList: foobarList:
//
// b: bar_b b: bar_b
// thing: foo_thing thing: foo_thing
// c: foobarList_c c: foobarList_c
// a: foo_a a: foo_a
//
// foobar: foobar:
//
// c: foo_c c: foo_c
// a: foo_a a: foo_a
// thing: foobar_thing thing: foobar_thing
//
// `}, `},
// },
// },
// { // {
// skipDoc: true, // skipDoc: true,
// document: mergeDocSample, // document: mergeDocSample,