Skip to content

v4.0.0-rc.5

@ingydotnet ingydotnet tagged this 08 Jun 20:43
Commit cb0eff8 added `&& stag != mergeTag` to the desolver's
implicit-tag stripping logic to preserve `!!merge` on round-trip.
That over-corrected: it stops the resolver-assigned (implicit) merge
tag from being elided on encode, which breaks yq.
yq builds the merge-key node tree from parsed YAML where the resolver
fills in `Tag = "!!merge"` on the bare `<<` scalar (no TaggedStyle),
then emits the tree back out and now sees `!!merge <<:` where the
source had `<<:`.

The explicit-tag preservation case that cb0eff8 was solving is already
handled by the TaggedStyle bit (set by the composer when the source
has an explicit tag) and the early return at desolver.go:55.
So the fix is to let `!!merge` be elided like every other implicit
tag when TaggedStyle is not set.

Changes:

- internal/libyaml/desolver.go: split the `case binaryTag, mergeTag:`
  in desolveScalar.
  `binaryTag` keeps its always-preserve behavior since binary scalars
  are not implicitly resolvable.
  `mergeTag` now strips the tag when `n.Value == "<<"`, the canonical
  merge-key marker.
  Explicit `!!merge` is still preserved via the TaggedStyle early
  return above.

- internal/libyaml/testdata/desolver.yaml: convert the
  "Preserve merge tag" case (which asserted the buggy behavior) into
  "Elide implicit merge tag" (asserts the tag is removed), and add a
  "Preserve merge tag with TaggedStyle" case that confirms explicit
  tags still survive.

- testdata/node.yaml: update the two cb0eff8 cases so their expected
  output drops the `!!merge ` prefix (the nodes have no TaggedStyle,
  so the tag should be elided). Add two new cases: "merge key with
  explicit tag preserved" (uses style: Tagged to verify preservation)
  and "bare merge key with untagged scalar" (documents that a
  tag-less `<<` scalar round-trips cleanly).

Verified:

- go test ./internal/libyaml/ -run TestDesolver: all cases pass,
  including the new Elide implicit / Preserve TaggedStyle pair.
- go test . -run TestNodeFromYAML: all four merge-key cases pass.
- go test . -run TestMerge: passes.
- go test ./...: full suite green (TestYAMLSuite skipped, needs
  yaml-test-suite data download).
- End-to-end repro: parsing `m:\n  <<: *x\n` with yaml.Unmarshal
  then yaml.Marshal now produces `<<: *x` again, not `!!merge <<: *x`.
Assets 2
Loading