Compare commits

...

7 Commits

Author SHA1 Message Date
Navid
ff40a023cc Fix out of range panic in yaml decoder 2025-09-09 20:45:53 +10:00
Mike Farah
7d49d408ef Added parents operator 2025-09-09 20:27:11 +10:00
Mike Farah
6251e95af8 Bumping version 2025-09-08 20:05:05 +10:00
Mike Farah
b2155ebb00 Preparing release 2025-09-08 20:04:59 +10:00
Mike Farah
911e3942e3 Bumping pflag 2025-09-08 20:01:58 +10:00
Louis Lombard
35d338cc24 modify empty table decode 2025-09-08 20:00:31 +10:00
dependabot[bot]
6d7aa384c4 Bump github.com/spf13/cobra from 1.9.1 to 1.10.1
Bumps [github.com/spf13/cobra](https://github.com/spf13/cobra) from 1.9.1 to 1.10.1.
- [Release notes](https://github.com/spf13/cobra/releases)
- [Commits](https://github.com/spf13/cobra/compare/v1.9.1...v1.10.1)

---
updated-dependencies:
- dependency-name: github.com/spf13/cobra
  dependency-version: 1.10.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-08 19:45:13 +10:00
13 changed files with 108 additions and 17 deletions

View File

@ -11,7 +11,7 @@ var (
GitDescribe string GitDescribe string
// Version is main version number that is being run at the moment. // Version is main version number that is being run at the moment.
Version = "v4.47.1" Version = "v4.47.2"
// VersionPrerelease is a pre-release marker for the version. If this is "" (empty string) // VersionPrerelease is a pre-release marker for the version. If this is "" (empty string)
// then it means that it is a final release. Otherwise, this is a pre-release // then it means that it is a final release. Otherwise, this is a pre-release

4
go.mod
View File

@ -14,8 +14,8 @@ require (
github.com/magiconair/properties v1.8.10 github.com/magiconair/properties v1.8.10
github.com/pelletier/go-toml/v2 v2.2.4 github.com/pelletier/go-toml/v2 v2.2.4
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e
github.com/spf13/cobra v1.9.1 github.com/spf13/cobra v1.10.1
github.com/spf13/pflag v1.0.7 github.com/spf13/pflag v1.0.10
github.com/yuin/gopher-lua v1.1.1 github.com/yuin/gopher-lua v1.1.1
go.yaml.in/yaml/v3 v3.0.4 go.yaml.in/yaml/v3 v3.0.4
golang.org/x/net v0.43.0 golang.org/x/net v0.43.0

10
go.sum
View File

@ -40,11 +40,11 @@ github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsK
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo= github.com/spf13/cobra v1.10.1 h1:lJeBwCfmrnXthfAupyUTzJ/J4Nc1RsHC/mSRU2dll/s=
github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0= github.com/spf13/cobra v1.10.1/go.mod h1:7SmJGaTHFVBY0jW4NXGluQoLvhqFQM+6XSKD+P4XaB0=
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/pflag v1.0.7 h1:vN6T9TfwStFPFM5XzjsvmzZkLuaLX+HS+0SeFLRgU6M= github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
github.com/spf13/pflag v1.0.7/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=

View File

@ -282,13 +282,13 @@ func (dec *tomlDecoder) processTable(currentNode *toml.Node) (bool, error) {
tableValue = dec.parser.Expression() tableValue = dec.parser.Expression()
// next expression is not table data, so we are done // next expression is not table data, so we are done
if tableValue.Kind != toml.KeyValue { if tableValue.Kind != toml.KeyValue {
log.Debug("got an empty table, returning") log.Debug("got an empty table")
return true, nil runAgainstCurrentExp = true
} } else {
runAgainstCurrentExp, err = dec.decodeKeyValuesIntoMap(tableNodeValue, tableValue)
runAgainstCurrentExp, err = dec.decodeKeyValuesIntoMap(tableNodeValue, tableValue) if err != nil && !errors.Is(err, io.EOF) {
if err != nil && !errors.Is(err, io.EOF) { return false, err
return false, err }
} }
} }

View File

@ -129,6 +129,8 @@ func (dec *yamlDecoder) Decode() (*CandidateNode, error) {
return nil, err return nil, err
} else if err != nil { } else if err != nil {
return nil, err return nil, err
} else if len(yamlNode.Content) == 0 {
return nil, errors.New("yaml node has no content")
} }
candidateNode := CandidateNode{document: dec.documentIndex} candidateNode := CandidateNode{document: dec.documentIndex}

View File

@ -56,6 +56,29 @@ will output
sam sam
``` ```
## Get parents
Match all parents
Given a sample.yml file of:
```yaml
a:
b:
c: cat
```
then
```bash
yq '.a.b.c | parents' sample.yml
```
will output
```yaml
- c: cat
- b:
c: cat
- a:
b:
c: cat
```
## N-th parent ## N-th parent
You can optionally supply the number of levels to go up for the parent, the default being 1. You can optionally supply the number of levels to go up for the parent, the default being 1.

View File

@ -130,6 +130,7 @@ var participleYqRules = []*participleYqRule{
simpleOp("contains", containsOpType), simpleOp("contains", containsOpType),
simpleOp("split", splitStringOpType), simpleOp("split", splitStringOpType),
simpleOp("parents", getParentsOpType),
{"ParentWithLevel", `parent\([0-9]+\)`, parentWithLevel(), 0}, {"ParentWithLevel", `parent\([0-9]+\)`, parentWithLevel(), 0},
{"ParentWithDefaultLevel", `parent`, parentWithDefaultLevel(), 0}, {"ParentWithDefaultLevel", `parent`, parentWithDefaultLevel(), 0},

View File

@ -128,6 +128,7 @@ var getKindOpType = &operationType{Type: "GET_KIND", NumArgs: 0, Precedence: 50,
var getKeyOpType = &operationType{Type: "GET_KEY", NumArgs: 0, Precedence: 50, Handler: getKeyOperator} var getKeyOpType = &operationType{Type: "GET_KEY", NumArgs: 0, Precedence: 50, Handler: getKeyOperator}
var isKeyOpType = &operationType{Type: "IS_KEY", NumArgs: 0, Precedence: 50, Handler: isKeyOperator} var isKeyOpType = &operationType{Type: "IS_KEY", NumArgs: 0, Precedence: 50, Handler: isKeyOperator}
var getParentOpType = &operationType{Type: "GET_PARENT", NumArgs: 0, Precedence: 50, Handler: getParentOperator} var getParentOpType = &operationType{Type: "GET_PARENT", NumArgs: 0, Precedence: 50, Handler: getParentOperator}
var getParentsOpType = &operationType{Type: "GET_PARENTS", NumArgs: 0, Precedence: 50, Handler: getParentsOperator}
var getCommentOpType = &operationType{Type: "GET_COMMENT", NumArgs: 0, Precedence: 50, Handler: getCommentsOperator} var getCommentOpType = &operationType{Type: "GET_COMMENT", NumArgs: 0, Precedence: 50, Handler: getCommentsOperator}
var getAnchorOpType = &operationType{Type: "GET_ANCHOR", NumArgs: 0, Precedence: 50, Handler: getAnchorOperator} var getAnchorOpType = &operationType{Type: "GET_ANCHOR", NumArgs: 0, Precedence: 50, Handler: getAnchorOperator}

View File

@ -6,6 +6,26 @@ type parentOpPreferences struct {
Level int Level int
} }
func getParentsOperator(_ *dataTreeNavigator, context Context, _ *ExpressionNode) (Context, error) {
log.Debugf("getParentsOperator")
var results = list.New()
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
candidate := el.Value.(*CandidateNode)
parentsList := &CandidateNode{Kind: SequenceNode, Tag: "!!seq"}
parent := candidate.Parent
for parent != nil {
parentsList.AddChild(parent)
parent = parent.Parent
}
results.PushBack(parentsList)
}
return context.ChildContext(results), nil
}
func getParentOperator(_ *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) { func getParentOperator(_ *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
log.Debugf("getParentOperator") log.Debugf("getParentOperator")

View File

@ -29,6 +29,15 @@ var parentOperatorScenarios = []expressionScenario{
"D0, P[b name], (!!str)::sam\n", "D0, P[b name], (!!str)::sam\n",
}, },
}, },
{
description: "Get parents",
subdescription: "Match all parents",
document: "{a: {b: {c: cat} } }",
expression: `.a.b.c | parents`,
expected: []string{
"D0, P[], (!!seq)::- {c: cat}\n- {b: {c: cat}}\n- {a: {b: {c: cat}}}\n",
},
},
{ {
description: "N-th parent", description: "N-th parent",
subdescription: "You can optionally supply the number of levels to go up for the parent, the default being 1.", subdescription: "You can optionally supply the number of levels to go up for the parent, the default being 1.",

View File

@ -23,6 +23,7 @@ street = "first street"
[owner] [owner]
name = "Tom Preston-Werner" name = "Tom Preston-Werner"
` `
var expectedTableArrayBeforeOwners = `owner: var expectedTableArrayBeforeOwners = `owner:
addresses: addresses:
- street: first street - street: first street
@ -67,6 +68,29 @@ var emptyTable = `
var emptyTableExpected = "dependencies: {}\n" var emptyTableExpected = "dependencies: {}\n"
var multipleEmptyTables = `
[firstEmptyTable]
[firstTableWithContent]
key = "value"
[secondEmptyTable]
[thirdEmptyTable]
[secondTableWithContent]
key = "value"
[fourthEmptyTable]
[fifthEmptyTable]
`
var expectedMultipleEmptyTables = `firstEmptyTable: {}
firstTableWithContent:
key: value
secondEmptyTable: {}
thirdEmptyTable: {}
secondTableWithContent:
key: value
fourthEmptyTable: {}
fifthEmptyTable: {}
`
var sampleWithHeader = ` var sampleWithHeader = `
[servers] [servers]
@ -238,6 +262,13 @@ var tomlScenarios = []formatScenario{
expected: expectedSampleWithHeader, expected: expectedSampleWithHeader,
scenarioType: "decode", scenarioType: "decode",
}, },
{
description: "Parse: multiple empty tables",
skipDoc: true,
input: multipleEmptyTables,
expected: expectedMultipleEmptyTables,
scenarioType: "decode",
},
} }
func testTomlScenario(t *testing.T, s formatScenario) { func testTomlScenario(t *testing.T, s formatScenario) {

View File

@ -1,3 +1,7 @@
4.47.2:
- Conversion from TOML to JSON no longer omits empty tables #2459 (thanks @louislouislouislouis)
- Bumped dependencies
4.47.1: 4.47.1:
- Fixed merge anchor behaviour (`<<`); #2404, #2110, #2386, #2178 Huge thanks to @stevenwdv! - Fixed merge anchor behaviour (`<<`); #2404, #2110, #2386, #2178 Huge thanks to @stevenwdv!
Note that you will need to set --yaml-fix-merge-anchor-to-spec to see the fixes Note that you will need to set --yaml-fix-merge-anchor-to-spec to see the fixes

View File

@ -1,5 +1,5 @@
name: yq name: yq
version: 'v4.47.1' version: 'v4.47.2'
summary: A lightweight and portable command-line data file processor summary: A lightweight and portable command-line data file processor
description: | description: |
`yq` uses [jq](https://github.com/stedolan/jq) like syntax but works with yaml, json, xml, csv, properties and TOML files. `yq` uses [jq](https://github.com/stedolan/jq) like syntax but works with yaml, json, xml, csv, properties and TOML files.
@ -27,6 +27,6 @@ parts:
build-environment: build-environment:
- CGO_ENABLED: 0 - CGO_ENABLED: 0
source: https://github.com/mikefarah/yq.git source: https://github.com/mikefarah/yq.git
source-tag: v4.47.1 source-tag: v4.47.2
build-snaps: build-snaps:
- go/latest/stable - go/latest/stable