Skip to content

Fix for #2677#2705

Open
W-Floyd wants to merge 4 commits into
mikefarah:masterfrom
W-Floyd:fix-2677
Open

Fix for #2677#2705
W-Floyd wants to merge 4 commits into
mikefarah:masterfrom
W-Floyd:fix-2677

Conversation

@W-Floyd
Copy link
Copy Markdown

@W-Floyd W-Floyd commented May 12, 2026

Depends on yaml/go-yaml#348

Comment on lines +49 to 54
if stringValue == "<<" {
node.Tag = "!!merge"
} else {
node.Tag = "!!str"
}
return node
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add tests for this?

Because it's not really obvious

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a test that replicates what's documented in #2677, will look at doing a more targeted test that exercises just this functionality.

@W-Floyd
Copy link
Copy Markdown
Author

W-Floyd commented May 13, 2026

Changed the existing tests to pass given the changes in yaml/go-yaml#348, added a test for the given fix, and found a corner case to improve specific to the example with multiplication. I am still very new to both the go-yaml and yq codebases, and neither am I intimately familiar with the YAML spec, so sorry for the back and forth, and I appreciate the feedback!


It seems when yq autocreates a << key it was creating it with tag=!!str, which go-yaml was handling for us before. Given the changes in http://github.com/yaml/go-yaml/commit/fbd745be58df058ec8eb7d7b42468458f8d8ec64, we need to give it tag=!!merge ourselves. Note that this is only for the nodes yq creates itself, hence why nested alias/anchor stuff (that were handled by go-yaml wholesale) kept working.

Regarding mergeObjects in operator_multiply.go, during a merge operation (*+), the code iterated over all nodes from the RHS and skipped any with tag=!!merge. It seems the intent was to avoid accidentally following merge anchors, but since DontFollowAlias: true is already set on the traversal, that protection was redundant. The problem was that skipping the << key node meant yq never ran the key assignment for it — so instead of copying the source key's style, it autocreated a fresh one with Style=0, silently dropping the explicit !!merge annotation. The fix narrows the skip to !candidate.IsMapKey: values tagged !!merge (hypothetical) are still skipped, but << key nodes are processed normally, and UpdateFrom copies both the tag and the style from the source.

@W-Floyd W-Floyd changed the title Fix for https://github.com/mikefarah/yq/issues/2677 Fix for #2677 May 13, 2026
@ccoVeille
Copy link
Copy Markdown
Contributor

@mikefarah @ingydotnet what do you think about what @W-Floyd explained ?

Thanks

I think his analysis is good, but it leads me to question the change we did in go-yaml with

yaml/go-yaml@fbd745b

It might be OK, and then imply a change in yq like the one suggested here, but I prefer everyone to review the changes here and the one we did in go-yaml

@ccoVeille
Copy link
Copy Markdown
Contributor

I'm very surprised by the commit

eb7738f

That remove the merge and float tags in a lot of files.

It doesn't sound OK.

Maybe it's due to the fact the go-yaml PR needs to be merged first, but seeing such commit that changes so much things make me feel there is something wrong

@W-Floyd
Copy link
Copy Markdown
Author

W-Floyd commented May 13, 2026

Yes, it is for the sake of yaml/go-yaml#348 - I can back out those changes if they should wait. But neither will the added test work until that's merged.

expression: `.a = .a % .b`,
expected: []string{
"D0, P[], (!!map)::{a: !!float 2, b: 2.5}\n",
"D0, P[], (!!map)::{a: 2, b: 2.5}\n",
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems to have change a whole bunch of unrelated things...

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, that's to match the new output of yaml/go-yaml#348 - I can revert it for now if we want to handle that separately.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sounds strange to me then.

I have commented the go-yaml PR

yaml/go-yaml#348 (comment)

description: "explode expands << merge keys regardless of explicit tag style (!!merge or plain)",
document: mixedMergeTagStyleDocument,
expression: `explode(.)`,
expected: []string{"D0, P[], (!!map)::" + mixedMergeTagStyleExplodedDocument},
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test makes sense to me 👍🏼

Comment thread pkg/yqlib/operator_multiply.go Outdated
log.Debugf("going to applied assignment to LHS: %v with RHS: %v", NodeToString(lhs), NodeToString(candidate))

if candidate.Tag == "!!merge" {
if candidate.Tag == "!!merge" && !candidate.IsMapKey {
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

been a long time since I've touched this logic...I'd be wary of making changes. Not sure why this is needed?

Copy link
Copy Markdown
Author

@W-Floyd W-Floyd May 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I took more of a look, and believe this entire check is no longer required, due to DontFollowAlias: true. Removing it has the same result. I added a test to show what this accomplishes.

@W-Floyd
Copy link
Copy Markdown
Author

W-Floyd commented May 14, 2026

Testing by adding this to go.mod:

replace go.yaml.in/yaml/v4 v4.0.0-rc.4 => github.com/yaml/go-yaml/v4 v4.0.0-20260512181823-09a581dc5494


log.Debugf("going to applied assignment to LHS: %v with RHS: %v", NodeToString(lhs), NodeToString(candidate))

if candidate.Tag == "!!merge" {
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is this not needed?

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, got it, read your comment later in the PR

@ingydotnet
Copy link
Copy Markdown

While I believe that yaml/go-yaml#348 is doing the "right" thing, It occurred to me later that the right thing doesn't necessarily mean the "same" thing as v3. I'll take a look and report back on that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants