Compare commits

...

5 Commits

Author SHA1 Message Date
Joeseph Grey
45190fd7f3
Merge 0cc5c19843 into e2f1d5ccf7 2026-07-01 09:09:52 -06:00
dependabot[bot]
e2f1d5ccf7
Bump go.yaml.in/yaml/v4 from 4.0.0-rc.5 to 4.0.0-rc.6 (#2759)
Bumps [go.yaml.in/yaml/v4](https://github.com/yaml/go-yaml) from 4.0.0-rc.5 to 4.0.0-rc.6.
- [Commits](https://github.com/yaml/go-yaml/compare/v4.0.0-rc.5...v4.0.0-rc.6)

---
updated-dependencies:
- dependency-name: go.yaml.in/yaml/v4
  dependency-version: 4.0.0-rc.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-29 16:54:05 +10:00
dependabot[bot]
16f149b351
Bump github.com/pelletier/go-toml/v2 from 2.4.0 to 2.4.2 (#2762)
Bumps [github.com/pelletier/go-toml/v2](https://github.com/pelletier/go-toml) from 2.4.0 to 2.4.2.
- [Release notes](https://github.com/pelletier/go-toml/releases)
- [Commits](https://github.com/pelletier/go-toml/compare/v2.4.0...v2.4.2)

---
updated-dependencies:
- dependency-name: github.com/pelletier/go-toml/v2
  dependency-version: 2.4.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-29 16:53:39 +10:00
dependabot[bot]
5da9215306
Bump actions/setup-go from 6.4.0 to 6.5.0 (#2763)
Bumps [actions/setup-go](https://github.com/actions/setup-go) from 6.4.0 to 6.5.0.
- [Release notes](https://github.com/actions/setup-go/releases)
- [Commits](4a3601121d...924ae3a1cd)

---
updated-dependencies:
- dependency-name: actions/setup-go
  dependency-version: 6.5.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-29 16:53:18 +10:00
StressTestor
0cc5c19843 fix: apply per-candidate index when traversing arrays/maps by a streamed index
`$o[.]` over a streamed context (e.g. `keys[] | $o[.]`) only returned the
first match. The index expression yields one index set per incoming
candidate, but traverseArrayOperator used only the first set
(rhs.MatchingNodes.Front()), dropping the rest.

Pair each index set with its candidate: when the LHS has one node per
candidate (e.g. `.[] | .[idx]`) each node is traversed with its own index
set; when the LHS collapses to a single node (a variable) it is traversed
against every index set. Covers both arrays and maps.

Fixes #2593.
2026-06-15 16:00:44 -06:00
6 changed files with 61 additions and 19 deletions

View File

@ -37,7 +37,7 @@ jobs:
steps:
- name: Set up Go
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6.5.0
with:
go-version: '^1.20'
id: go

View File

@ -15,7 +15,7 @@ jobs:
id-token: write
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
- uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6.5.0
with:
go-version: '^1.20'
check-latest: true

4
go.mod
View File

@ -13,13 +13,13 @@ require (
github.com/hashicorp/hcl/v2 v2.24.0
github.com/jinzhu/copier v0.4.0
github.com/magiconair/properties v1.8.10
github.com/pelletier/go-toml/v2 v2.4.0
github.com/pelletier/go-toml/v2 v2.4.2
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e
github.com/spf13/cobra v1.10.2
github.com/spf13/pflag v1.0.10
github.com/yuin/gopher-lua v1.1.2
github.com/zclconf/go-cty v1.18.1
go.yaml.in/yaml/v4 v4.0.0-rc.5
go.yaml.in/yaml/v4 v4.0.0-rc.6
golang.org/x/mod v0.37.0
golang.org/x/net v0.56.0
golang.org/x/text v0.38.0

8
go.sum
View File

@ -46,8 +46,8 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0=
github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0=
github.com/pelletier/go-toml/v2 v2.4.0 h1:Mwu0mAkUKbittDs3/ADDWXqMmq3EOK2VHiuCkV00Row=
github.com/pelletier/go-toml/v2 v2.4.0/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
github.com/pelletier/go-toml/v2 v2.4.2 h1:M2fKKbmyvI+hGId/D0W64qDBMVhJnNR10O5gIbMc//Q=
github.com/pelletier/go-toml/v2 v2.4.2/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e h1:aoZm08cpOy4WuID//EZDgcC4zIxODThtZNPirFr42+A=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
@ -68,8 +68,8 @@ github.com/zclconf/go-cty v1.18.1/go.mod h1:qpnV6EDNgC1sns/AleL1fvatHw72j+S+nS+M
github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940 h1:4r45xpDWB6ZMSMNJFMOjqrGHynW3DIBuR2H9j0ug+Mo=
github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940/go.mod h1:CmBdvvj3nqzfzJ6nTCIwDTPZ56aVGvDrmztiO5g3qrM=
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
go.yaml.in/yaml/v4 v4.0.0-rc.5 h1:JVliQq9EGOYaTgMi+k8BhUJyqcGk4ZqeuiN1Cirba9c=
go.yaml.in/yaml/v4 v4.0.0-rc.5/go.mod h1:aZqd9kCMsGL7AuUv/m/PvWLdg5sjJsZ4oHDEnfPPfY0=
go.yaml.in/yaml/v4 v4.0.0-rc.6 h1:1h7H1ohdUh93/FyE4YaDa1Zh64K6VVbjF4K6WUxMtH4=
go.yaml.in/yaml/v4 v4.0.0-rc.6/go.mod h1:aZqd9kCMsGL7AuUv/m/PvWLdg5sjJsZ4oHDEnfPPfY0=
golang.org/x/mod v0.37.0 h1:vF1DjpVEshcIqoEaauuHebaLk1O1forxjxBaVn884JQ=
golang.org/x/mod v0.37.0/go.mod h1:m8S8VeM9r4dzDwjrKO0a1sZP3YjeMamRRlD+fmR2Q/0=
golang.org/x/net v0.56.0 h1:Rw8j/hFzGvJUZwNBXnAtf5sVDVt+65SK2C7IxCxZt5o=

View File

@ -111,10 +111,10 @@ func traverseArrayOperator(d *dataTreeNavigator, context Context, expressionNode
return Context{}, err
}
// rhs is a collect expression that will yield indices to retrieve of the arrays
// rhs is a collect expression that yields the indices to retrieve. It is
// evaluated over the whole context, producing one index set per incoming
// candidate.
rhs, err := d.GetMatchingNodes(context.ReadOnlyClone(), expressionNode.RHS)
if err != nil {
return Context{}, err
}
@ -123,16 +123,37 @@ func traverseArrayOperator(d *dataTreeNavigator, context Context, expressionNode
if expressionNode.Operation.Preferences != nil {
prefs = expressionNode.Operation.Preferences.(traversePreferences)
}
var indicesToTraverse = rhs.MatchingNodes.Front().Value.(*CandidateNode).Content
log.Debugf("indicesToTraverse %v", len(indicesToTraverse))
//now we traverse the result of the lhs against the indices we found
result, err := traverseNodesWithArrayIndices(lhs, indicesToTraverse, prefs)
if err != nil {
return Context{}, err
results := list.New()
if lhs.MatchingNodes.Len() == rhs.MatchingNodes.Len() {
// One index set per LHS node (both derive from the same context):
// traverse each LHS node with its own index set. Previously only the
// first index set was used, so a context-dependent index like `$o[.]`
// over a `keys[]` stream dropped every match but the first (#2593).
rhsEl := rhs.MatchingNodes.Front()
for lhsEl := lhs.MatchingNodes.Front(); lhsEl != nil; lhsEl = lhsEl.Next() {
indicesToTraverse := rhsEl.Value.(*CandidateNode).Content
result, err := traverseNodesWithArrayIndices(context.SingleChildContext(lhsEl.Value.(*CandidateNode)), indicesToTraverse, prefs)
if err != nil {
return Context{}, err
}
results.PushBackList(result.MatchingNodes)
rhsEl = rhsEl.Next()
}
} else {
// LHS collapsed to a single node (e.g. a variable) while the index
// varies per candidate: traverse the LHS against every index set.
for rhsEl := rhs.MatchingNodes.Front(); rhsEl != nil; rhsEl = rhsEl.Next() {
indicesToTraverse := rhsEl.Value.(*CandidateNode).Content
result, err := traverseNodesWithArrayIndices(lhs, indicesToTraverse, prefs)
if err != nil {
return Context{}, err
}
results.PushBackList(result.MatchingNodes)
}
}
return context.ChildContext(result.MatchingNodes), nil
return context.ChildContext(results), nil
}
func traverseNodesWithArrayIndices(context Context, indicesToTraverse []*CandidateNode, prefs traversePreferences) (Context, error) {

View File

@ -675,6 +675,27 @@ var traversePathOperatorScenarios = []expressionScenario{
expression: ". = (.x = 1)",
expectedError: "alias cycle detected",
},
{
// Regression test for https://github.com/mikefarah/yq/issues/2593
// A context-dependent index (here the streamed key) must be applied
// per candidate; previously only the first index was used.
skipDoc: true,
document: `["a","b"]`,
expression: `. as $o | keys[] | $o[.]`,
expected: []string{
"D0, P[0], (!!str)::a\n",
"D0, P[1], (!!str)::b\n",
},
},
{
skipDoc: true,
document: `{"x": 1, "y": 2}`,
expression: `. as $o | keys[] | $o[.]`,
expected: []string{
"D0, P[x], (!!int)::1\n",
"D0, P[y], (!!int)::2\n",
},
},
}
func TestTraversePathOperatorScenarios(t *testing.T) {