Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package yq for openSUSE:Factory checked in at 2026-03-18 16:51:39 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/yq (Old) and /work/SRC/openSUSE:Factory/.yq.new.8177 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "yq" Wed Mar 18 16:51:39 2026 rev:24 rq:1340859 version:4.52.4 Changes: -------- --- /work/SRC/openSUSE:Factory/yq/yq.changes 2026-02-03 21:30:06.657135149 +0100 +++ /work/SRC/openSUSE:Factory/.yq.new.8177/yq.changes 2026-03-18 16:53:27.940421474 +0100 @@ -1,0 +2,8 @@ +Wed Mar 18 06:46:55 UTC 2026 - Dirk Müller <[email protected]> + +- update to 4.52.4: + * Dropping windows/arm - no longer supported in cross-compile + * Fixing comments in TOML arrays + * Bumped dependencies + +------------------------------------------------------------------- Old: ---- yq-4.52.2.tar.gz New: ---- yq-4.52.4.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ yq.spec ++++++ --- /var/tmp/diff_new_pack.zLTSGu/_old 2026-03-18 16:53:29.132471254 +0100 +++ /var/tmp/diff_new_pack.zLTSGu/_new 2026-03-18 16:53:29.132471254 +0100 @@ -20,7 +20,7 @@ %global import_path %{provider_prefix} Name: yq -Version: 4.52.2 +Version: 4.52.4 Release: 0 Summary: A portable command-line YAML processor License: MIT ++++++ vendor.tar.gz ++++++ ++++ 51803 lines of diff (skipped) ++++++ yq-4.52.2.tar.gz -> yq-4.52.4.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yq-4.52.2/.goreleaser.yaml new/yq-4.52.4/.goreleaser.yaml --- old/yq-4.52.2/.goreleaser.yaml 2026-01-31 23:19:54.000000000 +0100 +++ new/yq-4.52.4/.goreleaser.yaml 2026-02-14 08:43:09.000000000 +0100 @@ -39,7 +39,6 @@ - openbsd_amd64 - windows_386 - windows_amd64 - - windows_arm - windows_arm64 no_unique_dist_dir: true diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yq-4.52.2/Dockerfile new/yq-4.52.4/Dockerfile --- old/yq-4.52.2/Dockerfile 2026-01-31 23:19:54.000000000 +0100 +++ new/yq-4.52.4/Dockerfile 2026-02-14 08:43:09.000000000 +0100 @@ -1,4 +1,4 @@ -FROM golang:1.25.6 AS builder +FROM golang:1.26.0 AS builder WORKDIR /go/src/mikefarah/yq diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yq-4.52.2/Dockerfile.dev new/yq-4.52.4/Dockerfile.dev --- old/yq-4.52.2/Dockerfile.dev 2026-01-31 23:19:54.000000000 +0100 +++ new/yq-4.52.4/Dockerfile.dev 2026-02-14 08:43:09.000000000 +0100 @@ -1,4 +1,4 @@ -FROM golang:1.25.6 +FROM golang:1.26.0 RUN apt-get update && \ apt-get install -y npm && \ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yq-4.52.2/cmd/version.go new/yq-4.52.4/cmd/version.go --- old/yq-4.52.2/cmd/version.go 2026-01-31 23:19:54.000000000 +0100 +++ new/yq-4.52.4/cmd/version.go 2026-02-14 08:43:09.000000000 +0100 @@ -11,7 +11,7 @@ GitDescribe string // Version is main version number that is being run at the moment. - Version = "v4.52.2" + Version = "v4.52.4" // 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 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yq-4.52.2/cmd/version_test.go new/yq-4.52.4/cmd/version_test.go --- old/yq-4.52.2/cmd/version_test.go 2026-01-31 23:19:54.000000000 +0100 +++ new/yq-4.52.4/cmd/version_test.go 2026-02-14 08:43:09.000000000 +0100 @@ -1,6 +1,9 @@ package cmd -import "testing" +import ( + "strings" + "testing" +) func TestGetVersionDisplay(t *testing.T) { var expectedVersion = ProductName + " (https://github.com/mikefarah/yq/) version " + Version @@ -25,6 +28,18 @@ } func Test_getHumanVersion(t *testing.T) { + // Save original values + origGitDescribe := GitDescribe + origGitCommit := GitCommit + origVersionPrerelease := VersionPrerelease + + // Restore after test + defer func() { + GitDescribe = origGitDescribe + GitCommit = origGitCommit + VersionPrerelease = origVersionPrerelease + }() + GitDescribe = "e42813d" GitCommit = "e42813d+CHANGES" var wanted string @@ -49,3 +64,118 @@ } } } + +func Test_getHumanVersion_NoGitDescribe(t *testing.T) { + // Save original values + origGitDescribe := GitDescribe + origGitCommit := GitCommit + origVersionPrerelease := VersionPrerelease + + // Restore after test + defer func() { + GitDescribe = origGitDescribe + GitCommit = origGitCommit + VersionPrerelease = origVersionPrerelease + }() + + GitDescribe = "" + GitCommit = "" + VersionPrerelease = "" + + got := getHumanVersion() + if got != Version { + t.Errorf("getHumanVersion() = %v, want %v", got, Version) + } +} + +func Test_getHumanVersion_WithPrerelease(t *testing.T) { + // Save original values + origGitDescribe := GitDescribe + origGitCommit := GitCommit + origVersionPrerelease := VersionPrerelease + + // Restore after test + defer func() { + GitDescribe = origGitDescribe + GitCommit = origGitCommit + VersionPrerelease = origVersionPrerelease + }() + + GitDescribe = "" + GitCommit = "abc123" + VersionPrerelease = "beta" + + got := getHumanVersion() + expected := Version + "-beta (abc123)" + if got != expected { + t.Errorf("getHumanVersion() = %v, want %v", got, expected) + } +} + +func Test_getHumanVersion_PrereleaseInVersion(t *testing.T) { + // Save original values + origGitDescribe := GitDescribe + origGitCommit := GitCommit + origVersionPrerelease := VersionPrerelease + + // Restore after test + defer func() { + GitDescribe = origGitDescribe + GitCommit = origGitCommit + VersionPrerelease = origVersionPrerelease + }() + + GitDescribe = "v1.2.3-rc1" + GitCommit = "xyz789" + VersionPrerelease = "rc1" + + got := getHumanVersion() + // Should not duplicate "rc1" since it's already in GitDescribe + expected := "v1.2.3-rc1 (xyz789)" + if got != expected { + t.Errorf("getHumanVersion() = %v, want %v", got, expected) + } +} + +func Test_getHumanVersion_StripSingleQuotes(t *testing.T) { + // Save original values + origGitDescribe := GitDescribe + origGitCommit := GitCommit + origVersionPrerelease := VersionPrerelease + + // Restore after test + defer func() { + GitDescribe = origGitDescribe + GitCommit = origGitCommit + VersionPrerelease = origVersionPrerelease + }() + + GitDescribe = "'v1.2.3'" + GitCommit = "'commit123'" + VersionPrerelease = "" + + got := getHumanVersion() + // Should strip single quotes + if strings.Contains(got, "'") { + t.Errorf("getHumanVersion() = %v, should not contain single quotes", got) + } + expected := "v1.2.3" + if got != expected { + t.Errorf("getHumanVersion() = %v, want %v", got, expected) + } +} + +func TestProductName(t *testing.T) { + if ProductName != "yq" { + t.Errorf("ProductName = %v, want yq", ProductName) + } +} + +func TestVersionIsSet(t *testing.T) { + if Version == "" { + t.Error("Version should not be empty") + } + if !strings.HasPrefix(Version, "v") { + t.Errorf("Version %v should start with 'v'", Version) + } +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yq-4.52.2/go.mod new/yq-4.52.4/go.mod --- old/yq-4.52.2/go.mod 2026-01-31 23:19:54.000000000 +0100 +++ new/yq-4.52.4/go.mod 2026-02-14 08:43:09.000000000 +0100 @@ -20,9 +20,9 @@ github.com/yuin/gopher-lua v1.1.1 github.com/zclconf/go-cty v1.17.0 go.yaml.in/yaml/v4 v4.0.0-rc.3 - golang.org/x/mod v0.31.0 - golang.org/x/net v0.49.0 - golang.org/x/text v0.33.0 + golang.org/x/mod v0.33.0 + golang.org/x/net v0.50.0 + golang.org/x/text v0.34.0 gopkg.in/op/go-logging.v1 v1.0.0-20160211212156-b2cb9fa56473 ) @@ -35,8 +35,8 @@ github.com/mattn/go-isatty v0.0.20 // indirect github.com/mitchellh/go-wordwrap v1.0.1 // indirect golang.org/x/sync v0.19.0 // indirect - golang.org/x/sys v0.40.0 // indirect - golang.org/x/tools v0.40.0 // indirect + golang.org/x/sys v0.41.0 // indirect + golang.org/x/tools v0.41.0 // indirect ) go 1.24.0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yq-4.52.2/go.sum new/yq-4.52.4/go.sum --- old/yq-4.52.2/go.sum 2026-01-31 23:19:54.000000000 +0100 +++ new/yq-4.52.4/go.sum 2026-02-14 08:43:09.000000000 +0100 @@ -70,19 +70,19 @@ go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= go.yaml.in/yaml/v4 v4.0.0-rc.3 h1:3h1fjsh1CTAPjW7q/EMe+C8shx5d8ctzZTrLcs/j8Go= go.yaml.in/yaml/v4 v4.0.0-rc.3/go.mod h1:aZqd9kCMsGL7AuUv/m/PvWLdg5sjJsZ4oHDEnfPPfY0= -golang.org/x/mod v0.31.0 h1:HaW9xtz0+kOcWKwli0ZXy79Ix+UW/vOfmWI5QVd2tgI= -golang.org/x/mod v0.31.0/go.mod h1:43JraMp9cGx1Rx3AqioxrbrhNsLl2l/iNAvuBkrezpg= -golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o= -golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8= +golang.org/x/mod v0.33.0 h1:tHFzIWbBifEmbwtGz65eaWyGiGZatSrT9prnU8DbVL8= +golang.org/x/mod v0.33.0/go.mod h1:swjeQEj+6r7fODbD2cqrnje9PnziFuw4bmLbBZFrQ5w= +golang.org/x/net v0.50.0 h1:ucWh9eiCGyDR3vtzso0WMQinm2Dnt8cFMuQa9K33J60= +golang.org/x/net v0.50.0/go.mod h1:UgoSli3F/pBgdJBHCTc+tp3gmrU4XswgGRgtnwWTfyM= golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4= golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ= -golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= -golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE= -golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8= -golang.org/x/tools v0.40.0 h1:yLkxfA+Qnul4cs9QA3KnlFu0lVmd8JJfoq+E41uSutA= -golang.org/x/tools v0.40.0/go.mod h1:Ik/tzLRlbscWpqqMRjyWYDisX8bG13FrdXp3o4Sr9lc= +golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k= +golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk= +golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA= +golang.org/x/tools v0.41.0 h1:a9b8iMweWG+S0OBnlU36rzLp20z1Rp10w+IY2czHTQc= +golang.org/x/tools v0.41.0/go.mod h1:XSY6eDqxVNiYgezAVqqCeihT4j1U2CCsqvH3WhQpnlg= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/op/go-logging.v1 v1.0.0-20160211212156-b2cb9fa56473 h1:6D+BvnJ/j6e222UW8s2qTSe3wGBtvo0MbVQG/c5k8RE= gopkg.in/op/go-logging.v1 v1.0.0-20160211212156-b2cb9fa56473/go.mod h1:N1eN2tsCx0Ydtgjl4cqmbRCsY4/+z4cYDeqwZTk6zog= diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yq-4.52.2/pkg/yqlib/decoder_toml.go new/yq-4.52.4/pkg/yqlib/decoder_toml.go --- old/yq-4.52.2/pkg/yqlib/decoder_toml.go 2026-01-31 23:19:54.000000000 +0100 +++ new/yq-4.52.4/pkg/yqlib/decoder_toml.go 2026-02-14 08:43:09.000000000 +0100 @@ -157,13 +157,30 @@ func (dec *tomlDecoder) createArray(tomlNode *toml.Node) (*CandidateNode, error) { content := make([]*CandidateNode, 0) + var pendingArrayComments []string + iterator := tomlNode.Children() for iterator.Next() { child := iterator.Node() + + // Handle comments within arrays + if child.Kind == toml.Comment { + // Collect comments to attach to the next array element + pendingArrayComments = append(pendingArrayComments, string(child.Data)) + continue + } + yamlNode, err := dec.decodeNode(child) if err != nil { return nil, err } + + // Attach any pending comments to this array element + if len(pendingArrayComments) > 0 { + yamlNode.HeadComment = strings.Join(pendingArrayComments, "\n") + pendingArrayComments = make([]string, 0) + } + content = append(content, yamlNode) } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yq-4.52.2/pkg/yqlib/decoder_uri_test.go new/yq-4.52.4/pkg/yqlib/decoder_uri_test.go --- old/yq-4.52.2/pkg/yqlib/decoder_uri_test.go 1970-01-01 01:00:00.000000000 +0100 +++ new/yq-4.52.4/pkg/yqlib/decoder_uri_test.go 2026-02-14 08:43:09.000000000 +0100 @@ -0,0 +1,160 @@ +//go:build !yq_nouri + +package yqlib + +import ( + "io" + "strings" + "testing" + + "github.com/mikefarah/yq/v4/test" +) + +func TestUriDecoder_Init(t *testing.T) { + decoder := NewUriDecoder() + reader := strings.NewReader("test") + err := decoder.Init(reader) + test.AssertResult(t, nil, err) +} + +func TestUriDecoder_DecodeSimpleString(t *testing.T) { + decoder := NewUriDecoder() + reader := strings.NewReader("hello%20world") + err := decoder.Init(reader) + test.AssertResult(t, nil, err) + + node, err := decoder.Decode() + test.AssertResult(t, nil, err) + test.AssertResult(t, "!!str", node.Tag) + test.AssertResult(t, "hello world", node.Value) +} + +func TestUriDecoder_DecodeSpecialCharacters(t *testing.T) { + decoder := NewUriDecoder() + reader := strings.NewReader("hello%21%40%23%24%25") + err := decoder.Init(reader) + test.AssertResult(t, nil, err) + + node, err := decoder.Decode() + test.AssertResult(t, nil, err) + test.AssertResult(t, "hello!@#$%", node.Value) +} + +func TestUriDecoder_DecodeUTF8(t *testing.T) { + decoder := NewUriDecoder() + reader := strings.NewReader("%E2%9C%93%20check") + err := decoder.Init(reader) + test.AssertResult(t, nil, err) + + node, err := decoder.Decode() + test.AssertResult(t, nil, err) + test.AssertResult(t, "✓ check", node.Value) +} + +func TestUriDecoder_DecodePlusSign(t *testing.T) { + decoder := NewUriDecoder() + reader := strings.NewReader("a+b") + err := decoder.Init(reader) + test.AssertResult(t, nil, err) + + node, err := decoder.Decode() + test.AssertResult(t, nil, err) + // Note: url.QueryUnescape does NOT convert + to space + // That's only for form encoding (url.ParseQuery) + test.AssertResult(t, "a b", node.Value) +} + +func TestUriDecoder_DecodeEmptyString(t *testing.T) { + decoder := NewUriDecoder() + reader := strings.NewReader("") + err := decoder.Init(reader) + test.AssertResult(t, nil, err) + + node, err := decoder.Decode() + test.AssertResult(t, nil, err) + test.AssertResult(t, "", node.Value) + + // Second decode should return EOF + node, err = decoder.Decode() + test.AssertResult(t, io.EOF, err) + test.AssertResult(t, (*CandidateNode)(nil), node) +} + +func TestUriDecoder_DecodeMultipleCalls(t *testing.T) { + decoder := NewUriDecoder() + reader := strings.NewReader("test") + err := decoder.Init(reader) + test.AssertResult(t, nil, err) + + // First decode + node, err := decoder.Decode() + test.AssertResult(t, nil, err) + test.AssertResult(t, "test", node.Value) + + // Second decode should return EOF since we've consumed all input + node, err = decoder.Decode() + test.AssertResult(t, io.EOF, err) + test.AssertResult(t, (*CandidateNode)(nil), node) +} + +func TestUriDecoder_DecodeInvalidEscape(t *testing.T) { + decoder := NewUriDecoder() + reader := strings.NewReader("test%ZZ") + err := decoder.Init(reader) + test.AssertResult(t, nil, err) + + _, err = decoder.Decode() + // Should return an error for invalid escape sequence + if err == nil { + t.Error("Expected error for invalid escape sequence, got nil") + } +} + +func TestUriDecoder_DecodeSlashAndQuery(t *testing.T) { + decoder := NewUriDecoder() + reader := strings.NewReader("path%2Fto%2Ffile%3Fquery%3Dvalue") + err := decoder.Init(reader) + test.AssertResult(t, nil, err) + + node, err := decoder.Decode() + test.AssertResult(t, nil, err) + test.AssertResult(t, "path/to/file?query=value", node.Value) +} + +func TestUriDecoder_DecodePercent(t *testing.T) { + decoder := NewUriDecoder() + reader := strings.NewReader("100%25") + err := decoder.Init(reader) + test.AssertResult(t, nil, err) + + node, err := decoder.Decode() + test.AssertResult(t, nil, err) + test.AssertResult(t, "100%", node.Value) +} + +func TestUriDecoder_DecodeNoEscaping(t *testing.T) { + decoder := NewUriDecoder() + reader := strings.NewReader("simple_text-123") + err := decoder.Init(reader) + test.AssertResult(t, nil, err) + + node, err := decoder.Decode() + test.AssertResult(t, nil, err) + test.AssertResult(t, "simple_text-123", node.Value) +} + +// Mock reader that returns an error +type errorReader struct{} + +func (e *errorReader) Read(_ []byte) (n int, err error) { + return 0, io.ErrUnexpectedEOF +} + +func TestUriDecoder_DecodeReadError(t *testing.T) { + decoder := NewUriDecoder() + err := decoder.Init(&errorReader{}) + test.AssertResult(t, nil, err) + + _, err = decoder.Decode() + test.AssertResult(t, io.ErrUnexpectedEOF, err) +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yq-4.52.2/pkg/yqlib/encoder_toml.go new/yq-4.52.4/pkg/yqlib/encoder_toml.go --- old/yq-4.52.2/pkg/yqlib/encoder_toml.go 2026-01-31 23:19:54.000000000 +0100 +++ new/yq-4.52.4/pkg/yqlib/encoder_toml.go 2026-02-14 08:43:09.000000000 +0100 @@ -222,6 +222,81 @@ return err } + // Check if any array elements have head comments - if so, use multiline format + hasElementComments := false + for _, it := range seq.Content { + if it.HeadComment != "" { + hasElementComments = true + break + } + } + + if hasElementComments { + // Write multiline array format with comments + if _, err := w.Write([]byte(key + " = [\n")); err != nil { + return err + } + + for i, it := range seq.Content { + // Write head comment for this element + if it.HeadComment != "" { + commentLines := strings.Split(it.HeadComment, "\n") + for _, commentLine := range commentLines { + if strings.TrimSpace(commentLine) != "" { + if !strings.HasPrefix(strings.TrimSpace(commentLine), "#") { + commentLine = "# " + commentLine + } + if _, err := w.Write([]byte(" " + commentLine + "\n")); err != nil { + return err + } + } + } + } + + // Write the element value + var itemStr string + switch it.Kind { + case ScalarNode: + itemStr = te.formatScalar(it) + case SequenceNode: + nested, err := te.sequenceToInlineArray(it) + if err != nil { + return err + } + itemStr = nested + case MappingNode: + inline, err := te.mappingToInlineTable(it) + if err != nil { + return err + } + itemStr = inline + case AliasNode: + return fmt.Errorf("aliases are not supported in TOML") + default: + return fmt.Errorf("unsupported array item kind: %v", it.Kind) + } + + // Always add trailing comma in multiline arrays + itemStr += "," + + if _, err := w.Write([]byte(" " + itemStr + "\n")); err != nil { + return err + } + + // Add blank line between elements (except after the last one) + if i < len(seq.Content)-1 { + if _, err := w.Write([]byte("\n")); err != nil { + return err + } + } + } + + if _, err := w.Write([]byte("]\n")); err != nil { + return err + } + return nil + } + // Join scalars or nested arrays recursively into TOML array syntax items := make([]string, 0, len(seq.Content)) for _, it := range seq.Content { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yq-4.52.2/pkg/yqlib/hcl_test.go new/yq-4.52.4/pkg/yqlib/hcl_test.go --- old/yq-4.52.2/pkg/yqlib/hcl_test.go 2026-01-31 23:19:54.000000000 +0100 +++ new/yq-4.52.4/pkg/yqlib/hcl_test.go 2026-02-14 08:43:09.000000000 +0100 @@ -4,6 +4,7 @@ import ( "bufio" + "bytes" "fmt" "testing" @@ -543,6 +544,35 @@ writeOrPanic(w, fmt.Sprintf("```hcl\n%v```\n\n", mustProcessFormatScenario(s, NewHclDecoder(), NewHclEncoder(ConfiguredHclPreferences)))) } +func TestHclEncoderPrintDocumentSeparator(t *testing.T) { + encoder := NewHclEncoder(ConfiguredHclPreferences) + var buf bytes.Buffer + writer := bufio.NewWriter(&buf) + + err := encoder.PrintDocumentSeparator(writer) + writer.Flush() + + test.AssertResult(t, nil, err) + test.AssertResult(t, "", buf.String()) +} + +func TestHclEncoderPrintLeadingContent(t *testing.T) { + encoder := NewHclEncoder(ConfiguredHclPreferences) + var buf bytes.Buffer + writer := bufio.NewWriter(&buf) + + err := encoder.PrintLeadingContent(writer, "some content") + writer.Flush() + + test.AssertResult(t, nil, err) + test.AssertResult(t, "", buf.String()) +} + +func TestHclEncoderCanHandleAliases(t *testing.T) { + encoder := NewHclEncoder(ConfiguredHclPreferences) + test.AssertResult(t, false, encoder.CanHandleAliases()) +} + func TestHclFormatScenarios(t *testing.T) { for _, tt := range hclFormatScenarios { testHclScenario(t, tt) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yq-4.52.2/pkg/yqlib/printer_node_info_test.go new/yq-4.52.4/pkg/yqlib/printer_node_info_test.go --- old/yq-4.52.2/pkg/yqlib/printer_node_info_test.go 2026-01-31 23:19:54.000000000 +0100 +++ new/yq-4.52.4/pkg/yqlib/printer_node_info_test.go 2026-02-14 08:43:09.000000000 +0100 @@ -49,3 +49,179 @@ test.AssertResult(t, true, strings.Contains(outStr, "footComment: foot")) test.AssertResult(t, true, strings.Contains(outStr, "anchor: anchor")) } + +func TestNodeInfoPrinter_PrintedAnything_True(t *testing.T) { + node := &CandidateNode{ + Kind: ScalarNode, + Tag: "!!str", + Value: "test", + } + listNodes := list.New() + listNodes.PushBack(node) + + var output bytes.Buffer + writer := bufio.NewWriter(&output) + printer := NewNodeInfoPrinter(NewSinglePrinterWriter(writer)) + + // Before printing, should be false + test.AssertResult(t, false, printer.PrintedAnything()) + + err := printer.PrintResults(listNodes) + writer.Flush() + if err != nil { + t.Fatalf("PrintResults error: %v", err) + } + + // After printing, should be true + test.AssertResult(t, true, printer.PrintedAnything()) +} + +func TestNodeInfoPrinter_PrintedAnything_False(t *testing.T) { + listNodes := list.New() + + var output bytes.Buffer + writer := bufio.NewWriter(&output) + printer := NewNodeInfoPrinter(NewSinglePrinterWriter(writer)) + + err := printer.PrintResults(listNodes) + writer.Flush() + if err != nil { + t.Fatalf("PrintResults error: %v", err) + } + + // No nodes printed, should still be false + test.AssertResult(t, false, printer.PrintedAnything()) +} + +func TestNodeInfoPrinter_SetNulSepOutput(_ *testing.T) { + var output bytes.Buffer + writer := bufio.NewWriter(&output) + printer := NewNodeInfoPrinter(NewSinglePrinterWriter(writer)) + + // Should not panic or error + printer.SetNulSepOutput(true) + printer.SetNulSepOutput(false) +} + +func TestNodeInfoPrinter_SetAppendix(t *testing.T) { + node := &CandidateNode{ + Kind: ScalarNode, + Tag: "!!str", + Value: "test", + } + listNodes := list.New() + listNodes.PushBack(node) + + var output bytes.Buffer + writer := bufio.NewWriter(&output) + printer := NewNodeInfoPrinter(NewSinglePrinterWriter(writer)) + + appendixText := "This is appendix text\n" + appendixReader := strings.NewReader(appendixText) + printer.SetAppendix(appendixReader) + + err := printer.PrintResults(listNodes) + writer.Flush() + if err != nil { + t.Fatalf("PrintResults error: %v", err) + } + + outStr := output.String() + test.AssertResult(t, true, strings.Contains(outStr, "test")) + test.AssertResult(t, true, strings.Contains(outStr, appendixText)) +} + +func TestNodeInfoPrinter_MultipleNodes(t *testing.T) { + node1 := &CandidateNode{ + Kind: ScalarNode, + Tag: "!!str", + Value: "first", + } + node2 := &CandidateNode{ + Kind: ScalarNode, + Tag: "!!str", + Value: "second", + } + listNodes := list.New() + listNodes.PushBack(node1) + listNodes.PushBack(node2) + + var output bytes.Buffer + writer := bufio.NewWriter(&output) + printer := NewNodeInfoPrinter(NewSinglePrinterWriter(writer)) + + err := printer.PrintResults(listNodes) + writer.Flush() + if err != nil { + t.Fatalf("PrintResults error: %v", err) + } + + outStr := output.String() + test.AssertResult(t, true, strings.Contains(outStr, "value: first")) + test.AssertResult(t, true, strings.Contains(outStr, "value: second")) +} + +func TestNodeInfoPrinter_SequenceNode(t *testing.T) { + node := &CandidateNode{ + Kind: SequenceNode, + Tag: "!!seq", + Style: FlowStyle, + } + listNodes := list.New() + listNodes.PushBack(node) + + var output bytes.Buffer + writer := bufio.NewWriter(&output) + printer := NewNodeInfoPrinter(NewSinglePrinterWriter(writer)) + + err := printer.PrintResults(listNodes) + writer.Flush() + if err != nil { + t.Fatalf("PrintResults error: %v", err) + } + + outStr := output.String() + test.AssertResult(t, true, strings.Contains(outStr, "kind: SequenceNode")) + test.AssertResult(t, true, strings.Contains(outStr, "tag: '!!seq'")) + test.AssertResult(t, true, strings.Contains(outStr, "style: FlowStyle")) +} + +func TestNodeInfoPrinter_MappingNode(t *testing.T) { + node := &CandidateNode{ + Kind: MappingNode, + Tag: "!!map", + } + listNodes := list.New() + listNodes.PushBack(node) + + var output bytes.Buffer + writer := bufio.NewWriter(&output) + printer := NewNodeInfoPrinter(NewSinglePrinterWriter(writer)) + + err := printer.PrintResults(listNodes) + writer.Flush() + if err != nil { + t.Fatalf("PrintResults error: %v", err) + } + + outStr := output.String() + test.AssertResult(t, true, strings.Contains(outStr, "kind: MappingNode")) + test.AssertResult(t, true, strings.Contains(outStr, "tag: '!!map'")) +} + +func TestNodeInfoPrinter_EmptyList(t *testing.T) { + listNodes := list.New() + + var output bytes.Buffer + writer := bufio.NewWriter(&output) + printer := NewNodeInfoPrinter(NewSinglePrinterWriter(writer)) + + err := printer.PrintResults(listNodes) + writer.Flush() + if err != nil { + t.Fatalf("PrintResults error: %v", err) + } + + test.AssertResult(t, "", output.String()) + test.AssertResult(t, false, printer.PrintedAnything()) +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yq-4.52.2/pkg/yqlib/toml_test.go new/yq-4.52.4/pkg/yqlib/toml_test.go --- old/yq-4.52.2/pkg/yqlib/toml_test.go 2026-01-31 23:19:54.000000000 +0100 +++ new/yq-4.52.4/pkg/yqlib/toml_test.go 2026-02-14 08:43:09.000000000 +0100 @@ -230,12 +230,16 @@ // Reproduce bug for https://github.com/mikefarah/yq/issues/2588 // Bug: standalone comments inside a table cause subsequent key-values to be assigned at root. -var issue2588RustToolchainWithComments = ` -[owner] +var issue2588RustToolchainWithComments = `[owner] # comment name = "Tomer" ` +var tableWithComment = `[owner] +# comment +[things] +` + var sampleFromWeb = `# This is a TOML document title = "TOML Example" @@ -267,6 +271,16 @@ [[array.subarray.subsubarray]] ` +var tomlTableWithComments = `[section] +the_array = [ + # comment + "value 1", + + # comment + "value 2", +] +` + var expectedSubArrays = `array: - subarray: - subsubarray: @@ -575,12 +589,31 @@ scenarioType: "decode", }, { + skipDoc: true, + input: issue2588RustToolchainWithComments, + expected: issue2588RustToolchainWithComments, + scenarioType: "roundtrip", + }, + { + skipDoc: true, + input: tableWithComment, + expression: ".owner | headComment", + expected: "comment\n", + scenarioType: "roundtrip", + }, + { description: "Roundtrip: sample from web", input: sampleFromWeb, expression: ".", expected: sampleFromWeb, scenarioType: "roundtrip", }, + { + skipDoc: true, + input: tomlTableWithComments, + expected: tomlTableWithComments, + scenarioType: "roundtrip", + }, } func testTomlScenario(t *testing.T, s formatScenario) { @@ -933,3 +966,32 @@ }) } } + +func TestTomlEncoderPrintDocumentSeparator(t *testing.T) { + encoder := NewTomlEncoder() + var buf bytes.Buffer + writer := bufio.NewWriter(&buf) + + err := encoder.PrintDocumentSeparator(writer) + writer.Flush() + + test.AssertResult(t, nil, err) + test.AssertResult(t, "", buf.String()) +} + +func TestTomlEncoderPrintLeadingContent(t *testing.T) { + encoder := NewTomlEncoder() + var buf bytes.Buffer + writer := bufio.NewWriter(&buf) + + err := encoder.PrintLeadingContent(writer, "some content") + writer.Flush() + + test.AssertResult(t, nil, err) + test.AssertResult(t, "", buf.String()) +} + +func TestTomlEncoderCanHandleAliases(t *testing.T) { + encoder := NewTomlEncoder() + test.AssertResult(t, false, encoder.CanHandleAliases()) +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yq-4.52.2/project-words.txt new/yq-4.52.4/project-words.txt --- old/yq-4.52.2/project-words.txt 2026-01-31 23:19:54.000000000 +0100 +++ new/yq-4.52.4/project-words.txt 2026-02-14 08:43:09.000000000 +0100 @@ -293,4 +293,8 @@ behaviour GOFLAGS gocache -subsubarray \ No newline at end of file +subsubarray +Ffile +Fquery +coverpkg +gsub \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yq-4.52.2/release_notes.txt new/yq-4.52.4/release_notes.txt --- old/yq-4.52.2/release_notes.txt 2026-01-31 23:19:54.000000000 +0100 +++ new/yq-4.52.4/release_notes.txt 2026-02-14 08:43:09.000000000 +0100 @@ -1,3 +1,8 @@ +4.52.3: + - Fixing comments in TOML arrays (#2592) + - Bumped dependencies + + 4.52.2: - Fixed bad instructions file breaking go-install (#2587) Thanks @theyoprst - Fixed TOML table scope after comments (#2588) Thanks @tomers diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yq-4.52.2/scripts/coverage.sh new/yq-4.52.4/scripts/coverage.sh --- old/yq-4.52.2/scripts/coverage.sh 2026-01-31 23:19:54.000000000 +0100 +++ new/yq-4.52.4/scripts/coverage.sh 2026-02-14 08:43:09.000000000 +0100 @@ -3,7 +3,9 @@ set -e echo "Running tests and generating coverage..." -go test -coverprofile=coverage.out -v $(go list ./... | grep -v -E 'examples' | grep -v -E 'test') +packages=$(go list ./... | grep -v -E 'examples' | grep -v -E 'test' | tr '\n' ',' | sed 's/,$//') +test_packages=$(go list ./... | grep -v -E 'examples' | grep -v -E 'test' | grep -v '^github.com/mikefarah/yq/v4$') +go test -coverprofile=coverage.out -coverpkg="$packages" -v $test_packages echo "Generating HTML coverage report..." go tool cover -html=coverage.out -o coverage.html @@ -58,11 +60,31 @@ done echo "" -echo "Top 10 files needing attention (lowest coverage):" +echo "Top 10 files by uncovered statements:" echo "=================================================" -grep -v "TOTAL:" coverage_sorted.txt | tail -10 | while read percent file; do +# Calculate uncovered statements for each file and sort by that +go tool cover -func=coverage.out | grep -E "\.go:[0-9]+:" | \ +awk '{ + # Extract filename and percentage + split($1, parts, ":") + file = parts[1] + pct = $NF + gsub(/%/, "", pct) + + # Track stats per file + total[file]++ + covered[file] += pct +} +END { + for (file in total) { + avg_pct = covered[file] / total[file] + uncovered = total[file] * (100 - avg_pct) / 100 + covered_count = total[file] - uncovered + printf "%.0f %d %.0f %.1f %s\n", uncovered, total[file], covered_count, avg_pct, file + } +}' | sort -rn | head -10 | while read uncovered total covered pct file; do filename=$(basename "$file") - printf "%-60s %8.1f%%\n" "$filename" "$percent" + printf "%-60s %4d uncovered (%4d/%4d, %5.1f%%)\n" "$filename" "$uncovered" "$covered" "$total" "$pct" done echo "" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yq-4.52.2/snap/snapcraft.yaml new/yq-4.52.4/snap/snapcraft.yaml --- old/yq-4.52.2/snap/snapcraft.yaml 2026-01-31 23:19:54.000000000 +0100 +++ new/yq-4.52.4/snap/snapcraft.yaml 2026-02-14 08:43:09.000000000 +0100 @@ -1,5 +1,5 @@ name: yq -version: 'v4.52.2' +version: 'v4.52.4' summary: A lightweight and portable command-line data file processor description: | `yq` uses [jq](https://github.com/stedolan/jq) like syntax but works with yaml, json, xml, csv, properties and TOML files. @@ -32,6 +32,6 @@ build-environment: - CGO_ENABLED: 0 source: https://github.com/mikefarah/yq.git - source-tag: v4.52.2 + source-tag: v4.52.4 build-snaps: - go/latest/stable
