Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save scop/6ec72debf62a9603cff9dc97e6814ddd to your computer and use it in GitHub Desktop.

Select an option

Save scop/6ec72debf62a9603cff9dc97e6814ddd to your computer and use it in GitHub Desktop.
gopkg.in/yaml.v3@v3.0.1 to go.yaml.in/yaml/v3@v3.0.2 diff
diff -NruwB gopkg.in/yaml.v3@v3.0.1/decode.go go.yaml.in/yaml/v3@v3.0.2/decode.go
--- gopkg.in/yaml.v3@v3.0.1/decode.go 2025-12-04 09:55:31.687862796 +0200
+++ go.yaml.in/yaml/v3@v3.0.2/decode.go 2025-12-04 09:55:33.170181040 +0200
@@ -832,10 +832,10 @@
if d.unmarshal(n.Content[i], k) {
if mergedFields != nil {
ki := k.Interface()
- if mergedFields[ki] {
+ if d.getPossiblyUnhashableKey(mergedFields, ki) {
continue
}
- mergedFields[ki] = true
+ d.setPossiblyUnhashableKey(mergedFields, ki, true)
}
kkind := k.Kind()
if kkind == reflect.Interface {
@@ -956,6 +956,24 @@
failf("map merge requires map or sequence of maps as the value")
}
+func (d *decoder) setPossiblyUnhashableKey(m map[interface{}]bool, key interface{}, value bool) {
+ defer func() {
+ if err := recover(); err != nil {
+ failf("%v", err)
+ }
+ }()
+ m[key] = value
+}
+
+func (d *decoder) getPossiblyUnhashableKey(m map[interface{}]bool, key interface{}) bool {
+ defer func() {
+ if err := recover(); err != nil {
+ failf("%v", err)
+ }
+ }()
+ return m[key]
+}
+
func (d *decoder) merge(parent *Node, merge *Node, out reflect.Value) {
mergedFields := d.mergedFields
if mergedFields == nil {
@@ -963,7 +981,7 @@
for i := 0; i < len(parent.Content); i += 2 {
k := reflect.New(ifaceType).Elem()
if d.unmarshal(parent.Content[i], k) {
- d.mergedFields[k.Interface()] = true
+ d.setPossiblyUnhashableKey(d.mergedFields, k.Interface(), true)
}
}
}
diff -NruwB gopkg.in/yaml.v3@v3.0.1/decode_test.go go.yaml.in/yaml/v3@v3.0.2/decode_test.go
--- gopkg.in/yaml.v3@v3.0.1/decode_test.go 2025-12-04 09:55:31.687862796 +0200
+++ go.yaml.in/yaml/v3@v3.0.2/decode_test.go 2025-12-04 09:55:33.170203786 +0200
@@ -23,10 +23,12 @@
"math"
"reflect"
"strings"
+ "testing"
"time"
. "gopkg.in/check.v1"
- "gopkg.in/yaml.v3"
+
+ "go.yaml.in/yaml/v3"
)
var unmarshalIntTest = 123
@@ -307,7 +309,7 @@
}, {
"a: 1",
&struct {
- B int "a"
+ B int `yaml:"a"`
}{1},
}, {
// Some limited backwards compatibility with the 1.1 spec.
@@ -528,7 +530,7 @@
"a: 1\nb: 2\n",
&struct {
A int
- B int "-"
+ B int `yaml:"-"`
}{1, 0},
},
@@ -1013,15 +1015,15 @@
}
type unmarshalerPointer struct {
- Field *unmarshalerType "_"
+ Field *unmarshalerType `yaml:"_"`
}
type unmarshalerValue struct {
- Field unmarshalerType "_"
+ Field unmarshalerType `yaml:"_"`
}
type unmarshalerInlined struct {
- Field *unmarshalerType "_"
+ Field *unmarshalerType `yaml:"_"`
Inlined unmarshalerType `yaml:",inline"`
}
@@ -1046,11 +1048,11 @@
}
type obsoleteUnmarshalerPointer struct {
- Field *obsoleteUnmarshalerType "_"
+ Field *obsoleteUnmarshalerType `yaml:"_"`
}
type obsoleteUnmarshalerValue struct {
- Field obsoleteUnmarshalerType "_"
+ Field obsoleteUnmarshalerType `yaml:"_"`
}
func (s *S) TestUnmarshalerPointerField(c *C) {
@@ -1741,6 +1743,22 @@
}
}
+func TestIssue117(t *testing.T) {
+ data := []byte(`
+a:
+<<:
+-
+?
+-
+`)
+
+ x := map[string]interface{}{}
+ err := yaml.Unmarshal([]byte(data), &x)
+ if err == nil {
+ t.Errorf("expected error, got none")
+ }
+}
+
//var data []byte
//func init() {
// var err error
diff -NruwB gopkg.in/yaml.v3@v3.0.1/emitterc.go go.yaml.in/yaml/v3@v3.0.2/emitterc.go
--- gopkg.in/yaml.v3@v3.0.1/emitterc.go 2025-12-04 09:55:31.688165015 +0200
+++ go.yaml.in/yaml/v3@v3.0.2/emitterc.go 2025-12-04 09:55:33.170203786 +0200
@@ -165,7 +165,6 @@
// - 1 event for DOCUMENT-START
// - 2 events for SEQUENCE-START
// - 3 events for MAPPING-START
-//
func yaml_emitter_need_more_events(emitter *yaml_emitter_t) bool {
if emitter.events_head == len(emitter.events) {
return true
@@ -226,7 +225,7 @@
}
// Increase the indentation level.
-func yaml_emitter_increase_indent(emitter *yaml_emitter_t, flow, indentless bool) bool {
+func yaml_emitter_increase_indent_compact(emitter *yaml_emitter_t, flow, indentless bool, compact_seq bool) bool {
emitter.indents = append(emitter.indents, emitter.indent)
if emitter.indent < 0 {
if flow {
@@ -242,6 +241,13 @@
} else {
// Everything else aligns to the chosen indentation.
emitter.indent = emitter.best_indent*((emitter.indent+emitter.best_indent)/emitter.best_indent)
+ if compact_seq {
+ // The value compact_seq passed in is almost always set to `false` when this function is called,
+ // except when we are dealing with sequence nodes. So this gets triggered to subtract 2 only when we
+ // are increasing the indent to account for sequence nodes, which will be correct because we need to
+ // subtract 2 to account for the - at the beginning of the sequence node.
+ emitter.indent = emitter.indent - 2
+ }
}
}
return true
@@ -478,6 +484,18 @@
return yaml_emitter_set_emitter_error(emitter, "expected DOCUMENT-START or STREAM-END")
}
+// yaml_emitter_increase_indent preserves the original signature and delegates to
+// yaml_emitter_increase_indent_compact without compact-sequence indentation
+func yaml_emitter_increase_indent(emitter *yaml_emitter_t, flow, indentless bool) bool {
+ return yaml_emitter_increase_indent_compact(emitter, flow, indentless, false)
+}
+
+// yaml_emitter_process_line_comment preserves the original signature and delegates to
+// yaml_emitter_process_line_comment_linebreak passing false for linebreak
+func yaml_emitter_process_line_comment(emitter *yaml_emitter_t) bool {
+ return yaml_emitter_process_line_comment_linebreak(emitter, false)
+}
+
// Expect the root node.
func yaml_emitter_emit_document_content(emitter *yaml_emitter_t, event *yaml_event_t) bool {
emitter.states = append(emitter.states, yaml_EMIT_DOCUMENT_END_STATE)
@@ -728,7 +746,16 @@
// Expect a block item node.
func yaml_emitter_emit_block_sequence_item(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool {
if first {
- if !yaml_emitter_increase_indent(emitter, false, false) {
+ // emitter.mapping context tells us if we are currently in a mapping context.
+ // emiiter.column tells us which column we are in in the yaml output. 0 is the first char of the column.
+ // emitter.indentation tells us if the last character was an indentation character.
+ // emitter.compact_sequence_indent tells us if '- ' is considered part of the indentation for sequence elements.
+ // So, `seq` means that we are in a mapping context, and we are either at the first char of the column or
+ // the last character was not an indentation character, and we consider '- ' part of the indentation
+ // for sequence elements.
+ seq := emitter.mapping_context && (emitter.column == 0 || !emitter.indention) &&
+ emitter.compact_sequence_indent
+ if !yaml_emitter_increase_indent_compact(emitter, false, false, seq) {
return false
}
}
@@ -1144,8 +1171,15 @@
}
// Write an line comment.
-func yaml_emitter_process_line_comment(emitter *yaml_emitter_t) bool {
+func yaml_emitter_process_line_comment_linebreak(emitter *yaml_emitter_t, linebreak bool) bool {
if len(emitter.line_comment) == 0 {
+ // The next 3 lines are needed to resolve an issue with leading newlines
+ // See https://github.com/go-yaml/yaml/issues/755
+ // When linebreak is set to true, put_break will be called and will add
+ // the needed newline.
+ if linebreak && !put_break(emitter) {
+ return false
+ }
return true
}
if !emitter.whitespace {
@@ -1894,7 +1928,7 @@
if !yaml_emitter_write_block_scalar_hints(emitter, value) {
return false
}
- if !yaml_emitter_process_line_comment(emitter) {
+ if !yaml_emitter_process_line_comment_linebreak(emitter, true) {
return false
}
//emitter.indention = true
@@ -1931,7 +1965,7 @@
if !yaml_emitter_write_block_scalar_hints(emitter, value) {
return false
}
- if !yaml_emitter_process_line_comment(emitter) {
+ if !yaml_emitter_process_line_comment_linebreak(emitter, true) {
return false
}
diff -NruwB gopkg.in/yaml.v3@v3.0.1/encode_test.go go.yaml.in/yaml/v3@v3.0.2/encode_test.go
--- gopkg.in/yaml.v3@v3.0.1/encode_test.go 2025-12-04 09:55:31.688165015 +0200
+++ go.yaml.in/yaml/v3@v3.0.2/encode_test.go 2025-12-04 09:55:33.170203786 +0200
@@ -19,15 +19,15 @@
"bytes"
"fmt"
"math"
+ "net"
+ "os"
"strconv"
"strings"
"time"
- "net"
- "os"
-
. "gopkg.in/check.v1"
- "gopkg.in/yaml.v3"
+
+ "go.yaml.in/yaml/v3"
)
var marshalIntTest = 123
@@ -170,7 +170,7 @@
"a:\n - 1\n - 2\n",
}, {
&struct {
- B int "a"
+ B int `yaml:"a"`
}{1},
"a: 1\n",
}, {
@@ -187,54 +187,54 @@
// Conditional flag
{
&struct {
- A int "a,omitempty"
- B int "b,omitempty"
+ A int `yaml:"a,omitempty"`
+ B int `yaml:"b,omitempty"`
}{1, 0},
"a: 1\n",
}, {
&struct {
- A int "a,omitempty"
- B int "b,omitempty"
+ A int `yaml:"a,omitempty"`
+ B int `yaml:"b,omitempty"`
}{0, 0},
"{}\n",
}, {
&struct {
- A *struct{ X, y int } "a,omitempty,flow"
+ A *struct{ X, y int } `yaml:"a,omitempty,flow"`
}{&struct{ X, y int }{1, 2}},
"a: {x: 1}\n",
}, {
&struct {
- A *struct{ X, y int } "a,omitempty,flow"
+ A *struct{ X, y int } `yaml:"a,omitempty,flow"`
}{nil},
"{}\n",
}, {
&struct {
- A *struct{ X, y int } "a,omitempty,flow"
+ A *struct{ X, y int } `yaml:"a,omitempty,flow"`
}{&struct{ X, y int }{}},
"a: {x: 0}\n",
}, {
&struct {
- A struct{ X, y int } "a,omitempty,flow"
+ A struct{ X, y int } `yaml:"a,omitempty,flow"`
}{struct{ X, y int }{1, 2}},
"a: {x: 1}\n",
}, {
&struct {
- A struct{ X, y int } "a,omitempty,flow"
+ A struct{ X, y int } `yaml:"a,omitempty,flow"`
}{struct{ X, y int }{0, 1}},
"{}\n",
}, {
&struct {
- A float64 "a,omitempty"
- B float64 "b,omitempty"
+ A float64 `yaml:"a,omitempty"`
+ B float64 `yaml:"b,omitempty"`
}{1, 0},
"a: 1\n",
},
{
&struct {
- T1 time.Time "t1,omitempty"
- T2 time.Time "t2,omitempty"
- T3 *time.Time "t3,omitempty"
- T4 *time.Time "t4,omitempty"
+ T1 time.Time `yaml:"t1,omitempty"`
+ T2 time.Time `yaml:"t2,omitempty"`
+ T3 *time.Time `yaml:"t3,omitempty"`
+ T4 *time.Time `yaml:"t4,omitempty"`
}{
T2: time.Date(2018, 1, 9, 10, 40, 47, 0, time.UTC),
T4: newTime(time.Date(2098, 1, 9, 10, 40, 47, 0, time.UTC)),
@@ -252,24 +252,24 @@
// Flow flag
{
&struct {
- A []int "a,flow"
+ A []int `yaml:"a,flow"`
}{[]int{1, 2}},
"a: [1, 2]\n",
}, {
&struct {
- A map[string]string "a,flow"
+ A map[string]string `yaml:"a,flow"`
}{map[string]string{"b": "c", "d": "e"}},
"a: {b: c, d: e}\n",
}, {
&struct {
A struct {
B, D string
- } "a,flow"
+ } `yaml:"a,flow"`
}{struct{ B, D string }{"c", "e"}},
"a: {b: c, d: e}\n",
}, {
&struct {
- A string "a,flow"
+ A string `yaml:"a,flow"`
}{"b\nc"},
"a: \"b\\nc\"\n",
},
@@ -287,7 +287,7 @@
{
&struct {
A int
- B int "-"
+ B int `yaml:"-"`
}{1, 2},
"a: 1\n",
},
@@ -551,13 +551,13 @@
}{{
value: &struct {
B int
- inlineB ",inline"
+ inlineB `yaml:",inline"`
}{1, inlineB{2, inlineC{3}}},
panic: `duplicated key 'b' in struct struct \{ B int; .*`,
}, {
value: &struct {
A int
- B map[string]int ",inline"
+ B map[string]int `yaml:",inline"`
}{1, map[string]int{"a": 2}},
panic: `cannot have key "a" in inlined map: conflicts with struct field`,
}}
@@ -613,7 +613,7 @@
}
type marshalerValue struct {
- Field marshalerType "_"
+ Field marshalerType `yaml:"_"`
}
func (s *S) TestMarshaler(c *C) {
@@ -734,3 +734,139 @@
func newTime(t time.Time) *time.Time {
return &t
}
+
+func (s *S) TestCompactSeqIndentDefault(c *C) {
+ var buf bytes.Buffer
+ enc := yaml.NewEncoder(&buf)
+ enc.CompactSeqIndent()
+ err := enc.Encode(map[string]interface{}{"a": []string{"b", "c"}})
+ c.Assert(err, Equals, nil)
+ err = enc.Close()
+ c.Assert(err, Equals, nil)
+ // The default indent is 4, so these sequence elements get 2 indents as before
+ c.Assert(buf.String(), Equals, `a:
+ - b
+ - c
+`)
+}
+
+func (s *S) TestCompactSequenceWithSetIndent(c *C) {
+ var buf bytes.Buffer
+ enc := yaml.NewEncoder(&buf)
+ enc.CompactSeqIndent()
+ enc.SetIndent(2)
+ err := enc.Encode(map[string]interface{}{"a": []string{"b", "c"}})
+ c.Assert(err, Equals, nil)
+ err = enc.Close()
+ c.Assert(err, Equals, nil)
+ // The sequence indent is 2, so these sequence elements don't get indented at all
+ c.Assert(buf.String(), Equals, `a:
+- b
+- c
+`)
+}
+
+type normal string
+type compact string
+
+// newlinePlusNormalToNewlinePlusCompact maps the normal encoding (prefixed with a newline)
+// to the compact encoding (prefixed with a newline), for test cases in marshalTests
+var newlinePlusNormalToNewlinePlusCompact = map[normal]compact{
+ normal(`
+v:
+ - A
+ - B
+`): compact(`
+v:
+ - A
+ - B
+`),
+
+ normal(`
+v:
+ - A
+ - |-
+ B
+ C
+`): compact(`
+v:
+ - A
+ - |-
+ B
+ C
+`),
+
+ normal(`
+v:
+ - A
+ - 1
+ - B:
+ - 2
+ - 3
+`): compact(`
+v:
+ - A
+ - 1
+ - B:
+ - 2
+ - 3
+`),
+
+ normal(`
+a:
+ - 1
+ - 2
+`): compact(`
+a:
+ - 1
+ - 2
+`),
+
+ normal(`
+a:
+ b:
+ - c: 1
+ d: 2
+`): compact(`
+a:
+ b:
+ - c: 1
+ d: 2
+`),
+}
+
+func (s *S) TestEncoderCompactIndents(c *C) {
+ for i, item := range marshalTests {
+ c.Logf("test %d. %q", i, item.data)
+ var buf bytes.Buffer
+ enc := yaml.NewEncoder(&buf)
+ enc.CompactSeqIndent()
+ err := enc.Encode(item.value)
+ c.Assert(err, Equals, nil)
+ err = enc.Close()
+ c.Assert(err, Equals, nil)
+
+ // Default to expecting the item data
+ expected := item.data
+ // If there's a different compact representation, use that
+ if c, ok := newlinePlusNormalToNewlinePlusCompact[normal("\n"+item.data)]; ok {
+ expected = string(c[1:])
+ }
+
+ c.Assert(buf.String(), Equals, expected)
+ }
+}
+
+func (s *S) TestNewLinePreserved(c *C) {
+ obj := &marshalerValue{}
+ obj.Field.value = "a:\n b:\n c: d\n"
+ data, err := yaml.Marshal(obj)
+ c.Assert(err, IsNil)
+ c.Assert(string(data), Equals, "_: |\n a:\n b:\n c: d\n")
+
+ obj.Field.value = "\na:\n b:\n c: d\n"
+ data, err = yaml.Marshal(obj)
+ c.Assert(err, IsNil)
+ // the newline at the start of the file should be preserved
+ c.Assert(string(data), Equals, "_: |4\n\n a:\n b:\n c: d\n")
+}
diff -NruwB gopkg.in/yaml.v3@v3.0.1/example_embedded_test.go go.yaml.in/yaml/v3@v3.0.2/example_embedded_test.go
--- gopkg.in/yaml.v3@v3.0.1/example_embedded_test.go 2025-12-04 09:55:31.688165015 +0200
+++ go.yaml.in/yaml/v3@v3.0.2/example_embedded_test.go 2025-12-04 09:55:33.170203786 +0200
@@ -19,7 +19,7 @@
"fmt"
"log"
- "gopkg.in/yaml.v3"
+ "go.yaml.in/yaml/v3"
)
// An example showing how to unmarshal embedded
diff -NruwB gopkg.in/yaml.v3@v3.0.1/.github/workflows/go.yaml go.yaml.in/yaml/v3@v3.0.2/.github/workflows/go.yaml
--- gopkg.in/yaml.v3@v3.0.1/.github/workflows/go.yaml 2025-12-04 09:55:31.687862796 +0200
+++ go.yaml.in/yaml/v3@v3.0.2/.github/workflows/go.yaml 2025-12-04 09:55:33.170181040 +0200
@@ -1,61 +1,40 @@
----
name: Go
-on: [push, pull_request]
+
+on:
+ push:
+ branches: [ v3 ]
+ pull_request:
+ branches: [ v3 ]
jobs:
- test:
- name: Test
- runs-on: ubuntu-20.04
+ fmt:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - name: Set up Go
+ uses: actions/setup-go@v5
+ with:
+ go-version: stable
+ - name: Run go fmt
+ run: go fmt ./...
+ - name: Check if working tree is dirty
+ run: |
+ if [[ $(git diff --stat) ]]; then
+ git --no-pager diff
+ echo 'Run go fmt ./... and commit changes.'
+ exit 1
+ fi
+ build:
strategy:
- fail-fast: false
matrix:
- go:
- - "1.5"
- - "1.6"
- - "1.7"
- - "1.8"
- - "1.9"
- - "1.10"
- - "1.11"
- - "1.12"
- - "1.13"
- - "1.14"
- - "1.15"
- - "1.16.0-beta1"
- - "tip"
- env:
- GOPATH: ${{ github.workspace }}/go
+ go-versions: [1.21.x, 1.22.x, 1.23.x, 1.24.x]
+ runs-on: ubuntu-latest
steps:
- - name: Check out code into the Go module directory
- uses: actions/checkout@v2
- with:
- path: ${{ github.workspace }}/go/src/gopkg.in/yaml.v3
- - name: Set up Go ${{ matrix.go }}
- if: matrix.go != 'tip'
- uses: actions/setup-go@v2
+ - uses: actions/checkout@v4
+ - name: Set up Go
+ uses: actions/setup-go@v5
with:
- go-version: ${{ matrix.go }}
- stable: false
- - name: Set up Go ${{ matrix.go }}
- if: matrix.go == 'tip'
- run: |
- export GOROOT_BOOTSTRAP=`go env GOROOT`
- export GOROOT=$HOME/gotip
- mkdir $HOME/gotip
- cd $HOME/gotip
-
- curl -s 'https://go.googlesource.com/go/+/refs/heads/master?format=JSON' | awk '/"commit"/{print substr($2,2,40);exit}' >HEAD
- awk '{printf("gotip-%s",substr($0,0,7))}' <HEAD >VERSION
-
- curl -s -o go.tar.gz https://go.googlesource.com/go/+archive/`cat HEAD`.tar.gz
- tar xfz go.tar.gz
-
- cd src
- bash make.bash
-
- echo "GOROOT=$GOROOT" >> $GITHUB_ENV
- echo "$GOROOT/bin" >> $GITHUB_PATH
- - run: go version
- - run: go get -t ./...
- working-directory: ${{ github.workspace }}/go/src/gopkg.in/yaml.v3
- - run: go test .
- working-directory: ${{ github.workspace }}/go/src/gopkg.in/yaml.v3
+ go-version: ${{ matrix.go-versions }}
+ - name: Run go vet
+ run: go vet ./...
+ - name: Run go test
+ run: GO111MODULE=on go test -v -race ./...
diff -NruwB gopkg.in/yaml.v3@v3.0.1/go.mod go.yaml.in/yaml/v3@v3.0.2/go.mod
--- gopkg.in/yaml.v3@v3.0.1/go.mod 2025-12-04 09:55:31.688165015 +0200
+++ go.yaml.in/yaml/v3@v3.0.2/go.mod 2025-12-04 09:55:33.170203786 +0200
@@ -1,5 +1,5 @@
-module "gopkg.in/yaml.v3"
+module go.yaml.in/yaml/v3
-require (
- "gopkg.in/check.v1" v0.0.0-20161208181325-20d25e280405
-)
+go 1.22
+
+require gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405
diff -NruwB gopkg.in/yaml.v3@v3.0.1/go.sum go.yaml.in/yaml/v3@v3.0.2/go.sum
--- gopkg.in/yaml.v3@v3.0.1/go.sum 1970-01-01 02:00:00.000000000 +0200
+++ go.yaml.in/yaml/v3@v3.0.2/go.sum 2025-12-04 09:55:33.170203786 +0200
@@ -0,0 +1,2 @@
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
diff -NruwB gopkg.in/yaml.v3@v3.0.1/limit_test.go go.yaml.in/yaml/v3@v3.0.2/limit_test.go
--- gopkg.in/yaml.v3@v3.0.1/limit_test.go 2025-12-04 09:55:31.688165015 +0200
+++ go.yaml.in/yaml/v3@v3.0.2/limit_test.go 2025-12-04 09:55:33.170203786 +0200
@@ -5,7 +5,8 @@
"testing"
. "gopkg.in/check.v1"
- "gopkg.in/yaml.v3"
+
+ "go.yaml.in/yaml/v3"
)
var limitTests = []struct {
diff -NruwB gopkg.in/yaml.v3@v3.0.1/node_test.go go.yaml.in/yaml/v3@v3.0.2/node_test.go
--- gopkg.in/yaml.v3@v3.0.1/node_test.go 2025-12-04 09:55:31.688165015 +0200
+++ go.yaml.in/yaml/v3@v3.0.2/node_test.go 2025-12-04 09:55:33.170203786 +0200
@@ -18,12 +18,13 @@
import (
"bytes"
"fmt"
+ "io"
"os"
+ "strings"
. "gopkg.in/check.v1"
- "gopkg.in/yaml.v3"
- "io"
- "strings"
+
+ "go.yaml.in/yaml/v3"
)
var nodeTests = []struct {
@@ -2836,7 +2837,7 @@
func (s *S) TestNodeOmitEmpty(c *C) {
var v struct {
A int
- B yaml.Node ",omitempty"
+ B yaml.Node `yaml:",omitempty"`
}
v.A = 1
data, err := yaml.Marshal(&v)
diff -NruwB gopkg.in/yaml.v3@v3.0.1/parserc.go go.yaml.in/yaml/v3@v3.0.2/parserc.go
--- gopkg.in/yaml.v3@v3.0.1/parserc.go 2025-12-04 09:55:31.688165015 +0200
+++ go.yaml.in/yaml/v3@v3.0.2/parserc.go 2025-12-04 09:55:33.171203812 +0200
@@ -227,6 +227,7 @@
// Parse the production:
// stream ::= STREAM-START implicit_document? explicit_document* STREAM-END
+//
// ************
func yaml_parser_parse_stream_start(parser *yaml_parser_t, event *yaml_event_t) bool {
token := peek_token(parser)
@@ -249,8 +250,11 @@
// Parse the productions:
// implicit_document ::= block_node DOCUMENT-END*
+//
// *
+//
// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
+//
// *************************
func yaml_parser_parse_document_start(parser *yaml_parser_t, event *yaml_event_t, implicit bool) bool {
@@ -356,8 +360,8 @@
// Parse the productions:
// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
-// ***********
//
+// ***********
func yaml_parser_parse_document_content(parser *yaml_parser_t, event *yaml_event_t) bool {
token := peek_token(parser)
if token == nil {
@@ -379,9 +383,10 @@
// Parse the productions:
// implicit_document ::= block_node DOCUMENT-END*
+//
// *************
-// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
//
+// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
func yaml_parser_parse_document_end(parser *yaml_parser_t, event *yaml_event_t) bool {
token := peek_token(parser)
if token == nil {
@@ -428,29 +433,40 @@
// Parse the productions:
// block_node_or_indentless_sequence ::=
+//
// ALIAS
// *****
// | properties (block_content | indentless_block_sequence)?
// ********** *
// | block_content | indentless_block_sequence
// *
+//
// block_node ::= ALIAS
+//
// *****
// | properties block_content?
// ********** *
// | block_content
// *
+//
// flow_node ::= ALIAS
+//
// *****
// | properties flow_content?
// ********** *
// | flow_content
// *
+//
// properties ::= TAG ANCHOR? | ANCHOR TAG?
+//
// *************************
+//
// block_content ::= block_collection | flow_collection | SCALAR
+//
// ******
+//
// flow_content ::= flow_collection | SCALAR
+//
// ******
func yaml_parser_parse_node(parser *yaml_parser_t, event *yaml_event_t, block, indentless_sequence bool) bool {
//defer trace("yaml_parser_parse_node", "block:", block, "indentless_sequence:", indentless_sequence)()
@@ -682,8 +698,8 @@
// Parse the productions:
// block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END
-// ******************** *********** * *********
//
+// ******************** *********** * *********
func yaml_parser_parse_block_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
if first {
token := peek_token(parser)
@@ -740,6 +756,7 @@
// Parse the productions:
// indentless_sequence ::= (BLOCK-ENTRY block_node?)+
+//
// *********** *
func yaml_parser_parse_indentless_sequence_entry(parser *yaml_parser_t, event *yaml_event_t) bool {
token := peek_token(parser)
@@ -805,6 +822,7 @@
// Parse the productions:
// block_mapping ::= BLOCK-MAPPING_START
+//
// *******************
// ((KEY block_node_or_indentless_sequence?)?
// *** *
@@ -812,7 +830,6 @@
//
// BLOCK-END
// *********
-//
func yaml_parser_parse_block_mapping_key(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
if first {
token := peek_token(parser)
@@ -886,8 +903,6 @@
// (VALUE block_node_or_indentless_sequence?)?)*
// ***** *
// BLOCK-END
-//
-//
func yaml_parser_parse_block_mapping_value(parser *yaml_parser_t, event *yaml_event_t) bool {
token := peek_token(parser)
if token == nil {
@@ -915,6 +930,7 @@
// Parse the productions:
// flow_sequence ::= FLOW-SEQUENCE-START
+//
// *******************
// (flow_sequence_entry FLOW-ENTRY)*
// * **********
@@ -922,9 +938,10 @@
// *
// FLOW-SEQUENCE-END
// *****************
+//
// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
-// *
//
+// *
func yaml_parser_parse_flow_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
if first {
token := peek_token(parser)
@@ -987,11 +1004,10 @@
return true
}
-//
// Parse the productions:
// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
-// *** *
//
+// *** *
func yaml_parser_parse_flow_sequence_entry_mapping_key(parser *yaml_parser_t, event *yaml_event_t) bool {
token := peek_token(parser)
if token == nil {
@@ -1011,8 +1027,8 @@
// Parse the productions:
// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
-// ***** *
//
+// ***** *
func yaml_parser_parse_flow_sequence_entry_mapping_value(parser *yaml_parser_t, event *yaml_event_t) bool {
token := peek_token(parser)
if token == nil {
@@ -1035,8 +1051,8 @@
// Parse the productions:
// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
-// *
//
+// *
func yaml_parser_parse_flow_sequence_entry_mapping_end(parser *yaml_parser_t, event *yaml_event_t) bool {
token := peek_token(parser)
if token == nil {
@@ -1053,6 +1069,7 @@
// Parse the productions:
// flow_mapping ::= FLOW-MAPPING-START
+//
// ******************
// (flow_mapping_entry FLOW-ENTRY)*
// * **********
@@ -1060,9 +1077,9 @@
// ******************
// FLOW-MAPPING-END
// ****************
-// flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
-// * *** *
//
+// flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+// - *** *
func yaml_parser_parse_flow_mapping_key(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
if first {
token := peek_token(parser)
@@ -1128,8 +1145,7 @@
// Parse the productions:
// flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
-// * ***** *
-//
+// - ***** *
func yaml_parser_parse_flow_mapping_value(parser *yaml_parser_t, event *yaml_event_t, empty bool) bool {
token := peek_token(parser)
if token == nil {
diff -NruwB gopkg.in/yaml.v3@v3.0.1/README.md go.yaml.in/yaml/v3@v3.0.2/README.md
--- gopkg.in/yaml.v3@v3.0.1/README.md 2025-12-04 09:55:31.687862796 +0200
+++ go.yaml.in/yaml/v3@v3.0.2/README.md 2025-12-04 09:55:33.170181040 +0200
@@ -1,78 +1,94 @@
-# YAML support for the Go language
+go.yaml.in/yaml
+===============
-Introduction
-------------
+YAML Support for the Go Language
-The yaml package enables Go programs to comfortably encode and decode YAML
-values. It was developed within [Canonical](https://www.canonical.com) as
-part of the [juju](https://juju.ubuntu.com) project, and is based on a
-pure Go port of the well-known [libyaml](http://pyyaml.org/wiki/LibYAML)
-C library to parse and generate YAML data quickly and reliably.
-
-Compatibility
--------------
-
-The yaml package supports most of YAML 1.2, but preserves some behavior
-from 1.1 for backwards compatibility.
-
-Specifically, as of v3 of the yaml package:
-
- - YAML 1.1 bools (_yes/no, on/off_) are supported as long as they are being
- decoded into a typed bool value. Otherwise they behave as a string. Booleans
- in YAML 1.2 are _true/false_ only.
- - Octals encode and decode as _0777_ per YAML 1.1, rather than _0o777_
- as specified in YAML 1.2, because most parsers still use the old format.
- Octals in the _0o777_ format are supported though, so new files work.
- - Does not support base-60 floats. These are gone from YAML 1.2, and were
- actually never supported by this package as it's clearly a poor choice.
-
-and offers backwards
-compatibility with YAML 1.1 in some cases.
-1.2, including support for
-anchors, tags, map merging, etc. Multi-document unmarshalling is not yet
-implemented, and base-60 floats from YAML 1.1 are purposefully not
-supported since they're a poor design and are gone in YAML 1.2.
-Installation and usage
-----------------------
+## Introduction
-The import path for the package is *gopkg.in/yaml.v3*.
+The `yaml` package enables [Go](https://go.dev/) programs to comfortably encode
+and decode [YAML](https://yaml.org/) values.
-To install it, run:
+It was originally developed within [Canonical](https://www.canonical.com) as
+part of the [juju](https://juju.ubuntu.com) project, and is based on a pure Go
+port of the well-known [libyaml](http://pyyaml.org/wiki/LibYAML) C library to
+parse and generate YAML data quickly and reliably.
- go get gopkg.in/yaml.v3
-API documentation
------------------
+## Project Status
-If opened in a browser, the import path itself leads to the API documentation:
+This project started as a fork of the extremely popular [go-yaml](
+https://github.com/go-yaml/yaml/)
+project, and is being maintained by the official [YAML organization](
+https://github.com/yaml/).
- - [https://gopkg.in/yaml.v3](https://gopkg.in/yaml.v3)
+The YAML team took over ongoing maintenance and development of the project after
+discussion with go-yaml's author, @niemeyer, following his decision to
+[label the project repository as "unmaintained"](
+https://github.com/go-yaml/yaml/blob/944c86a7d2/README.md) in April 2025.
-API stability
--------------
+We have put together a team of dedicated maintainers including representatives
+of go-yaml's most important downstream projects.
-The package API for yaml v3 will remain stable as described in [gopkg.in](https://gopkg.in).
+We will strive to earn the trust of the various go-yaml forks to switch back to
+this repository as their upstream.
+Please [contact us](https://cloud-native.slack.com/archives/C08PPAT8PS7) if you
+would like to contribute or be involved.
-License
--------
-The yaml package is licensed under the MIT and Apache License 2.0 licenses.
-Please see the LICENSE file for details.
+## Compatibility
+
+The `yaml` package supports most of YAML 1.2, but preserves some behavior from
+1.1 for backwards compatibility.
+
+Specifically, v3 of the `yaml` package:
+
+* Supports YAML 1.1 bools (`yes`/`no`, `on`/`off`) as long as they are being
+ decoded into a typed bool value.
+ Otherwise they behave as a string.
+ Booleans in YAML 1.2 are `true`/`false` only.
+* Supports octals encoded and decoded as `0777` per YAML 1.1, rather than
+ `0o777` as specified in YAML 1.2, because most parsers still use the old
+ format.
+ Octals in the `0o777` format are supported though, so new files work.
+* Does not support base-60 floats.
+ These are gone from YAML 1.2, and were actually never supported by this
+ package as it's clearly a poor choice.
-Example
--------
+## Installation and Usage
+
+The import path for the package is *go.yaml.in/yaml/v3*.
+
+To install it, run:
+
+```bash
+go get go.yaml.in/yaml/v3
+```
+
-```Go
+## API Documentation
+
+See: <https://pkg.go.dev/go.yaml.in/yaml/v3>
+
+
+## API Stability
+
+The package API for yaml v3 will remain stable as described in [gopkg.in](
+https://gopkg.in).
+
+
+## Example
+
+```go
package main
import (
"fmt"
"log"
- "gopkg.in/yaml.v3"
+ "go.yaml.in/yaml/v3"
)
var data = `
@@ -148,3 +164,8 @@
- 4
```
+
+## License
+
+The yaml package is licensed under the MIT and Apache License 2.0 licenses.
+Please see the LICENSE file for details.
diff -NruwB gopkg.in/yaml.v3@v3.0.1/scannerc.go go.yaml.in/yaml/v3@v3.0.2/scannerc.go
--- gopkg.in/yaml.v3@v3.0.1/scannerc.go 2025-12-04 09:55:31.689165041 +0200
+++ go.yaml.in/yaml/v3@v3.0.2/scannerc.go 2025-12-04 09:55:33.171203812 +0200
@@ -1614,11 +1614,11 @@
// Scan a YAML-DIRECTIVE or TAG-DIRECTIVE token.
//
// Scope:
+//
// %YAML 1.1 # a comment \n
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// %TAG !yaml! tag:yaml.org,2002: \n
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-//
func yaml_parser_scan_directive(parser *yaml_parser_t, token *yaml_token_t) bool {
// Eat '%'.
start_mark := parser.mark
@@ -1719,11 +1719,11 @@
// Scan the directive name.
//
// Scope:
+//
// %YAML 1.1 # a comment \n
// ^^^^
// %TAG !yaml! tag:yaml.org,2002: \n
// ^^^
-//
func yaml_parser_scan_directive_name(parser *yaml_parser_t, start_mark yaml_mark_t, name *[]byte) bool {
// Consume the directive name.
if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
@@ -1758,6 +1758,7 @@
// Scan the value of VERSION-DIRECTIVE.
//
// Scope:
+//
// %YAML 1.1 # a comment \n
// ^^^^^^
func yaml_parser_scan_version_directive_value(parser *yaml_parser_t, start_mark yaml_mark_t, major, minor *int8) bool {
@@ -1797,6 +1798,7 @@
// Scan the version number of VERSION-DIRECTIVE.
//
// Scope:
+//
// %YAML 1.1 # a comment \n
// ^
// %YAML 1.1 # a comment \n
@@ -1834,9 +1836,9 @@
// Scan the value of a TAG-DIRECTIVE token.
//
// Scope:
+//
// %TAG !yaml! tag:yaml.org,2002: \n
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-//
func yaml_parser_scan_tag_directive_value(parser *yaml_parser_t, start_mark yaml_mark_t, handle, prefix *[]byte) bool {
var handle_value, prefix_value []byte
diff -NruwB gopkg.in/yaml.v3@v3.0.1/suite_test.go go.yaml.in/yaml/v3@v3.0.2/suite_test.go
--- gopkg.in/yaml.v3@v3.0.1/suite_test.go 2025-12-04 09:55:31.689165041 +0200
+++ go.yaml.in/yaml/v3@v3.0.2/suite_test.go 2025-12-04 09:55:33.171203812 +0200
@@ -16,8 +16,9 @@
package yaml_test
import (
- . "gopkg.in/check.v1"
"testing"
+
+ . "gopkg.in/check.v1"
)
func Test(t *testing.T) { TestingT(t) }
diff -NruwB gopkg.in/yaml.v3@v3.0.1/yaml.go go.yaml.in/yaml/v3@v3.0.2/yaml.go
--- gopkg.in/yaml.v3@v3.0.1/yaml.go 2025-12-04 09:55:31.689165041 +0200
+++ go.yaml.in/yaml/v3@v3.0.2/yaml.go 2025-12-04 09:55:33.172203839 +0200
@@ -18,7 +18,6 @@
// Source code and other details for the project are available at GitHub:
//
// https://github.com/go-yaml/yaml
-//
package yaml
import (
@@ -84,7 +83,6 @@
//
// See the documentation of Marshal for the format of tags and a list of
// supported tag options.
-//
func Unmarshal(in []byte, out interface{}) (err error) {
return unmarshal(in, out, false)
}
@@ -214,7 +212,6 @@
// }
// yaml.Marshal(&T{B: 2}) // Returns "b: 2\n"
// yaml.Marshal(&T{F: 1}} // Returns "a: 1\nb: 0\n"
-//
func Marshal(in interface{}) (out []byte, err error) {
defer handleErr(&err)
e := newEncoder()
@@ -278,6 +275,16 @@
e.encoder.indent = spaces
}
+// CompactSeqIndent makes it so that '- ' is considered part of the indentation.
+func (e *Encoder) CompactSeqIndent() {
+ e.encoder.emitter.compact_sequence_indent = true
+}
+
+// DefaultSeqIndent makes it so that '- ' is not considered part of the indentation.
+func (e *Encoder) DefaultSeqIndent() {
+ e.encoder.emitter.compact_sequence_indent = false
+}
+
// Close closes the encoder by writing any remaining data.
// It does not write a stream terminating string "...".
func (e *Encoder) Close() (err error) {
@@ -368,7 +375,6 @@
//
// var person Node
// err := yaml.Unmarshal(data, &person)
-//
type Node struct {
// Kind defines whether the node is a document, a mapping, a sequence,
// a scalar value, or an alias to another node. The specific data type of
diff -NruwB gopkg.in/yaml.v3@v3.0.1/yamlh.go go.yaml.in/yaml/v3@v3.0.2/yamlh.go
--- gopkg.in/yaml.v3@v3.0.1/yamlh.go 2025-12-04 09:55:31.689165041 +0200
+++ go.yaml.in/yaml/v3@v3.0.2/yamlh.go 2025-12-04 09:55:33.172203839 +0200
@@ -438,7 +438,9 @@
// The number of written bytes should be set to the size_read variable.
//
// [in,out] data A pointer to an application data specified by
+//
// yaml_parser_set_input().
+//
// [out] buffer The buffer to write the data from the source.
// [in] size The size of the buffer.
// [out] size_read The actual number of bytes read from the source.
@@ -659,13 +660,14 @@
// @a buffer to the output.
//
// @param[in,out] data A pointer to an application data specified by
+//
// yaml_emitter_set_output().
+//
// @param[in] buffer The buffer with bytes to be written.
// @param[in] size The size of the buffer.
//
// @returns On success, the handler should return @c 1. If the handler failed,
// the returned value should be @c 0.
-//
type yaml_write_handler_t func(emitter *yaml_emitter_t, buffer []byte) error
type yaml_emitter_state_t int
@@ -742,6 +744,8 @@
indent int // The current indentation level.
+ compact_sequence_indent bool // Is '- ' is considered part of the indentation for sequence elements?
+
flow_level int // The current flow level.
root_context bool // Is it the document root context?
#!/bin/bash
set -euo pipefail
tmpdir=$(mktemp -d)
trap "rm -rf \"$tmpdir\"" EXIT
cd "$tmpdir"
# 3.0.1 are identical
gopkg_in_version=3.0.1
go_yaml_in_version=3.0.2
diff_switches=-NruwB
git clone --quiet --depth=1 --branch="v$gopkg_in_version" \
https://github.com/go-yaml/yaml.git \
"gopkg.in/yaml.v3@v$gopkg_in_version"
rm -rf "gopkg.in/yaml.v3@v$gopkg_in_version/.git"
git clone --quiet --depth=1 --branch="v$go_yaml_in_version" \
https://github.com/yaml/go-yaml.git \
"go.yaml.in/yaml/v3@v$go_yaml_in_version"
rm -rf "go.yaml.in/yaml/v3@v$go_yaml_in_version/.git"
diff "$diff_switches" \
"gopkg.in/yaml.v3@v$gopkg_in_version" \
"go.yaml.in/yaml/v3@v$go_yaml_in_version"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment