Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package nfpm for openSUSE:Factory checked in at 2026-03-12 22:22:33 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/nfpm (Old) and /work/SRC/openSUSE:Factory/.nfpm.new.8177 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "nfpm" Thu Mar 12 22:22:33 2026 rev:18 rq:1338475 version:2.45.1 Changes: -------- --- /work/SRC/openSUSE:Factory/nfpm/nfpm.changes 2026-02-04 21:08:16.170058149 +0100 +++ /work/SRC/openSUSE:Factory/.nfpm.new.8177/nfpm.changes 2026-03-12 22:27:21.390841969 +0100 @@ -1,0 +2,28 @@ +Thu Mar 12 11:47:20 UTC 2026 - Johannes Kastl <[email protected]> + +- Update to version 2.45.1: + * Bug fixes + - a1d6813: fix(apk): handle all/noarch (#1034) (@caarlos0) + - 7c60130: fix: consistent gzip level 9 default for RPM and DEB + compression (#1050) (@Copilot) + - 2d7995c: fix: gzip:9 and some lint issues (@caarlos0) + - 532c31d: fix: lint (@caarlos0) + - 427463f: fix: remove invalid License field from deb control + (#1035) (@caarlos0) + * Build process updates + - 8b0ad9b: ci(deps): bump the actions group with 2 updates + (#1042) (@dependabot[bot]) + - 609f487: ci(deps): bump the actions group with 2 updates + (#1046) (@dependabot[bot]) + - 3a92613: ci(deps): bump the actions group with 3 updates + (#1043) (@dependabot[bot]) + - d3c4f29: ci(deps): bump the actions group with 4 updates + (#1039) (@dependabot[bot]) + - 71285a7: ci(deps): bump the actions group with 6 updates + (#1049) (@dependabot[bot]) + * Other work + - 4ac5dfd: docs: Update install.md (#1047) (@pebosi) + - d11b063: docs: update cmd docs (@caarlos0) + - c72e5be: refactor: modernize (@caarlos0) + +------------------------------------------------------------------- Old: ---- nfpm-2.45.0.obscpio New: ---- nfpm-2.45.1.obscpio ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ nfpm.spec ++++++ --- /var/tmp/diff_new_pack.0psCot/_old 2026-03-12 22:27:22.582891927 +0100 +++ /var/tmp/diff_new_pack.0psCot/_new 2026-03-12 22:27:22.582891927 +0100 @@ -17,7 +17,7 @@ Name: nfpm -Version: 2.45.0 +Version: 2.45.1 Release: 0 Summary: Simple deb, rpm, apk and arch linux packager written in Go License: MIT ++++++ _service ++++++ --- /var/tmp/diff_new_pack.0psCot/_old 2026-03-12 22:27:22.618893436 +0100 +++ /var/tmp/diff_new_pack.0psCot/_new 2026-03-12 22:27:22.622893604 +0100 @@ -3,7 +3,7 @@ <param name="url">https://github.com/goreleaser/nfpm</param> <param name="scm">git</param> <param name="exclude">.git</param> - <param name="revision">v2.45.0</param> + <param name="revision">v2.45.1</param> <param name="versionformat">@PARENT_TAG@</param> <param name="versionrewrite-pattern">v(.*)</param> <param name="changesgenerate">enable</param> ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.0psCot/_old 2026-03-12 22:27:22.654894945 +0100 +++ /var/tmp/diff_new_pack.0psCot/_new 2026-03-12 22:27:22.658895112 +0100 @@ -1,6 +1,6 @@ <servicedata> <service name="tar_scm"> <param name="url">https://github.com/goreleaser/nfpm</param> - <param name="changesrevision">be6fd83eed6f241359ae3e7d340a13f197ae6463</param></service></servicedata> + <param name="changesrevision">532c31d97dab4308fbfcaaaf6452c548325e56df</param></service></servicedata> (No newline at EOF) ++++++ nfpm-2.45.0.obscpio -> nfpm-2.45.1.obscpio ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nfpm-2.45.0/apk/apk.go new/nfpm-2.45.1/apk/apk.go --- old/nfpm-2.45.0/apk/apk.go 2026-02-03 13:30:36.000000000 +0100 +++ new/nfpm-2.45.1/apk/apk.go 2026-03-11 17:38:01.000000000 +0100 @@ -61,6 +61,7 @@ // https://github.com/golang/go/blob/master/src/internal/syslist/syslist.go // nolint: gochecknoglobals var archToAlpine = map[string]string{ + "all": "noarch", "386": "x86", "amd64": "x86_64", "arm64": "aarch64", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nfpm-2.45.0/apk/apk_test.go new/nfpm-2.45.1/apk/apk_test.go --- old/nfpm-2.45.0/apk/apk_test.go 2026-02-03 13:30:36.000000000 +0100 +++ new/nfpm-2.45.1/apk/apk_test.go 2026-03-11 17:38:01.000000000 +0100 @@ -139,7 +139,6 @@ "etc/fake/fake3.conf": "96c335dc28122b5f09a4cef74b156cd24c23784c", } for _, arch := range []string{"386", "amd64"} { - arch := arch t.Run(arch, func(t *testing.T) { info := exampleInfo() info.Arch = arch @@ -518,7 +517,7 @@ }, { Arch: "all", Version: "1.2.3", - Expect: "default_1.2.3_all.apk", + Expect: "default_1.2.3_noarch.apk", }, { Arch: "386", Version: "1.2.3", Release: "1", Prerelease: "beta1", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nfpm-2.45.0/arch/arch_test.go new/nfpm-2.45.1/arch/arch_test.go --- old/nfpm-2.45.0/arch/arch_test.go 2026-02-03 13:30:36.000000000 +0100 +++ new/nfpm-2.45.1/arch/arch_test.go 2026-03-11 17:38:01.000000000 +0100 @@ -95,7 +95,6 @@ func TestArch(t *testing.T) { for _, arch := range []string{"386", "amd64", "arm64"} { - arch := arch t.Run(arch, func(t *testing.T) { info := exampleInfo() info.Arch = arch @@ -131,7 +130,6 @@ func TestArchConventionalFileName(t *testing.T) { for _, arch := range []string{"386", "amd64", "arm64"} { - arch := arch t.Run(arch, func(t *testing.T) { info := exampleInfo() info.Arch = arch @@ -378,7 +376,7 @@ "./usr/share/nfpm-repro/b/b.txt": {expectedTime, "mode=644", "size=7", "type=file", "md5digest=551a67cc6e06de1910061fe318d28f72", "sha256digest=73a2c64f9545172c1195efb6616ca5f7afd1df6f245407cafb90de3998a1c97f"}, } - for _, line := range strings.Split(string(mtreeContentBts), "\n") { + for line := range strings.SplitSeq(string(mtreeContentBts), "\n") { if line == "#mtree" || line == "" { continue } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nfpm-2.45.0/deb/deb.go new/nfpm-2.45.1/deb/deb.go --- old/nfpm-2.45.0/deb/deb.go 2026-02-03 13:30:36.000000000 +0100 +++ new/nfpm-2.45.1/deb/deb.go 2026-03-11 17:38:01.000000000 +0100 @@ -5,6 +5,7 @@ "archive/tar" "bufio" "bytes" + "cmp" "compress/gzip" "crypto/md5" // nolint:gas "crypto/sha1" @@ -299,9 +300,7 @@ // Priority should be set on all packages per: // https://www.debian.org/doc/debian-policy/ch-archive.html#priorities // "optional" seems to be the safe/sane default here - if info.Priority == "" { - info.Priority = "optional" - } + info.Priority = cmp.Or(info.Priority, "optional") // The safe thing here feels like defaulting to something like below. // That will prevent existing configs from breaking anyway... Wondering @@ -311,6 +310,8 @@ deprecation.Println("Leaving the 'maintainer' field unset will not be allowed in a future version") info.Maintainer = "Unset Maintainer <unset@localhost>" } + + info.Deb.Compression = cmp.Or(info.Deb.Compression, "gzip") } func addArFile(w *ar.Writer, name string, body []byte, date time.Time) error { @@ -341,10 +342,6 @@ dataTarballWriteCloser io.WriteCloser ) - if info.Deb.Compression == "" { - info.Deb.Compression = "gzip:-1" // the default for now - } - parts := strings.Split(info.Deb.Compression, ":") if len(parts) > 2 { return nil, nil, 0, "", fmt.Errorf("malformed compressor setting: %s", info.Deb.Compression) @@ -785,9 +782,6 @@ {{- if .Info.Deb.ArchVariant}} Architecture-Variant: {{ .Info.Deb.ArchVariant }} {{- end }} -{{- if .Info.License }} -License: {{.Info.License}} -{{- end }} {{- if .Info.Maintainer}} Maintainer: {{.Info.Maintainer}} {{- end }} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nfpm-2.45.0/deb/deb_test.go new/nfpm-2.45.1/deb/deb_test.go --- old/nfpm-2.45.0/deb/deb_test.go 2026-02-03 13:30:36.000000000 +0100 +++ new/nfpm-2.45.1/deb/deb_test.go 2026-03-11 17:38:01.000000000 +0100 @@ -112,7 +112,6 @@ func TestDeb(t *testing.T) { for _, arch := range []string{"386", "amd64"} { - arch := arch t.Run(arch, func(t *testing.T) { info := exampleInfo() info.Arch = arch @@ -133,7 +132,7 @@ } func extractDebArchitecture(deb *bytes.Buffer) string { - for _, s := range strings.Split(deb.String(), "\n") { + for s := range strings.SplitSeq(deb.String(), "\n") { if strings.Contains(s, "Architecture: ") { return strings.TrimPrefix(s, "Architecture: ") } @@ -169,7 +168,7 @@ } func extractDebVersion(deb *bytes.Buffer) string { - for _, s := range strings.Split(deb.String(), "\n") { + for s := range strings.SplitSeq(deb.String(), "\n") { if strings.Contains(s, "Version: ") { return strings.TrimPrefix(s, "Version: ") } @@ -636,8 +635,9 @@ Changelog: "../testdata/changelog.yaml", Maintainer: "maintainer", } - err := nfpm.PrepareForPackager(withChangelogIfRequested(info), packagerName) - require.NoError(t, err) + + Default.SetPackagerDefaults(info) + require.NoError(t, nfpm.PrepareForPackager(withChangelogIfRequested(info), packagerName)) dataTarball, _, _, dataTarballName, err := createDataTarball(info) require.NoError(t, err) @@ -660,8 +660,9 @@ Version: "1.0.0", Maintainer: "maintainer", } - err := nfpm.PrepareForPackager(withChangelogIfRequested(info), packagerName) - require.NoError(t, err) + + Default.SetPackagerDefaults(info) + require.NoError(t, nfpm.PrepareForPackager(withChangelogIfRequested(info), packagerName)) dataTarball, _, _, dataTarballName, err := createDataTarball(info) require.NoError(t, err) @@ -767,8 +768,9 @@ }, }, } - err := nfpm.PrepareForPackager(withChangelogIfRequested(info), packagerName) - require.NoError(t, err) + + Default.SetPackagerDefaults(info) + require.NoError(t, nfpm.PrepareForPackager(withChangelogIfRequested(info), packagerName)) dataTarball, _, _, dataTarballName, err := createDataTarball(info) require.NoError(t, err) @@ -791,8 +793,9 @@ }, } info.Changelog = "../testdata/changelog.yaml" - err := nfpm.PrepareForPackager(withChangelogIfRequested(info), packagerName) - require.NoError(t, err) + + Default.SetPackagerDefaults(info) + require.NoError(t, nfpm.PrepareForPackager(withChangelogIfRequested(info), packagerName)) dataTarball, md5sums, instSize, tarballName, err := createDataTarball(info) require.NoError(t, err) @@ -814,8 +817,8 @@ } } - err := nfpm.PrepareForPackager(withChangelogIfRequested(info), packagerName) - require.NoError(t, err) + Default.SetPackagerDefaults(info) + require.NoError(t, nfpm.PrepareForPackager(withChangelogIfRequested(info), packagerName)) dataTarball, md5sums, instSize, tarballName, err := createDataTarball(info) require.NoError(t, err) @@ -872,6 +875,7 @@ }, } + Default.SetPackagerDefaults(info) require.NoError(t, nfpm.PrepareForPackager(withChangelogIfRequested(info), packagerName)) deflatedDataTarball, _, _, dataTarballName, err := createDataTarball(info) @@ -934,6 +938,7 @@ }, } + Default.SetPackagerDefaults(info) require.NoError(t, nfpm.PrepareForPackager(withChangelogIfRequested(info), packagerName)) deflatedDataTarball, _, _, dataTarballName, err := createDataTarball(info) @@ -1089,6 +1094,8 @@ Destination: "/test/{file}[", }, } + + Default.SetPackagerDefaults(info) require.NoError(t, nfpm.PrepareForPackager(withChangelogIfRequested(info), packagerName)) dataTarball, _, _, tarballName, err := createDataTarball(info) @@ -1115,6 +1122,8 @@ Destination: "/etc/foo", }, } + + Default.SetPackagerDefaults(info) require.NoError(t, nfpm.PrepareForPackager(withChangelogIfRequested(info), packagerName)) expected := map[string]bool{ @@ -1184,8 +1193,6 @@ } for _, testCase := range testCases { - testCase := testCase - t.Run(testCase.algorithm, func(t *testing.T) { info := exampleInfo() info.Deb.Compression = testCase.algorithm @@ -1213,6 +1220,23 @@ } } +func TestDefaultCompressionMatchesExplicitGzip(t *testing.T) { + // When compression is unset, it should default to gzip at the same level + // as explicitly setting compression to "gzip", producing identical output. + buildDeb := func(compression string) []byte { + info := exampleInfo() + info.Deb.Compression = compression + + var deb bytes.Buffer + require.NoError(t, Default.Package(info, &deb)) + return deb.Bytes() + } + + defaultDeb := buildDeb("") + explicitGzipDeb := buildDeb("gzip") + require.Len(t, explicitGzipDeb, len(defaultDeb), "default compression should produce identical output to explicit 'gzip'") +} + func TestIgnoreUnrelatedFiles(t *testing.T) { info := exampleInfo() info.Contents = files.Contents{ @@ -1242,6 +1266,7 @@ }, } + Default.SetPackagerDefaults(info) require.NoError(t, nfpm.PrepareForPackager(withChangelogIfRequested(info), packagerName)) dataTarball, _, _, tarballName, err := createDataTarball(info) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nfpm-2.45.0/deb/testdata/bad_provides.golden new/nfpm-2.45.1/deb/testdata/bad_provides.golden --- old/nfpm-2.45.0/deb/testdata/bad_provides.golden 2026-02-03 13:30:36.000000000 +0100 +++ new/nfpm-2.45.1/deb/testdata/bad_provides.golden 2026-03-11 17:38:01.000000000 +0100 @@ -3,7 +3,6 @@ Section: default Priority: extra Architecture: amd64 -License: MIT Maintainer: Carlos A Becker <[email protected]> Installed-Size: 0 Replaces: svn diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nfpm-2.45.0/deb/testdata/control.golden new/nfpm-2.45.1/deb/testdata/control.golden --- old/nfpm-2.45.0/deb/testdata/control.golden 2026-02-03 13:30:36.000000000 +0100 +++ new/nfpm-2.45.1/deb/testdata/control.golden 2026-03-11 17:38:01.000000000 +0100 @@ -3,7 +3,6 @@ Section: default Priority: extra Architecture: amd64 -License: MIT Maintainer: Carlos A Becker <[email protected]> Installed-Size: 10 Replaces: svn diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nfpm-2.45.0/files/files_test.go new/nfpm-2.45.1/files/files_test.go --- old/nfpm-2.45.0/files/files_test.go 2026-02-03 13:30:36.000000000 +0100 +++ new/nfpm-2.45.1/files/files_test.go 2026-03-11 17:38:01.000000000 +0100 @@ -283,9 +283,7 @@ t.Cleanup(func() { close(errs) }) var wg sync.WaitGroup for range 10 { - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { _, err := files.PrepareForPackager( config.Contents, 0, @@ -294,7 +292,7 @@ mtime, ) errs <- err - }() + }) } wg.Wait() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nfpm-2.45.0/go.mod new/nfpm-2.45.1/go.mod --- old/nfpm-2.45.0/go.mod 2026-02-03 13:30:36.000000000 +0100 +++ new/nfpm-2.45.1/go.mod 2026-03-11 17:38:01.000000000 +0100 @@ -6,7 +6,7 @@ dario.cat/mergo v1.0.2 github.com/AlekSi/pointer v1.2.0 github.com/Masterminds/semver/v3 v3.4.0 - github.com/ProtonMail/go-crypto v1.3.0 + github.com/ProtonMail/go-crypto v1.4.0 github.com/ProtonMail/gopenpgp/v2 v2.7.1 github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb github.com/caarlos0/go-version v0.2.2 @@ -14,7 +14,7 @@ github.com/goreleaser/chglog v0.7.4 github.com/goreleaser/fileglob v1.4.0 github.com/invopop/jsonschema v0.13.0 - github.com/klauspost/compress v1.18.3 + github.com/klauspost/compress v1.18.4 github.com/klauspost/pgzip v1.2.6 github.com/muesli/mango-cobra v1.3.0 github.com/muesli/roff v0.1.0 @@ -34,14 +34,14 @@ github.com/bahlo/generic-list-go v0.2.0 // indirect github.com/buger/jsonparser v1.1.1 // indirect github.com/cavaliergopher/cpio v1.0.1 // indirect - github.com/cloudflare/circl v1.6.1 // indirect + github.com/cloudflare/circl v1.6.3 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.6 // indirect github.com/cyphar/filepath-securejoin v0.4.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/emirpasic/gods v1.18.1 // indirect github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect github.com/go-git/go-billy/v5 v5.7.0 // indirect - github.com/go-git/go-git/v5 v5.16.4 // indirect + github.com/go-git/go-git/v5 v5.16.5 // indirect github.com/gobwas/glob v0.2.3 // indirect github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect github.com/google/uuid v1.6.0 // indirect diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nfpm-2.45.0/go.sum new/nfpm-2.45.1/go.sum --- old/nfpm-2.45.0/go.sum 2026-02-03 13:30:36.000000000 +0100 +++ new/nfpm-2.45.1/go.sum 2026-03-11 17:38:01.000000000 +0100 @@ -14,8 +14,8 @@ github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= github.com/ProtonMail/go-crypto v0.0.0-20230321155629-9a39f2531310/go.mod h1:8TI4H3IbrackdNgv+92dI+rhpCaLqM0IfpgCgenFvRE= -github.com/ProtonMail/go-crypto v1.3.0 h1:ILq8+Sf5If5DCpHQp4PbZdS1J7HDFRXz/+xKBiRGFrw= -github.com/ProtonMail/go-crypto v1.3.0/go.mod h1:9whxjD8Rbs29b4XWbB8irEcE8KHMqaR2e7GWU1R+/PE= +github.com/ProtonMail/go-crypto v1.4.0 h1:Zq/pbM3F5DFgJiMouxEdSVY44MVoQNEKp5d5QxIQceQ= +github.com/ProtonMail/go-crypto v1.4.0/go.mod h1:e1OaTyu5SYVrO9gKOEhTc+5UcXtTUa+P3uLudwcgPqo= github.com/ProtonMail/go-mime v0.0.0-20230322103455-7d82a3887f2f h1:tCbYj7/299ekTTXpdwKYF8eBlsYsDVoggDAuAjoK66k= github.com/ProtonMail/go-mime v0.0.0-20230322103455-7d82a3887f2f/go.mod h1:gcr0kNtGBqin9zDW9GOHcVntrwnjrK+qdJ06mWYBybw= github.com/ProtonMail/gopenpgp/v2 v2.7.1 h1:Awsg7MPc2gD3I7IFac2qE3Gdls0lZW8SzrFZ3k1oz0s= @@ -38,8 +38,8 @@ github.com/cavaliergopher/cpio v1.0.1 h1:KQFSeKmZhv0cr+kawA3a0xTQCU4QxXF1vhU7P7av2KM= github.com/cavaliergopher/cpio v1.0.1/go.mod h1:pBdaqQjnvXxdS/6CvNDwIANIFSP0xRKI16PX4xejRQc= github.com/cloudflare/circl v1.1.0/go.mod h1:prBCrKB9DV4poKZY1l9zBXg2QJY7mvgRvtMxxK7fi4I= -github.com/cloudflare/circl v1.6.1 h1:zqIqSPIndyBh1bjLVVDHMPpVKqp8Su/V+6MeDzzQBQ0= -github.com/cloudflare/circl v1.6.1/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs= +github.com/cloudflare/circl v1.6.3 h1:9GPOhQGF9MCYUeXyMYlqTR6a5gTrgR/fBLXvUgtVcg8= +github.com/cloudflare/circl v1.6.3/go.mod h1:2eXP6Qfat4O/Yhh8BznvKnJ+uzEoTQ6jVKJRn81BiS4= github.com/cpuguy83/go-md2man/v2 v2.0.6 h1:XJtiaUW6dEEqVuZiMTn1ldk455QWwEIsMIJlo5vtkx0= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/cyphar/filepath-securejoin v0.4.1 h1:JyxxyPEaktOD+GAnqIqTf9A8tHyAG22rowi7HkoSU1s= @@ -61,8 +61,8 @@ github.com/go-git/go-billy/v5 v5.7.0/go.mod h1:/1IUejTKH8xipsAcdfcSAlUlo2J7lkYV8GTKxAT/L3E= github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4= github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII= -github.com/go-git/go-git/v5 v5.16.4 h1:7ajIEZHZJULcyJebDLo99bGgS0jRrOxzZG4uCk2Yb2Y= -github.com/go-git/go-git/v5 v5.16.4/go.mod h1:4Ge4alE/5gPs30F2H1esi2gPd69R0C39lolkucHBOp8= +github.com/go-git/go-git/v5 v5.16.5 h1:mdkuqblwr57kVfXri5TTH+nMFLNUxIj9Z7F5ykFbw5s= +github.com/go-git/go-git/v5 v5.16.5/go.mod h1:QOMLpNf1qxuSY4StA/ArOdfFR2TrKEjJiye2kel2m+M= github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ= @@ -92,8 +92,8 @@ github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= -github.com/klauspost/compress v1.18.3 h1:9PJRvfbmTabkOX8moIpXPbMMbYN60bWImDDU7L+/6zw= -github.com/klauspost/compress v1.18.3/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4= +github.com/klauspost/compress v1.18.4 h1:RPhnKRAQ4Fh8zU2FY/6ZFDwTVTxgJ/EMydqSTzE9a2c= +github.com/klauspost/compress v1.18.4/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4= github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU= github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nfpm-2.45.0/internal/sign/pgp_test.go new/nfpm-2.45.1/internal/sign/pgp_test.go --- old/nfpm-2.45.0/internal/sign/pgp_test.go 2026-02-03 13:30:36.000000000 +0100 +++ new/nfpm-2.45.1/internal/sign/pgp_test.go 2026-03-11 17:38:01.000000000 +0100 @@ -36,7 +36,6 @@ func TestPGPSignerAndVerify(t *testing.T) { data := []byte("testdata") for _, testCase := range testCases { - testCase := testCase t.Run(testCase.name, func(t *testing.T) { armoredPublicKey := fmt.Sprintf("%s.asc", testCase.pubKeyFile) gpgPublicKey := fmt.Sprintf("%s.gpg", testCase.pubKeyFile) @@ -67,7 +66,6 @@ func TestArmoredDetachSignAndVerify(t *testing.T) { data := []byte("testdata") for _, testCase := range testCases { - testCase := testCase t.Run(testCase.name, func(t *testing.T) { armoredPublicKey := fmt.Sprintf("%s.asc", testCase.pubKeyFile) gpgPublicKey := fmt.Sprintf("%s.gpg", testCase.pubKeyFile) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nfpm-2.45.0/internal/sign/rsa_test.go new/nfpm-2.45.1/internal/sign/rsa_test.go --- old/nfpm-2.45.0/internal/sign/rsa_test.go 2026-02-03 13:30:36.000000000 +0100 +++ new/nfpm-2.45.1/internal/sign/rsa_test.go 2026-03-11 17:38:01.000000000 +0100 @@ -23,7 +23,6 @@ } for _, testCase := range testCases { - testCase := testCase t.Run(testCase.name, func(t *testing.T) { sig, err := rsaSign(bytes.NewReader(testData), testCase.privKey, testCase.passphrase) require.NoError(t, err) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nfpm-2.45.0/ipk/ipk_test.go new/nfpm-2.45.1/ipk/ipk_test.go --- old/nfpm-2.45.0/ipk/ipk_test.go 2026-02-03 13:30:36.000000000 +0100 +++ new/nfpm-2.45.1/ipk/ipk_test.go 2026-03-11 17:38:01.000000000 +0100 @@ -98,7 +98,6 @@ func TestIPK(t *testing.T) { for _, arch := range []string{"386", "amd64"} { - arch := arch t.Run(arch, func(t *testing.T) { info := exampleInfo() info.Arch = arch @@ -119,7 +118,7 @@ } func extractIPKArchitecture(deb *bytes.Buffer) string { - for _, s := range strings.Split(deb.String(), "\n") { + for s := range strings.SplitSeq(deb.String(), "\n") { if strings.Contains(s, "Architecture: ") { return strings.TrimPrefix(s, "Architecture: ") } @@ -155,7 +154,7 @@ } func extractIPKVersion(deb *bytes.Buffer) string { - for _, s := range strings.Split(deb.String(), "\n") { + for s := range strings.SplitSeq(deb.String(), "\n") { if strings.Contains(s, "Version: ") { return strings.TrimPrefix(s, "Version: ") } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nfpm-2.45.0/nfpm_test.go new/nfpm-2.45.1/nfpm_test.go --- old/nfpm-2.45.0/nfpm_test.go 2026-02-03 13:30:36.000000000 +0100 +++ new/nfpm-2.45.1/nfpm_test.go 2026-03-11 17:38:01.000000000 +0100 @@ -576,7 +576,6 @@ require.Equal(t, "amd64", config.Arch) for _, format := range []string{"apk", "deb", "rpm"} { - format := format t.Run(format, func(t *testing.T) { pkg, err := config.Get(format) require.NoError(t, err) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nfpm-2.45.0/rpm/rpm.go new/nfpm-2.45.1/rpm/rpm.go --- old/nfpm-2.45.0/rpm/rpm.go 2026-02-03 13:30:36.000000000 +0100 +++ new/nfpm-2.45.1/rpm/rpm.go 2026-03-11 17:38:01.000000000 +0100 @@ -4,6 +4,7 @@ import ( "bytes" + "cmp" "fmt" "io" "os" @@ -52,7 +53,7 @@ // nolint: gochecknoglobals var DefaultRPM = &RPM{formatRPM} -// DefaultRPM RPM packager. +// DefaultSRPM SRPM packager. // nolint: gochecknoglobals var DefaultSRPM = &RPM{formatSRPM} @@ -95,8 +96,8 @@ info.Arch = arch } - info.Release = defaultTo(info.Release, "1") - + info.Release = cmp.Or(info.Release, "1") + info.RPM.Compression = cmp.Or(info.RPM.Compression, "gzip") return info } @@ -231,9 +232,6 @@ suggests, conflicts rpmpack.Relations ) - if info.RPM.Compression == "" { - info.RPM.Compression = "gzip:-1" - } if info.Epoch == "" { epoch = uint64(rpmpack.NoEpoch) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nfpm-2.45.0/rpm/rpm_test.go new/nfpm-2.45.1/rpm/rpm_test.go --- old/nfpm-2.45.0/rpm/rpm_test.go 2026-02-03 13:30:36.000000000 +0100 +++ new/nfpm-2.45.1/rpm/rpm_test.go 2026-03-11 17:38:01.000000000 +0100 @@ -369,6 +369,48 @@ } } +func TestRPMDefaultCompression(t *testing.T) { + // When compression is unset, it should default to gzip and produce the + // same output as explicitly setting compression to "gzip". + buildRPM := func(compression string) []byte { + f, err := os.CreateTemp(t.TempDir(), "test.rpm") + require.NoError(t, err) + defer f.Close() + + info := exampleInfo() + info.RPM.Compression = compression + require.NoError(t, DefaultRPM.Package(info, f)) + + data, err := os.ReadFile(f.Name()) + require.NoError(t, err) + return data + } + + defaultRPM := buildRPM("") + explicitGzipRPM := buildRPM("gzip") + require.Len(t, explicitGzipRPM, len(defaultRPM), "default compression should produce identical output to explicit 'gzip'") + + // Also verify the default uses gzip as the compressor type in the RPM header. + f, err := os.CreateTemp(t.TempDir(), "test.rpm") + require.NoError(t, err) + defer f.Close() + + info := exampleInfo() + // leave info.RPM.Compression empty to test the default + require.NoError(t, DefaultRPM.Package(info, f)) + + file, err := os.OpenFile(f.Name(), os.O_RDONLY, 0o600) //nolint:gosec + require.NoError(t, err) + defer file.Close() + + rpm, err := rpmutils.ReadRpm(file) + require.NoError(t, err) + + rpmCompressor, err := rpm.Header.GetString(rpmutils.PAYLOADCOMPRESSOR) + require.NoError(t, err) + require.Equal(t, "gzip", rpmCompressor) +} + func TestRPMSummary(t *testing.T) { f, err := os.CreateTemp(t.TempDir(), "test.rpm") require.NoError(t, err) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nfpm-2.45.0/www/content/docs/install.md new/nfpm-2.45.1/www/content/docs/install.md --- old/nfpm-2.45.0/www/content/docs/install.md 2026-02-03 13:30:36.000000000 +0100 +++ new/nfpm-2.45.1/www/content/docs/install.md 2026-03-11 17:38:01.000000000 +0100 @@ -160,9 +160,9 @@ ### Pull the images ```bash -docker buill goreleaser/nfpm +docker pull goreleaser/nfpm # or -docker build ghcr.io/goreleaser/nfpm +docker pull ghcr.io/goreleaser/nfpm ``` ### Verify diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nfpm-2.45.0/www/static/latest new/nfpm-2.45.1/www/static/latest --- old/nfpm-2.45.0/www/static/latest 2026-02-03 13:30:36.000000000 +0100 +++ new/nfpm-2.45.1/www/static/latest 2026-03-11 17:38:01.000000000 +0100 @@ -1 +1 @@ -v2.44.2 +v2.45.0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nfpm-2.45.0/www/static/schema.json new/nfpm-2.45.1/www/static/schema.json --- old/nfpm-2.45.0/www/static/schema.json 2026-02-03 13:30:36.000000000 +0100 +++ new/nfpm-2.45.1/www/static/schema.json 2026-03-11 17:38:01.000000000 +0100 @@ -408,6 +408,13 @@ "type": "string", "title": "architecture in deb nomenclature" }, + "arch_variant": { + "type": "string", + "title": "target architecture variant in deb nomenclature", + "examples": [ + "amd64v3" + ] + }, "scripts": { "$ref": "#/$defs/DebScripts", "title": "scripts" ++++++ nfpm.obsinfo ++++++ --- /var/tmp/diff_new_pack.0psCot/_old 2026-03-12 22:27:23.170916571 +0100 +++ /var/tmp/diff_new_pack.0psCot/_new 2026-03-12 22:27:23.178916906 +0100 @@ -1,5 +1,5 @@ name: nfpm -version: 2.45.0 -mtime: 1770121836 -commit: be6fd83eed6f241359ae3e7d340a13f197ae6463 +version: 2.45.1 +mtime: 1773247081 +commit: 532c31d97dab4308fbfcaaaf6452c548325e56df ++++++ vendor.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/github.com/ProtonMail/go-crypto/openpgp/armor/armor.go new/vendor/github.com/ProtonMail/go-crypto/openpgp/armor/armor.go --- old/vendor/github.com/ProtonMail/go-crypto/openpgp/armor/armor.go 2026-02-03 13:30:36.000000000 +0100 +++ new/vendor/github.com/ProtonMail/go-crypto/openpgp/armor/armor.go 2026-03-11 17:38:01.000000000 +0100 @@ -69,6 +69,8 @@ if isPrefix { return 0, ArmorCorrupt } + // Trim the line to remove any whitespace + line = bytes.TrimSpace(line) if bytes.HasPrefix(line, armorEnd) { l.eof = true diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/github.com/ProtonMail/go-crypto/openpgp/clearsign/clearsign.go new/vendor/github.com/ProtonMail/go-crypto/openpgp/clearsign/clearsign.go --- old/vendor/github.com/ProtonMail/go-crypto/openpgp/clearsign/clearsign.go 2026-02-03 13:30:36.000000000 +0100 +++ new/vendor/github.com/ProtonMail/go-crypto/openpgp/clearsign/clearsign.go 2026-03-11 17:38:01.000000000 +0100 @@ -17,6 +17,7 @@ "hash" "io" "net/textproto" + "slices" "strconv" "strings" @@ -49,6 +50,8 @@ // end is a marker which denotes the end of the armored signature. var end = []byte("\n-----END PGP SIGNATURE-----") +var allowedHashHeaderValues = []string{"MD5", "SHA1", "RIPEMD160", "SHA224", "SHA256", "SHA384", "SHA512", "SHA3-256", "SHA3-512"} + var crlf = []byte("\r\n") var lf = byte('\n') @@ -131,7 +134,10 @@ key = strings.TrimSpace(key) if key == hashHeader { for _, val := range strings.Split(val, ",") { - val = strings.TrimSpace(val) + val = strings.ToUpper(strings.TrimSpace(val)) + if !slices.Contains(allowedHashHeaderValues, val) { + return nil, data + } b.Headers.Add(key, val) } } else { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/curve25519.go new/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/curve25519.go --- old/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/curve25519.go 2026-02-03 13:30:36.000000000 +0100 +++ new/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/curve25519.go 2026-03-11 17:38:01.000000000 +0100 @@ -125,7 +125,10 @@ // "VB = convert point V to the octet string" // sharedPoint corresponds to `VB`. var sharedPoint x25519lib.Key - x25519lib.Shared(&sharedPoint, &ephemeralPrivate, &pubKey) + ok := x25519lib.Shared(&sharedPoint, &ephemeralPrivate, &pubKey) + if !ok { + return nil, nil, errors.KeyInvalidError("ecc: the public key is a low order point") + } return ephemeralPublic[:], sharedPoint[:], nil } @@ -146,7 +149,10 @@ // RFC6637 ยง8: "Note that the recipient obtains the shared secret by calculating // S = rV = rvG, where (r,R) is the recipient's key pair." // sharedPoint corresponds to `S`. - x25519lib.Shared(&sharedPoint, &decodedPrivate, &ephemeralPublic) + ok := x25519lib.Shared(&sharedPoint, &decodedPrivate, &ephemeralPublic) + if !ok { + return nil, errors.KeyInvalidError("ecc: the public key is a low order point") + } return sharedPoint[:], nil } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/config.go new/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/config.go --- old/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/config.go 2026-02-03 13:30:36.000000000 +0100 +++ new/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/config.go 2026-03-11 17:38:01.000000000 +0100 @@ -178,6 +178,18 @@ // When set to true, a key without flags is treated as if all flags are enabled. // This behavior is consistent with GPG. InsecureAllowAllKeyFlagsWhenMissing bool + // InsecureGenerateNonCriticalKeyFlags causes the "Key Flags" signature subpacket + // to be non-critical in newly generated signatures. + // This may be needed for keys to be accepted by older clients who do not recognize + // the subpacket. + // For example, rpm 4.14.3-150400.59.3.1 in OpenSUSE Leap 15.4 does not recognize it. + InsecureGenerateNonCriticalKeyFlags bool + // InsecureGenerateNonCriticalSignatureCreationTime causes the "Signature Creation Time" signature subpacket + // to be non-critical in newly generated signatures. + // This may be needed for keys to be accepted by older clients who do not recognize + // the subpacket. + // For example, yum 3.4.3-168 in CentOS 7 and yum 3.4.3-158 in Amazon Linux 2 do not recognize it. + InsecureGenerateNonCriticalSignatureCreationTime bool // MaxDecompressedMessageSize specifies the maximum number of bytes that can be // read from a compressed packet. This serves as an upper limit to prevent @@ -420,6 +432,20 @@ return c.InsecureAllowAllKeyFlagsWhenMissing } +func (c *Config) GenerateNonCriticalKeyFlags() bool { + if c == nil { + return false + } + return c.InsecureGenerateNonCriticalKeyFlags +} + +func (c *Config) GenerateNonCriticalSignatureCreationTime() bool { + if c == nil { + return false + } + return c.InsecureGenerateNonCriticalSignatureCreationTime +} + func (c *Config) DecompressedMessageSizeLimit() *int64 { if c == nil { return nil diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/signature.go new/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/signature.go --- old/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/signature.go 2026-02-03 13:30:36.000000000 +0100 +++ new/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/signature.go 2026-03-11 17:38:01.000000000 +0100 @@ -933,7 +933,7 @@ } sig.Notations = append(sig.Notations, ¬ation) } - sig.outSubpackets, err = sig.buildSubpackets(priv.PublicKey) + sig.outSubpackets, err = sig.buildSubpackets(priv.PublicKey, config) if err != nil { return err } @@ -1254,11 +1254,11 @@ contents []byte } -func (sig *Signature) buildSubpackets(issuer PublicKey) (subpackets []outputSubpacket, err error) { +func (sig *Signature) buildSubpackets(issuer PublicKey, config *Config) (subpackets []outputSubpacket, err error) { creationTime := make([]byte, 4) binary.BigEndian.PutUint32(creationTime, uint32(sig.CreationTime.Unix())) // Signature Creation Time - subpackets = append(subpackets, outputSubpacket{true, creationTimeSubpacket, true, creationTime}) + subpackets = append(subpackets, outputSubpacket{true, creationTimeSubpacket, !config.GenerateNonCriticalSignatureCreationTime(), creationTime}) // Signature Expiration Time if sig.SigLifetimeSecs != nil && *sig.SigLifetimeSecs != 0 { sigLifetime := make([]byte, 4) @@ -1357,7 +1357,7 @@ if sig.FlagGroupKey { flags |= KeyFlagGroupKey } - subpackets = append(subpackets, outputSubpacket{true, keyFlagsSubpacket, true, []byte{flags}}) + subpackets = append(subpackets, outputSubpacket{true, keyFlagsSubpacket, !config.GenerateNonCriticalKeyFlags(), []byte{flags}}) } // Signer's User ID if sig.SignerUserId != nil { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/github.com/cloudflare/circl/internal/sha3/xor_unaligned.go new/vendor/github.com/cloudflare/circl/internal/sha3/xor_unaligned.go --- old/vendor/github.com/cloudflare/circl/internal/sha3/xor_unaligned.go 2026-02-03 13:30:36.000000000 +0100 +++ new/vendor/github.com/cloudflare/circl/internal/sha3/xor_unaligned.go 2026-03-11 17:38:01.000000000 +0100 @@ -14,14 +14,14 @@ type storageBuf [maxRate / 8]uint64 func (b *storageBuf) asBytes() *[maxRate]byte { - return (*[maxRate]byte)(unsafe.Pointer(b)) + return (*[maxRate]byte)(unsafe.Pointer(b)) //nolint:gosec } // xorInuses unaligned reads and writes to update d.a to contain d.a // XOR buf. func xorIn(d *State, buf []byte) { n := len(buf) - bw := (*[maxRate / 8]uint64)(unsafe.Pointer(&buf[0]))[: n/8 : n/8] + bw := (*[maxRate / 8]uint64)(unsafe.Pointer(&buf[0]))[: n/8 : n/8] //nolint:gosec if n >= 72 { d.a[0] ^= bw[0] d.a[1] ^= bw[1] @@ -56,6 +56,6 @@ } func copyOut(d *State, buf []byte) { - ab := (*[maxRate]uint8)(unsafe.Pointer(&d.a[0])) + ab := (*[maxRate]uint8)(unsafe.Pointer(&d.a[0])) //nolint:gosec copy(buf, ab[:]) } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/github.com/cloudflare/circl/sign/sign.go new/vendor/github.com/cloudflare/circl/sign/sign.go --- old/vendor/github.com/cloudflare/circl/sign/sign.go 2026-02-03 13:30:36.000000000 +0100 +++ new/vendor/github.com/cloudflare/circl/sign/sign.go 2026-03-11 17:38:01.000000000 +0100 @@ -38,6 +38,12 @@ encoding.BinaryMarshaler } +// A private key that retains the seed with which it was generated. +type Seeded interface { + // returns the seed if retained, otherwise nil + Seed() []byte +} + // A Scheme represents a specific instance of a signature scheme. type Scheme interface { // Name of the scheme. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/github.com/go-git/go-git/v5/plumbing/format/idxfile/decoder.go new/vendor/github.com/go-git/go-git/v5/plumbing/format/idxfile/decoder.go --- old/vendor/github.com/go-git/go-git/v5/plumbing/format/idxfile/decoder.go 2026-02-03 13:30:36.000000000 +0100 +++ new/vendor/github.com/go-git/go-git/v5/plumbing/format/idxfile/decoder.go 2026-03-11 17:38:01.000000000 +0100 @@ -1,9 +1,11 @@ package idxfile import ( - "bufio" "bytes" + "crypto" + "encoding/hex" "errors" + "fmt" "io" "github.com/go-git/go-git/v5/plumbing/hash" @@ -25,12 +27,15 @@ // Decoder reads and decodes idx files from an input stream. type Decoder struct { - *bufio.Reader + io.Reader + h hash.Hash } // NewDecoder builds a new idx stream decoder, that reads from r. func NewDecoder(r io.Reader) *Decoder { - return &Decoder{bufio.NewReader(r)} + h := hash.New(crypto.SHA1) + tr := io.TeeReader(r, h) + return &Decoder{tr, h} } // Decode reads from the stream and decode the content into the MemoryIndex struct. @@ -45,7 +50,7 @@ readObjectNames, readCRC32, readOffsets, - readChecksums, + readPackChecksum, } for _, f := range flow { @@ -54,11 +59,21 @@ } } + actual := d.h.Sum(nil) + if err := readIdxChecksum(idx, d); err != nil { + return err + } + + if !bytes.Equal(actual, idx.IdxChecksum[:]) { + return fmt.Errorf("%w: checksum mismatch: %q instead of %q", + ErrMalformedIdxFile, hex.EncodeToString(idx.IdxChecksum[:]), hex.EncodeToString(actual)) + } + return nil } func validateHeader(r io.Reader) error { - var h = make([]byte, 4) + h := make([]byte, 4) if _, err := io.ReadFull(r, h); err != nil { return err } @@ -165,11 +180,15 @@ return nil } -func readChecksums(idx *MemoryIndex, r io.Reader) error { +func readPackChecksum(idx *MemoryIndex, r io.Reader) error { if _, err := io.ReadFull(r, idx.PackfileChecksum[:]); err != nil { return err } + return nil +} + +func readIdxChecksum(idx *MemoryIndex, r io.Reader) error { if _, err := io.ReadFull(r, idx.IdxChecksum[:]); err != nil { return err } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/github.com/go-git/go-git/v5/plumbing/format/objfile/reader.go new/vendor/github.com/go-git/go-git/v5/plumbing/format/objfile/reader.go --- old/vendor/github.com/go-git/go-git/v5/plumbing/format/objfile/reader.go 2026-02-03 13:30:36.000000000 +0100 +++ new/vendor/github.com/go-git/go-git/v5/plumbing/format/objfile/reader.go 2026-03-11 17:38:01.000000000 +0100 @@ -30,7 +30,7 @@ func NewReader(r io.Reader) (*Reader, error) { zlib, err := sync.GetZlibReader(r) if err != nil { - return nil, packfile.ErrZLib.AddDetails(err.Error()) + return nil, packfile.ErrZLib.AddDetails("%s", err.Error()) } return &Reader{ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/github.com/go-git/go-git/v5/plumbing/format/packfile/parser.go new/vendor/github.com/go-git/go-git/v5/plumbing/format/packfile/parser.go --- old/vendor/github.com/go-git/go-git/v5/plumbing/format/packfile/parser.go 2026-02-03 13:30:36.000000000 +0100 +++ new/vendor/github.com/go-git/go-git/v5/plumbing/format/packfile/parser.go 2026-03-11 17:38:01.000000000 +0100 @@ -47,7 +47,6 @@ oi []*objectInfo oiByHash map[plumbing.Hash]*objectInfo oiByOffset map[int64]*objectInfo - checksum plumbing.Hash cache *cache.BufferLRU // delta content by offset, only used if source is not seekable @@ -133,28 +132,27 @@ // Parse start decoding phase of the packfile. func (p *Parser) Parse() (plumbing.Hash, error) { if err := p.init(); err != nil { - return plumbing.ZeroHash, err + return plumbing.ZeroHash, wrapEOF(err) } if err := p.indexObjects(); err != nil { - return plumbing.ZeroHash, err + return plumbing.ZeroHash, wrapEOF(err) } - var err error - p.checksum, err = p.scanner.Checksum() + checksum, err := p.scanner.Checksum() if err != nil && err != io.EOF { - return plumbing.ZeroHash, err + return plumbing.ZeroHash, wrapEOF(err) } if err := p.resolveDeltas(); err != nil { - return plumbing.ZeroHash, err + return plumbing.ZeroHash, wrapEOF(err) } - if err := p.onFooter(p.checksum); err != nil { - return plumbing.ZeroHash, err + if err := p.onFooter(checksum); err != nil { + return plumbing.ZeroHash, wrapEOF(err) } - return p.checksum, nil + return checksum, nil } func (p *Parser) init() error { @@ -218,7 +216,7 @@ if !ok { // can't find referenced object in this pack file // this must be a "thin" pack. - parent = &objectInfo{ //Placeholder parent + parent = &objectInfo{ // Placeholder parent SHA1: oh.Reference, ExternalRef: true, // mark as an external reference that must be resolved Type: plumbing.AnyObject, @@ -531,6 +529,13 @@ return nil } +func wrapEOF(err error) error { + if err == io.ErrUnexpectedEOF || err == io.EOF { + return fmt.Errorf("%w: %w", ErrMalformedPackFile, err) + } + return err +} + // applyPatchBase applies the patch to target. // // Note that ota will be updated based on the description in resolveObject. @@ -558,15 +563,6 @@ return nil } -func getSHA1(t plumbing.ObjectType, data []byte) (plumbing.Hash, error) { - hasher := plumbing.NewHasher(t, int64(len(data))) - if _, err := hasher.Write(data); err != nil { - return plumbing.ZeroHash, err - } - - return hasher.Sum(), nil -} - type objectInfo struct { Offset int64 Length int64 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/github.com/go-git/go-git/v5/plumbing/format/packfile/scanner.go new/vendor/github.com/go-git/go-git/v5/plumbing/format/packfile/scanner.go --- old/vendor/github.com/go-git/go-git/v5/plumbing/format/packfile/scanner.go 2026-02-03 13:30:36.000000000 +0100 +++ new/vendor/github.com/go-git/go-git/v5/plumbing/format/packfile/scanner.go 2026-03-11 17:38:01.000000000 +0100 @@ -3,12 +3,15 @@ import ( "bufio" "bytes" + "crypto" + "errors" "fmt" - "hash" + gohash "hash" "hash/crc32" "io" "github.com/go-git/go-git/v5/plumbing" + "github.com/go-git/go-git/v5/plumbing/hash" "github.com/go-git/go-git/v5/utils/binary" "github.com/go-git/go-git/v5/utils/ioutil" "github.com/go-git/go-git/v5/utils/sync" @@ -24,6 +27,8 @@ ErrUnsupportedVersion = NewError("unsupported packfile version") // ErrSeekNotSupported returned if seek is not support ErrSeekNotSupported = NewError("not seek support") + // ErrMalformedPackFile is returned by the parser when the pack file is corrupted. + ErrMalformedPackFile = errors.New("malformed PACK file") ) // ObjectHeader contains the information related to the object, this information @@ -37,8 +42,9 @@ } type Scanner struct { - r *scannerReader - crc hash.Hash32 + r *scannerReader + crc gohash.Hash32 + packHasher hash.Hash // pendingObject is used to detect if an object has been read, or still // is waiting to be read @@ -56,10 +62,12 @@ _, ok := r.(io.ReadSeeker) crc := crc32.NewIEEE() + hasher := hash.New(crypto.SHA1) return &Scanner{ - r: newScannerReader(r, crc), + r: newScannerReader(r, io.MultiWriter(crc, hasher)), crc: crc, IsSeekable: ok, + packHasher: hasher, } } @@ -68,6 +76,7 @@ s.r.Reset(r) s.crc.Reset() + s.packHasher.Reset() s.IsSeekable = ok s.pendingObject = nil s.version = 0 @@ -114,7 +123,7 @@ // readSignature reads a returns the signature field in the packfile. func (s *Scanner) readSignature() ([]byte, error) { - var sig = make([]byte, 4) + sig := make([]byte, 4) if _, err := io.ReadFull(s.r, sig); err != nil { return []byte{}, err } @@ -322,7 +331,6 @@ func (s *Scanner) ReadObject() (io.ReadCloser, error) { s.pendingObject = nil zr, err := sync.GetZlibReader(s.r) - if err != nil { return nil, fmt.Errorf("zlib reset error: %s", err) } @@ -374,7 +382,18 @@ return plumbing.ZeroHash, err } - return binary.ReadHash(s.r) + s.r.Flush() + actual := plumbing.Hash(s.packHasher.Sum(nil)) + packChecksum, err := binary.ReadHash(s.r) + if err != nil { + return plumbing.ZeroHash, err + } + + if actual != packChecksum { + return plumbing.ZeroHash, fmt.Errorf("%w: checksum mismatch: %q instead of %q", ErrMalformedPackFile, packChecksum, actual) + } + + return packChecksum, nil } // Close reads the reader until io.EOF @@ -401,17 +420,17 @@ // to the crc32 hash writer. type scannerReader struct { reader io.Reader - crc io.Writer + writer io.Writer rbuf *bufio.Reader wbuf *bufio.Writer offset int64 } -func newScannerReader(r io.Reader, h io.Writer) *scannerReader { +func newScannerReader(r io.Reader, w io.Writer) *scannerReader { sr := &scannerReader{ - rbuf: bufio.NewReader(nil), - wbuf: bufio.NewWriterSize(nil, 64), - crc: h, + rbuf: bufio.NewReader(nil), + wbuf: bufio.NewWriterSize(nil, 64), + writer: w, } sr.Reset(r) @@ -421,7 +440,7 @@ func (r *scannerReader) Reset(reader io.Reader) { r.reader = reader r.rbuf.Reset(r.reader) - r.wbuf.Reset(r.crc) + r.wbuf.Reset(r.writer) r.offset = 0 if seeker, ok := r.reader.(io.ReadSeeker); ok { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/advrefs_decode.go new/vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/advrefs_decode.go --- old/vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/advrefs_decode.go 2026-02-03 13:30:36.000000000 +0100 +++ new/vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/advrefs_decode.go 2026-03-11 17:38:01.000000000 +0100 @@ -262,9 +262,8 @@ p.line = bytes.TrimPrefix(p.line, shallow) if len(p.line) != hashSize { - p.error(fmt.Sprintf( - "malformed shallow hash: wrong length, expected 40 bytes, read %d bytes", - len(p.line))) + p.error("malformed shallow hash: wrong length, expected 40 bytes, read %d bytes", + len(p.line)) return nil } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/updreq_encode.go new/vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/updreq_encode.go --- old/vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/updreq_encode.go 2026-02-03 13:30:36.000000000 +0100 +++ new/vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/updreq_encode.go 2026-03-11 17:38:01.000000000 +0100 @@ -62,7 +62,7 @@ } for _, cmd := range cmds[1:] { - if err := e.Encodef(formatCommand(cmd)); err != nil { + if err := e.Encodef("%s", formatCommand(cmd)); err != nil { return err } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/github.com/go-git/go-git/v5/storage/filesystem/object.go new/vendor/github.com/go-git/go-git/v5/storage/filesystem/object.go --- old/vendor/github.com/go-git/go-git/v5/storage/filesystem/object.go 2026-02-03 13:30:36.000000000 +0100 +++ new/vendor/github.com/go-git/go-git/v5/storage/filesystem/object.go 2026-03-11 17:38:01.000000000 +0100 @@ -2,6 +2,8 @@ import ( "bytes" + "encoding/hex" + "fmt" "io" "os" "sync" @@ -87,6 +89,11 @@ return err } + if !bytes.Equal(idxf.PackfileChecksum[:], h[:]) { + return fmt.Errorf("%w: packfile mismatch: target is %q not %q", + idxfile.ErrMalformedIdxFile, hex.EncodeToString(idxf.PackfileChecksum[:]), h.String()) + } + s.index[h] = idxf return err } @@ -186,7 +193,8 @@ } func (s *ObjectStorage) encodedObjectSizeFromUnpacked(h plumbing.Hash) ( - size int64, err error) { + size int64, err error, +) { f, err := s.dir.Object(h) if err != nil { if os.IsNotExist(err) { @@ -274,7 +282,8 @@ } func (s *ObjectStorage) encodedObjectSizeFromPackfile(h plumbing.Hash) ( - size int64, err error) { + size int64, err error, +) { if err := s.requireIndex(); err != nil { return 0, err } @@ -310,7 +319,8 @@ // EncodedObjectSize returns the plaintext size of the given object, // without actually reading the full object data from storage. func (s *ObjectStorage) EncodedObjectSize(h plumbing.Hash) ( - size int64, err error) { + size int64, err error, +) { size, err = s.encodedObjectSizeFromUnpacked(h) if err != nil && err != plumbing.ErrObjectNotFound { return 0, err @@ -371,7 +381,8 @@ // DeltaObject returns the object with the given hash, by searching for // it in the packfile and the git object directories. func (s *ObjectStorage) DeltaObject(t plumbing.ObjectType, - h plumbing.Hash) (plumbing.EncodedObject, error) { + h plumbing.Hash, +) (plumbing.EncodedObject, error) { obj, err := s.getFromUnpacked(h) if err == plumbing.ErrObjectNotFound { obj, err = s.getFromPackfile(h, true) @@ -451,8 +462,8 @@ // Get returns the object with the given hash, by searching for it in // the packfile. func (s *ObjectStorage) getFromPackfile(h plumbing.Hash, canBeDelta bool) ( - plumbing.EncodedObject, error) { - + plumbing.EncodedObject, error, +) { if err := s.requireIndex(); err != nil { return nil, err } @@ -509,9 +520,7 @@ return nil, err } - var ( - base plumbing.Hash - ) + var base plumbing.Hash switch header.Type { case plumbing.REFDeltaObject: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/github.com/go-git/go-git/v5/worktree.go new/vendor/github.com/go-git/go-git/v5/worktree.go --- old/vendor/github.com/go-git/go-git/v5/worktree.go 2026-02-03 13:30:36.000000000 +0100 +++ new/vendor/github.com/go-git/go-git/v5/worktree.go 2026-03-11 17:38:01.000000000 +0100 @@ -310,13 +310,20 @@ return err } + var removedFiles []string if opts.Mode == MixedReset || opts.Mode == MergeReset || opts.Mode == HardReset { - if err := w.resetIndex(t, dirs, opts.Files); err != nil { + if removedFiles, err = w.resetIndex(t, dirs, opts.Files); err != nil { return err } } - if opts.Mode == MergeReset || opts.Mode == HardReset { + if opts.Mode == MergeReset && len(removedFiles) > 0 { + if err := w.resetWorktree(t, removedFiles); err != nil { + return err + } + } + + if opts.Mode == HardReset { if err := w.resetWorktree(t, opts.Files); err != nil { return err } @@ -365,23 +372,24 @@ return w.ResetSparsely(opts, nil) } -func (w *Worktree) resetIndex(t *object.Tree, dirs []string, files []string) error { +func (w *Worktree) resetIndex(t *object.Tree, dirs []string, files []string) ([]string, error) { idx, err := w.r.Storer.Index() if err != nil { - return err + return nil, err } b := newIndexBuilder(idx) changes, err := w.diffTreeWithStaging(t, true) if err != nil { - return err + return nil, err } + var removedFiles []string for _, ch := range changes { a, err := ch.Action() if err != nil { - return err + return nil, err } var name string @@ -392,7 +400,7 @@ name = ch.To.String() e, err = t.FindEntry(name) if err != nil { - return err + return nil, err } case merkletrie.Delete: name = ch.From.String() @@ -406,6 +414,7 @@ } b.Remove(name) + removedFiles = append(removedFiles, name) if e == nil { continue } @@ -424,7 +433,7 @@ idx.SkipUnless(dirs) } - return w.r.Storer.SetIndex(idx) + return removedFiles, w.r.Storer.SetIndex(idx) } func inFiles(files []string, v string) bool { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/github.com/klauspost/compress/README.md new/vendor/github.com/klauspost/compress/README.md --- old/vendor/github.com/klauspost/compress/README.md 2026-02-03 13:30:36.000000000 +0100 +++ new/vendor/github.com/klauspost/compress/README.md 2026-03-11 17:38:01.000000000 +0100 @@ -7,7 +7,7 @@ * Optimized [deflate](https://godoc.org/github.com/klauspost/compress/flate) packages which can be used as a dropin replacement for [gzip](https://godoc.org/github.com/klauspost/compress/gzip), [zip](https://godoc.org/github.com/klauspost/compress/zip) and [zlib](https://godoc.org/github.com/klauspost/compress/zlib). * [snappy](https://github.com/klauspost/compress/tree/master/snappy) is a drop-in replacement for `github.com/golang/snappy` offering better compression and concurrent streams. * [huff0](https://github.com/klauspost/compress/tree/master/huff0) and [FSE](https://github.com/klauspost/compress/tree/master/fse) implementations for raw entropy encoding. -* [gzhttp](https://github.com/klauspost/compress/tree/master/gzhttp) Provides client and server wrappers for handling gzipped requests efficiently. +* [gzhttp](https://github.com/klauspost/compress/tree/master/gzhttp) Provides client and server wrappers for handling gzipped/zstd HTTP requests efficiently. * [pgzip](https://github.com/klauspost/pgzip) is a separate package that provides a very fast parallel gzip implementation. [](https://pkg.go.dev/github.com/klauspost/compress?tab=subdirectories) @@ -26,8 +26,14 @@ Use the links above for more information on each. # changelog +* Jan 16th, 2026 [1.18.3](https://github.com/klauspost/compress/releases/tag/v1.18.3) + * Downstream CVE-2025-61728. See [golang/go#77102](https://github.com/golang/go/issues/77102). -* Oct 20, 2025 - [1.18.1](https://github.com/klauspost/compress/releases/tag/v1.18.1) +* Dec 1st, 2025 - [1.18.2](https://github.com/klauspost/compress/releases/tag/v1.18.2) + * flate: Fix invalid encoding on level 9 with single value input in https://github.com/klauspost/compress/pull/1115 + * flate: reduce stateless allocations by @RXamzin in https://github.com/klauspost/compress/pull/1106 + +* Oct 20, 2025 - [1.18.1](https://github.com/klauspost/compress/releases/tag/v1.18.1) - RETRACTED * zstd: Add simple zstd EncodeTo/DecodeTo functions https://github.com/klauspost/compress/pull/1079 * zstd: Fix incorrect buffer size in dictionary encodes https://github.com/klauspost/compress/pull/1059 * s2: check for cap, not len of buffer in EncodeBetter/Best by @vdarulis in https://github.com/klauspost/compress/pull/1080 @@ -603,7 +609,7 @@ # deflate usage -The packages are drop-in replacements for standard libraries. Simply replace the import path to use them: +The packages are drop-in replacements for standard library [deflate](https://godoc.org/github.com/klauspost/compress/flate), [gzip](https://godoc.org/github.com/klauspost/compress/gzip), [zip](https://godoc.org/github.com/klauspost/compress/zip), and [zlib](https://godoc.org/github.com/klauspost/compress/zlib). Simply replace the import path to use them: Typical speed is about 2x of the standard library packages. @@ -614,17 +620,15 @@ | `archive/zip` | `github.com/klauspost/compress/zip` | [zip](https://pkg.go.dev/github.com/klauspost/compress/zip?tab=doc) | | `compress/flate` | `github.com/klauspost/compress/flate` | [flate](https://pkg.go.dev/github.com/klauspost/compress/flate?tab=doc) | -* Optimized [deflate](https://godoc.org/github.com/klauspost/compress/flate) packages which can be used as a dropin replacement for [gzip](https://godoc.org/github.com/klauspost/compress/gzip), [zip](https://godoc.org/github.com/klauspost/compress/zip) and [zlib](https://godoc.org/github.com/klauspost/compress/zlib). - -You may also be interested in [pgzip](https://github.com/klauspost/pgzip), which is a drop in replacement for gzip, which support multithreaded compression on big files and the optimized [crc32](https://github.com/klauspost/crc32) package used by these packages. +You may also be interested in [pgzip](https://github.com/klauspost/pgzip), which is a drop-in replacement for gzip, which support multithreaded compression on big files and the optimized [crc32](https://github.com/klauspost/crc32) package used by these packages. -The packages contains the same as the standard library, so you can use the godoc for that: [gzip](http://golang.org/pkg/compress/gzip/), [zip](http://golang.org/pkg/archive/zip/), [zlib](http://golang.org/pkg/compress/zlib/), [flate](http://golang.org/pkg/compress/flate/). +The packages implement the same API as the standard library, so you can use the original godoc documentation: [gzip](http://golang.org/pkg/compress/gzip/), [zip](http://golang.org/pkg/archive/zip/), [zlib](http://golang.org/pkg/compress/zlib/), [flate](http://golang.org/pkg/compress/flate/). Currently there is only minor speedup on decompression (mostly CRC32 calculation). Memory usage is typically 1MB for a Writer. stdlib is in the same range. If you expect to have a lot of concurrently allocated Writers consider using -the stateless compress described below. +the stateless compression described below. For compression performance, see: [this spreadsheet](https://docs.google.com/spreadsheets/d/1nuNE2nPfuINCZJRMt6wFWhKpToF95I47XjSsc-1rbPQ/edit?usp=sharing). @@ -684,3 +688,6 @@ This code is licensed under the same conditions as the original Go code. See LICENSE file. + + + diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/github.com/klauspost/compress/zstd/decoder.go new/vendor/github.com/klauspost/compress/zstd/decoder.go --- old/vendor/github.com/klauspost/compress/zstd/decoder.go 2026-02-03 13:30:36.000000000 +0100 +++ new/vendor/github.com/klauspost/compress/zstd/decoder.go 2026-03-11 17:38:01.000000000 +0100 @@ -39,9 +39,6 @@ frame *frameDec - // Custom dictionaries. - dicts map[uint32]*dict - // streamWg is the waitgroup for all streams streamWg sync.WaitGroup } @@ -101,12 +98,10 @@ d.current.err = ErrDecoderNilInput } - // Transfer option dicts. - d.dicts = make(map[uint32]*dict, len(d.o.dicts)) - for _, dc := range d.o.dicts { - d.dicts[dc.id] = dc + // Initialize dict map if needed. + if d.o.dicts == nil { + d.o.dicts = make(map[uint32]*dict) } - d.o.dicts = nil // Create decoders d.decoders = make(chan *blockDec, d.o.concurrent) @@ -238,6 +233,21 @@ return nil } +// ResetWithOptions will reset the decoder and apply the given options +// for the next stream or DecodeAll operation. +// Options are applied on top of the existing options. +// Some options cannot be changed on reset and will return an error. +func (d *Decoder) ResetWithOptions(r io.Reader, opts ...DOption) error { + d.o.resetOpt = true + defer func() { d.o.resetOpt = false }() + for _, o := range opts { + if err := o(&d.o); err != nil { + return err + } + } + return d.Reset(r) +} + // drainOutput will drain the output until errEndOfStream is sent. func (d *Decoder) drainOutput() { if d.current.cancel != nil { @@ -930,7 +940,7 @@ } func (d *Decoder) setDict(frame *frameDec) (err error) { - dict, ok := d.dicts[frame.DictionaryID] + dict, ok := d.o.dicts[frame.DictionaryID] if ok { if debugDecoder { println("setting dict", frame.DictionaryID) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/github.com/klauspost/compress/zstd/decoder_options.go new/vendor/github.com/klauspost/compress/zstd/decoder_options.go --- old/vendor/github.com/klauspost/compress/zstd/decoder_options.go 2026-02-03 13:30:36.000000000 +0100 +++ new/vendor/github.com/klauspost/compress/zstd/decoder_options.go 2026-03-11 17:38:01.000000000 +0100 @@ -20,10 +20,11 @@ concurrent int maxDecodedSize uint64 maxWindowSize uint64 - dicts []*dict + dicts map[uint32]*dict ignoreChecksum bool limitToCap bool decodeBufsBelow int + resetOpt bool } func (o *decoderOptions) setDefault() { @@ -42,8 +43,15 @@ // WithDecoderLowmem will set whether to use a lower amount of memory, // but possibly have to allocate more while running. +// Cannot be changed with ResetWithOptions. func WithDecoderLowmem(b bool) DOption { - return func(o *decoderOptions) error { o.lowMem = b; return nil } + return func(o *decoderOptions) error { + if o.resetOpt && b != o.lowMem { + return errors.New("WithDecoderLowmem cannot be changed on Reset") + } + o.lowMem = b + return nil + } } // WithDecoderConcurrency sets the number of created decoders. @@ -53,18 +61,23 @@ // inflight blocks. // When decoding streams and setting maximum to 1, // no async decoding will be done. +// The value supplied must be at least 0. // When a value of 0 is provided GOMAXPROCS will be used. // By default this will be set to 4 or GOMAXPROCS, whatever is lower. +// Cannot be changed with ResetWithOptions. func WithDecoderConcurrency(n int) DOption { return func(o *decoderOptions) error { if n < 0 { - return errors.New("concurrency must be at least 1") + return errors.New("concurrency must be at least 0") } + newVal := n if n == 0 { - o.concurrent = runtime.GOMAXPROCS(0) - } else { - o.concurrent = n + newVal = runtime.GOMAXPROCS(0) } + if o.resetOpt && newVal != o.concurrent { + return errors.New("WithDecoderConcurrency cannot be changed on Reset") + } + o.concurrent = newVal return nil } } @@ -73,6 +86,7 @@ // non-streaming operations or maximum window size for streaming operations. // This can be used to control memory usage of potentially hostile content. // Maximum is 1 << 63 bytes. Default is 64GiB. +// Can be changed with ResetWithOptions. func WithDecoderMaxMemory(n uint64) DOption { return func(o *decoderOptions) error { if n == 0 { @@ -92,16 +106,20 @@ // "zstd --train" from the Zstandard reference implementation. // // If several dictionaries with the same ID are provided, the last one will be used. +// Can be changed with ResetWithOptions. // // [dictionary format]: https://github.com/facebook/zstd/blob/dev/doc/zstd_compression_format.md#dictionary-format func WithDecoderDicts(dicts ...[]byte) DOption { return func(o *decoderOptions) error { + if o.dicts == nil { + o.dicts = make(map[uint32]*dict) + } for _, b := range dicts { d, err := loadDict(b) if err != nil { return err } - o.dicts = append(o.dicts, d) + o.dicts[d.id] = d } return nil } @@ -109,12 +127,16 @@ // WithDecoderDictRaw registers a dictionary that may be used by the decoder. // The slice content can be arbitrary data. +// Can be changed with ResetWithOptions. func WithDecoderDictRaw(id uint32, content []byte) DOption { return func(o *decoderOptions) error { if bits.UintSize > 32 && uint(len(content)) > dictMaxLength { return fmt.Errorf("dictionary of size %d > 2GiB too large", len(content)) } - o.dicts = append(o.dicts, &dict{id: id, content: content, offsets: [3]int{1, 4, 8}}) + if o.dicts == nil { + o.dicts = make(map[uint32]*dict) + } + o.dicts[id] = &dict{id: id, content: content, offsets: [3]int{1, 4, 8}} return nil } } @@ -124,6 +146,7 @@ // The Decoder will likely allocate more memory based on the WithDecoderLowmem setting. // If WithDecoderMaxMemory is set to a lower value, that will be used. // Default is 512MB, Maximum is ~3.75 TB as per zstandard spec. +// Can be changed with ResetWithOptions. func WithDecoderMaxWindow(size uint64) DOption { return func(o *decoderOptions) error { if size < MinWindowSize { @@ -141,6 +164,7 @@ // or any size set in WithDecoderMaxMemory. // This can be used to limit decoding to a specific maximum output size. // Disabled by default. +// Can be changed with ResetWithOptions. func WithDecodeAllCapLimit(b bool) DOption { return func(o *decoderOptions) error { o.limitToCap = b @@ -153,17 +177,37 @@ // This typically uses less allocations but will have the full decompressed object in memory. // Note that DecodeAllCapLimit will disable this, as well as giving a size of 0 or less. // Default is 128KiB. +// Cannot be changed with ResetWithOptions. func WithDecodeBuffersBelow(size int) DOption { return func(o *decoderOptions) error { + if o.resetOpt && size != o.decodeBufsBelow { + return errors.New("WithDecodeBuffersBelow cannot be changed on Reset") + } o.decodeBufsBelow = size return nil } } // IgnoreChecksum allows to forcibly ignore checksum checking. +// Can be changed with ResetWithOptions. func IgnoreChecksum(b bool) DOption { return func(o *decoderOptions) error { o.ignoreChecksum = b return nil } } + +// WithDecoderDictDelete removes dictionaries by ID. +// If no ids are passed, all dictionaries are deleted. +// Should be used with ResetWithOptions. +func WithDecoderDictDelete(ids ...uint32) DOption { + return func(o *decoderOptions) error { + if len(ids) == 0 { + clear(o.dicts) + } + for _, id := range ids { + delete(o.dicts, id) + } + return nil + } +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/github.com/klauspost/compress/zstd/encoder.go new/vendor/github.com/klauspost/compress/zstd/encoder.go --- old/vendor/github.com/klauspost/compress/zstd/encoder.go 2026-02-03 13:30:36.000000000 +0100 +++ new/vendor/github.com/klauspost/compress/zstd/encoder.go 2026-03-11 17:38:01.000000000 +0100 @@ -131,6 +131,22 @@ s.frameContentSize = 0 } +// ResetWithOptions will re-initialize the writer and apply the given options +// as a new, independent stream. +// Options are applied on top of the existing options. +// Some options cannot be changed on reset and will return an error. +func (e *Encoder) ResetWithOptions(w io.Writer, opts ...EOption) error { + e.o.resetOpt = true + defer func() { e.o.resetOpt = false }() + for _, o := range opts { + if err := o(&e.o); err != nil { + return err + } + } + e.Reset(w) + return nil +} + // ResetContentSize will reset and set a content size for the next stream. // If the bytes written does not match the size given an error will be returned // when calling Close(). diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/github.com/klauspost/compress/zstd/encoder_options.go new/vendor/github.com/klauspost/compress/zstd/encoder_options.go --- old/vendor/github.com/klauspost/compress/zstd/encoder_options.go 2026-02-03 13:30:36.000000000 +0100 +++ new/vendor/github.com/klauspost/compress/zstd/encoder_options.go 2026-03-11 17:38:01.000000000 +0100 @@ -14,6 +14,7 @@ // options retains accumulated state of multiple options. type encoderOptions struct { + resetOpt bool concurrent int level EncoderLevel single *bool @@ -71,19 +72,28 @@ // WithEncoderCRC will add CRC value to output. // Output will be 4 bytes larger. +// Can be changed with ResetWithOptions. func WithEncoderCRC(b bool) EOption { return func(o *encoderOptions) error { o.crc = b; return nil } } // WithEncoderConcurrency will set the concurrency, // meaning the maximum number of encoders to run concurrently. -// The value supplied must be at least 1. +// The value supplied must be at least 0. +// When a value of 0 is provided GOMAXPROCS will be used. // For streams, setting a value of 1 will disable async compression. // By default this will be set to GOMAXPROCS. +// Cannot be changed with ResetWithOptions. func WithEncoderConcurrency(n int) EOption { return func(o *encoderOptions) error { - if n <= 0 { - return fmt.Errorf("concurrency must be at least 1") + if n < 0 { + return errors.New("concurrency must at least 0") + } + if n == 0 { + n = runtime.GOMAXPROCS(0) + } + if o.resetOpt && n != o.concurrent { + return errors.New("WithEncoderConcurrency cannot be changed on Reset") } o.concurrent = n return nil @@ -95,6 +105,7 @@ // A larger value will enable better compression but allocate more memory and, // for above-default values, take considerably longer. // The default value is determined by the compression level and max 8MB. +// Cannot be changed with ResetWithOptions. func WithWindowSize(n int) EOption { return func(o *encoderOptions) error { switch { @@ -105,6 +116,9 @@ case (n & (n - 1)) != 0: return errors.New("window size must be a power of 2") } + if o.resetOpt && n != o.windowSize { + return errors.New("WithWindowSize cannot be changed on Reset") + } o.windowSize = n o.customWindow = true @@ -122,6 +136,7 @@ // n must be > 0 and <= 1GB, 1<<30 bytes. // The padded area will be filled with data from crypto/rand.Reader. // If `EncodeAll` is used with data already in the destination, the total size will be multiple of this. +// Can be changed with ResetWithOptions. func WithEncoderPadding(n int) EOption { return func(o *encoderOptions) error { if n <= 0 { @@ -215,12 +230,16 @@ } // WithEncoderLevel specifies a predefined compression level. +// Cannot be changed with ResetWithOptions. func WithEncoderLevel(l EncoderLevel) EOption { return func(o *encoderOptions) error { switch { case l <= speedNotSet || l >= speedLast: return fmt.Errorf("unknown encoder level") } + if o.resetOpt && l != o.level { + return errors.New("WithEncoderLevel cannot be changed on Reset") + } o.level = l if !o.customWindow { switch o.level { @@ -248,6 +267,7 @@ // WithZeroFrames will encode 0 length input as full frames. // This can be needed for compatibility with zstandard usage, // but is not needed for this package. +// Can be changed with ResetWithOptions. func WithZeroFrames(b bool) EOption { return func(o *encoderOptions) error { o.fullZero = b @@ -259,6 +279,7 @@ // Disabling this will skip incompressible data faster, but in cases with no matches but // skewed character distribution compression is lost. // Default value depends on the compression level selected. +// Can be changed with ResetWithOptions. func WithAllLitEntropyCompression(b bool) EOption { return func(o *encoderOptions) error { o.customALEntropy = true @@ -270,6 +291,7 @@ // WithNoEntropyCompression will always skip entropy compression of literals. // This can be useful if content has matches, but unlikely to benefit from entropy // compression. Usually the slight speed improvement is not worth enabling this. +// Can be changed with ResetWithOptions. func WithNoEntropyCompression(b bool) EOption { return func(o *encoderOptions) error { o.noEntropy = b @@ -287,6 +309,7 @@ // This is only a recommendation, each decoder is free to support higher or lower limits, depending on local limitations. // If this is not specified, block encodes will automatically choose this based on the input size and the window size. // This setting has no effect on streamed encodes. +// Can be changed with ResetWithOptions. func WithSingleSegment(b bool) EOption { return func(o *encoderOptions) error { o.single = &b @@ -298,8 +321,12 @@ // slower encoding speed. // This will not change the window size which is the primary function for reducing // memory usage. See WithWindowSize. +// Cannot be changed with ResetWithOptions. func WithLowerEncoderMem(b bool) EOption { return func(o *encoderOptions) error { + if o.resetOpt && b != o.lowMem { + return errors.New("WithLowerEncoderMem cannot be changed on Reset") + } o.lowMem = b return nil } @@ -311,6 +338,7 @@ // "zstd --train" from the Zstandard reference implementation. // // The encoder *may* choose to use no dictionary instead for certain payloads. +// Can be changed with ResetWithOptions. // // [dictionary format]: https://github.com/facebook/zstd/blob/dev/doc/zstd_compression_format.md#dictionary-format func WithEncoderDict(dict []byte) EOption { @@ -328,6 +356,7 @@ // // The slice content may contain arbitrary data. It will be used as an initial // history. +// Can be changed with ResetWithOptions. func WithEncoderDictRaw(id uint32, content []byte) EOption { return func(o *encoderOptions) error { if bits.UintSize > 32 && uint(len(content)) > dictMaxLength { @@ -337,3 +366,12 @@ return nil } } + +// WithEncoderDictDelete clears the dictionary, so no dictionary will be used. +// Should be used with ResetWithOptions. +func WithEncoderDictDelete() EOption { + return func(o *encoderOptions) error { + o.dict = nil + return nil + } +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/modules.txt new/vendor/modules.txt --- old/vendor/modules.txt 2026-02-03 13:30:36.000000000 +0100 +++ new/vendor/modules.txt 2026-03-11 17:38:01.000000000 +0100 @@ -23,8 +23,8 @@ github.com/Microsoft/go-winio/internal/socket github.com/Microsoft/go-winio/internal/stringbuffer github.com/Microsoft/go-winio/pkg/guid -# github.com/ProtonMail/go-crypto v1.3.0 -## explicit; go 1.22.0 +# github.com/ProtonMail/go-crypto v1.4.0 +## explicit; go 1.23.0 github.com/ProtonMail/go-crypto/bitcurves github.com/ProtonMail/go-crypto/brainpool github.com/ProtonMail/go-crypto/eax @@ -72,7 +72,7 @@ # github.com/cavaliergopher/cpio v1.0.1 ## explicit; go 1.17 github.com/cavaliergopher/cpio -# github.com/cloudflare/circl v1.6.1 +# github.com/cloudflare/circl v1.6.3 ## explicit; go 1.22.0 github.com/cloudflare/circl/dh/x25519 github.com/cloudflare/circl/dh/x448 @@ -117,8 +117,8 @@ github.com/go-git/go-billy/v5/memfs github.com/go-git/go-billy/v5/osfs github.com/go-git/go-billy/v5/util -# github.com/go-git/go-git/v5 v5.16.4 -## explicit; go 1.23.0 +# github.com/go-git/go-git/v5 v5.16.5 +## explicit; go 1.24.0 github.com/go-git/go-git/v5 github.com/go-git/go-git/v5/config github.com/go-git/go-git/v5/internal/path_util @@ -205,7 +205,7 @@ # github.com/kevinburke/ssh_config v1.2.0 ## explicit github.com/kevinburke/ssh_config -# github.com/klauspost/compress v1.18.3 +# github.com/klauspost/compress v1.18.4 ## explicit; go 1.23 github.com/klauspost/compress github.com/klauspost/compress/flate
