Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package apko for openSUSE:Factory checked in at 2025-03-13 15:07:10 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/apko (Old) and /work/SRC/openSUSE:Factory/.apko.new.19136 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "apko" Thu Mar 13 15:07:10 2025 rev:39 rq:1252644 version:0.25.3 Changes: -------- --- /work/SRC/openSUSE:Factory/apko/apko.changes 2025-03-10 18:07:33.620166680 +0100 +++ /work/SRC/openSUSE:Factory/.apko.new.19136/apko.changes 2025-03-13 15:08:07.467049657 +0100 @@ -1,0 +2,7 @@ +Thu Mar 13 05:53:15 UTC 2025 - opensuse_buildserv...@ojkastl.de + +- Update to version 0.25.3: + * Use sync.Pools for allocations (#1568) + * Add SubFS implementation for Melange (#1560) + +------------------------------------------------------------------- Old: ---- apko-0.25.2.obscpio New: ---- apko-0.25.3.obscpio ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ apko.spec ++++++ --- /var/tmp/diff_new_pack.OFhPDg/_old 2025-03-13 15:08:08.879108886 +0100 +++ /var/tmp/diff_new_pack.OFhPDg/_new 2025-03-13 15:08:08.879108886 +0100 @@ -17,7 +17,7 @@ Name: apko -Version: 0.25.2 +Version: 0.25.3 Release: 0 Summary: Build OCI images from APK packages directly without Dockerfile License: Apache-2.0 ++++++ _service ++++++ --- /var/tmp/diff_new_pack.OFhPDg/_old 2025-03-13 15:08:08.915110396 +0100 +++ /var/tmp/diff_new_pack.OFhPDg/_new 2025-03-13 15:08:08.919110564 +0100 @@ -3,7 +3,7 @@ <param name="url">https://github.com/chainguard-dev/apko</param> <param name="scm">git</param> <param name="exclude">.git</param> - <param name="revision">v0.25.2</param> + <param name="revision">v0.25.3</param> <param name="versionformat">@PARENT_TAG@</param> <param name="versionrewrite-pattern">v(.*)</param> <param name="changesgenerate">enable</param> ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.OFhPDg/_old 2025-03-13 15:08:08.943111571 +0100 +++ /var/tmp/diff_new_pack.OFhPDg/_new 2025-03-13 15:08:08.947111739 +0100 @@ -1,6 +1,6 @@ <servicedata> <service name="tar_scm"> <param name="url">https://github.com/chainguard-dev/apko</param> - <param name="changesrevision">c524373d42a781ac36cf5a8b57d3959e84288ba1</param></service></servicedata> + <param name="changesrevision">1df32e3292f9e12bfdb7dc609e5ccb59dd401b84</param></service></servicedata> (No newline at EOF) ++++++ apko-0.25.2.obscpio -> apko-0.25.3.obscpio ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/apko-0.25.2/pkg/apk/expandapk/expandapk.go new/apko-0.25.3/pkg/apk/expandapk/expandapk.go --- old/apko-0.25.2/pkg/apk/expandapk/expandapk.go 2025-03-08 08:42:22.000000000 +0100 +++ new/apko-0.25.3/pkg/apk/expandapk/expandapk.go 2025-03-12 19:31:18.000000000 +0100 @@ -28,6 +28,40 @@ "go.opentelemetry.io/otel" ) +var slicePool = sync.Pool{ + New: func() interface{} { + return make([]byte, 1<<20) + }, +} + +func pooledSlice() []byte { + return slicePool.Get().([]byte) +} + +var readerPool = sync.Pool{ + New: func() interface{} { + return bufio.NewReaderSize(nil, 1<<20) + }, +} + +func pooledBufioReader(r io.Reader) *bufio.Reader { + br := readerPool.Get().(*bufio.Reader) + br.Reset(r) + return br +} + +var writerPool = sync.Pool{ + New: func() interface{} { + return bufio.NewWriterSize(nil, 1<<20) + }, +} + +func pooledBufioWriter(w io.Writer) *bufio.Writer { + bw := writerPool.Get().(*bufio.Writer) + bw.Reset(w) + return bw +} + // APKExpanded contains information about and reference to an expanded APK package. // Close() deletes all temporary files and directories created during the expansion process. type APKExpanded struct { @@ -66,8 +100,6 @@ controlData []byte } -const meg = 1 << 20 - func (a *APKExpanded) ControlData() ([]byte, error) { a.Lock() defer a.Unlock() @@ -100,12 +132,6 @@ return nil, fmt.Errorf("opening package data file: %w", err) } - // Use min(1MB, a.Size) bufio to avoid GC pressure for small packages. - bufSize := meg - if total := int(a.Size); total != 0 && total < bufSize { - bufSize = total - } - // Handle old caches without the uncompressed file. f, err := os.Open(a.PackageFile) if err != nil { @@ -113,7 +139,9 @@ } defer f.Close() - br := bufio.NewReaderSize(f, bufSize) + br := pooledBufioReader(f) + defer readerPool.Put(br) + zr, err := gzip.NewReader(br) if err != nil { return nil, fmt.Errorf("parsing %q: %w", a.PackageFile, err) @@ -124,7 +152,9 @@ return nil, fmt.Errorf("opening tar file %q: %w", a.TarFile, err) } - buf := make([]byte, bufSize) + buf := pooledSlice() + defer slicePool.Put(buf) + if _, err := io.CopyBuffer(uf, zr, buf); err != nil { return nil, fmt.Errorf("decompressing %q: %w", a.PackageFile, err) } @@ -390,7 +420,9 @@ if err != nil { return nil, fmt.Errorf("opening tar file: %w", err) } - bw := bufio.NewWriterSize(tarfile, 1<<20) + bw := pooledBufioWriter(tarfile) + defer writerPool.Put(bw) + tr := io.TeeReader(gzi, bw) if err := checkSums(ctx, tr); err != nil { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/apko-0.25.2/pkg/apk/fs/fs.go new/apko-0.25.3/pkg/apk/fs/fs.go --- old/apko-0.25.2/pkg/apk/fs/fs.go 2025-03-08 08:42:22.000000000 +0100 +++ new/apko-0.25.3/pkg/apk/fs/fs.go 2025-03-12 19:31:18.000000000 +0100 @@ -45,6 +45,7 @@ GetXattr(path string, attr string) ([]byte, error) RemoveXattr(path string, attr string) error ListXattrs(path string) (map[string][]byte, error) + Sub(path string) (FullFS, error) } // File is an interface for a file. It includes Read, Write, Close. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/apko-0.25.2/pkg/apk/fs/memfs.go new/apko-0.25.3/pkg/apk/fs/memfs.go --- old/apko-0.25.2/pkg/apk/fs/memfs.go 2025-03-08 08:42:22.000000000 +0100 +++ new/apko-0.25.3/pkg/apk/fs/memfs.go 2025-03-12 19:31:18.000000000 +0100 @@ -524,6 +524,36 @@ return ret, nil } +func Sub(fsys FullFS, dir string) (FullFS, error) { + if !fs.ValidPath(dir) { + return nil, &fs.PathError{Op: "sub", Path: dir, Err: fs.ErrInvalid} + } + if dir == "." { + return fsys, nil + } + return &SubFS{fsys, dir}, nil +} + +func (m *memFS) Sub(path string) (FullFS, error) { + cleanPath := filepath.Clean(path) + if cleanPath == "." { + return m, nil + } + + info, err := m.Stat(cleanPath) + if err != nil { + return nil, err + } + if !info.IsDir() { + return nil, errors.New("not a directory") + } + + return &SubFS{ + FS: m, + Root: cleanPath, + }, nil +} + type memFile struct { node *node fs *memFS diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/apko-0.25.2/pkg/apk/fs/rwosfs.go new/apko-0.25.3/pkg/apk/fs/rwosfs.go --- old/apko-0.25.2/pkg/apk/fs/rwosfs.go 2025-03-08 08:42:22.000000000 +0100 +++ new/apko-0.25.3/pkg/apk/fs/rwosfs.go 2025-03-12 19:31:18.000000000 +0100 @@ -547,6 +547,9 @@ func (f *dirFS) ListXattrs(path string) (map[string][]byte, error) { return f.overrides.ListXattrs(path) } +func (f *dirFS) Sub(path string) (FullFS, error) { + return f.overrides.Sub(path) +} // sanitize ensures that we never go beyond the root of the filesystem func (f *dirFS) sanitizePath(p string) (v string, err error) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/apko-0.25.2/pkg/apk/fs/sub.go new/apko-0.25.3/pkg/apk/fs/sub.go --- old/apko-0.25.2/pkg/apk/fs/sub.go 1970-01-01 01:00:00.000000000 +0100 +++ new/apko-0.25.3/pkg/apk/fs/sub.go 2025-03-12 19:31:18.000000000 +0100 @@ -0,0 +1,148 @@ +package fs + +import ( + "errors" + "io/fs" + "path/filepath" + "time" +) + +type SubFS struct { + FS FullFS + Root string +} + +func (s *SubFS) Open(path string) (fs.File, error) { + if !fs.ValidPath(path) { + return nil, &fs.PathError{Op: "open", Path: path, Err: fs.ErrInvalid} + } + fullPath := filepath.Join(s.Root, path) + return s.FS.Open(fullPath) +} + +func (s *SubFS) OpenReaderAt(path string) (File, error) { + fullPath := filepath.Join(s.Root, path) + return s.FS.OpenReaderAt(fullPath) +} + +func (s *SubFS) OpenFile(name string, flag int, perm fs.FileMode) (File, error) { + fullPath := filepath.Join(s.Root, name) + return s.FS.OpenFile(fullPath, flag, perm) +} +func (s *SubFS) Create(name string) (File, error) { + fullPath := filepath.Join(s.Root, name) + return s.FS.Create(fullPath) +} + +func (s *SubFS) ReadFile(name string) ([]byte, error) { + fullPath := filepath.Join(s.Root, name) + return s.FS.ReadFile(fullPath) +} +func (s *SubFS) WriteFile(name string, b []byte, mode fs.FileMode) error { + fullPath := filepath.Join(s.Root, name) + return s.FS.WriteFile(fullPath, b, mode) +} + +func (s *SubFS) Mkdir(path string, perm fs.FileMode) error { + fullPath := filepath.Join(s.Root, path) + return s.FS.Mkdir(fullPath, perm) +} +func (s *SubFS) MkdirAll(path string, perm fs.FileMode) error { + fullPath := filepath.Join(s.Root, path) + return s.FS.MkdirAll(fullPath, perm) +} +func (s *SubFS) ReadDir(name string) ([]fs.DirEntry, error) { + fullPath := filepath.Join(s.Root, name) + return s.FS.ReadDir(fullPath) +} + +func (s *SubFS) Stat(path string) (fs.FileInfo, error) { + fullPath := filepath.Join(s.Root, path) + return s.FS.Stat(fullPath) +} +func (s *SubFS) Lstat(path string) (fs.FileInfo, error) { + fullPath := filepath.Join(s.Root, path) + return s.FS.Lstat(fullPath) +} + +func (s *SubFS) Remove(name string) error { + fullPath := filepath.Join(s.Root, name) + return s.FS.Remove(fullPath) +} +func (s *SubFS) Chmod(path string, perm fs.FileMode) error { + fullPath := filepath.Join(s.Root, path) + return s.FS.Chmod(fullPath, perm) +} +func (s *SubFS) Chown(path string, uid int, gid int) error { + fullPath := filepath.Join(s.Root, path) + return s.FS.Chown(fullPath, uid, gid) +} +func (s *SubFS) Chtimes(path string, atime time.Time, mtime time.Time) error { + fullPath := filepath.Join(s.Root, path) + return s.FS.Chtimes(fullPath, atime, mtime) +} + +func (s *SubFS) Symlink(oldname, newname string) error { + return s.FS.Symlink(oldname, newname) +} +func (s *SubFS) Link(oldname, newname string) error { + return s.FS.Link(oldname, newname) +} +func (s *SubFS) Readlink(name string) (string, error) { + fullPath := filepath.Join(s.Root, name) + return s.FS.Readlink(fullPath) +} + +func (s *SubFS) Mknod(path string, mode uint32, dev int) error { + fullPath := filepath.Join(s.Root, path) + return s.FS.Mknod(fullPath, mode, dev) +} +func (s *SubFS) Readnod(path string) (int, error) { + fullPath := filepath.Join(s.Root, path) + return s.FS.Readnod(fullPath) +} + +func (s *SubFS) SetXattr(path string, attr string, data []byte) error { + fullPath := filepath.Join(s.Root, path) + return s.FS.SetXattr(fullPath, attr, data) +} +func (s *SubFS) GetXattr(path string, attr string) ([]byte, error) { + fullPath := filepath.Join(s.Root, path) + return s.FS.GetXattr(fullPath, attr) +} + +func (s *SubFS) RemoveXattr(path string, attr string) error { + fullPath := filepath.Join(s.Root, path) + return s.FS.RemoveXattr(fullPath, attr) +} + +func (s *SubFS) ListXattrs(path string) (map[string][]byte, error) { + fullPath := filepath.Join(s.Root, path) + return s.FS.ListXattrs(fullPath) +} + +func (s *SubFS) Sub(path string) (FullFS, error) { + if !fs.ValidPath(path) { + return nil, &fs.PathError{Op: "sub", Path: path, Err: fs.ErrInvalid} + } + + cleanPath := filepath.Clean(path) + + if cleanPath == "." { + return s, nil + } + + fullPath := filepath.Join(s.Root, cleanPath) + info, err := s.FS.Stat(fullPath) + if err != nil { + return nil, err + } + if !info.IsDir() { + return nil, errors.New("not a directory") + } + + return &SubFS{ + FS: s.FS, + Root: fullPath, + }, nil +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/apko-0.25.2/pkg/apk/internal/tarfs/tarfs.go new/apko-0.25.3/pkg/apk/internal/tarfs/tarfs.go --- old/apko-0.25.2/pkg/apk/internal/tarfs/tarfs.go 2025-03-08 08:42:22.000000000 +0100 +++ new/apko-0.25.3/pkg/apk/internal/tarfs/tarfs.go 2025-03-12 19:31:18.000000000 +0100 @@ -24,9 +24,22 @@ "io/fs" "path" "slices" + "sync" "time" ) +var readerPool = sync.Pool{ + New: func() interface{} { + return bufio.NewReaderSize(nil, 1<<20) + }, +} + +func pooledBufioReader(r io.Reader) *bufio.Reader { + br := readerPool.Get().(*bufio.Reader) + br.Reset(r) + return br +} + type Entry struct { Header tar.Header Offset int64 @@ -204,7 +217,11 @@ // TODO: Consider caching this across builds. r := io.NewSectionReader(ra, 0, size) - cr := &countReader{bufio.NewReaderSize(r, 1<<20), 0} + + br := pooledBufioReader(r) + defer readerPool.Put(br) + + cr := &countReader{br, 0} tr := tar.NewReader(cr) for { hdr, err := tr.Next() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/apko-0.25.2/pkg/build/build_implementation.go new/apko-0.25.3/pkg/build/build_implementation.go --- old/apko-0.25.2/pkg/build/build_implementation.go 2025-03-08 08:42:22.000000000 +0100 +++ new/apko-0.25.3/pkg/build/build_implementation.go 2025-03-12 19:31:18.000000000 +0100 @@ -25,6 +25,7 @@ "os" "path/filepath" "runtime" + "sync" gzip "github.com/klauspost/pgzip" "github.com/sigstore/cosign/v2/pkg/oci" @@ -48,12 +49,33 @@ // concurrent builds on giant machines, and uses only 1 core on tiny machines. var pgzipThreads = min(runtime.GOMAXPROCS(0), 8) -func min(l, r int) int { - if l < r { - return l - } +var pgzipPool = sync.Pool{ + New: func() interface{} { + zw := gzip.NewWriter(nil) + if err := zw.SetConcurrency(1<<20, pgzipThreads); err != nil { + // This should never happen. + panic(fmt.Errorf("tried to set pgzip concurrency to %d: %w", pgzipThreads, err)) + } + return zw + }, +} + +func pooledGzipWriter(w io.Writer) *gzip.Writer { + zw := pgzipPool.Get().(*gzip.Writer) + zw.Reset(w) + return zw +} - return r +var bufioPool = sync.Pool{ + New: func() interface{} { + return bufio.NewWriterSize(nil, 1<<22) + }, +} + +func pooledBufioWriter(w io.Writer) *bufio.Writer { + bw := bufioPool.Get().(*bufio.Writer) + bw.Reset(w) + return bw } // BuildTarball takes the fully populated working directory and saves it to @@ -85,11 +107,11 @@ digest := sha256.New() - buf := bufio.NewWriterSize(outfile, 1<<22) - gzw := gzip.NewWriter(io.MultiWriter(digest, buf)) - if err := gzw.SetConcurrency(1<<20, pgzipThreads); err != nil { - return "", nil, nil, 0, fmt.Errorf("tried to set pgzip concurrency to %d: %w", pgzipThreads, err) - } + buf := pooledBufioWriter(outfile) + defer bufioPool.Put(buf) + + gzw := pooledGzipWriter(io.MultiWriter(digest, buf)) + defer pgzipPool.Put(gzw) diffid := sha256.New() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/apko-0.25.2/pkg/tarfs/fs.go new/apko-0.25.3/pkg/tarfs/fs.go --- old/apko-0.25.2/pkg/tarfs/fs.go 2025-03-08 08:42:22.000000000 +0100 +++ new/apko-0.25.3/pkg/tarfs/fs.go 2025-03-12 19:31:18.000000000 +0100 @@ -801,6 +801,27 @@ return ret, nil } +func (m *memFS) Sub(path string) (apkfs.FullFS, error) { + cleanPath := filepath.Clean(path) + + if cleanPath == "." { + return m, nil + } + + info, err := m.Stat(cleanPath) + if err != nil { + return nil, err + } + if !info.IsDir() { + return nil, errors.New("not a directory") + } + + return &apkfs.SubFS{ + FS: m, + Root: cleanPath, + }, nil +} + type memFile struct { node *node fs *memFS ++++++ apko.obsinfo ++++++ --- /var/tmp/diff_new_pack.OFhPDg/_old 2025-03-13 15:08:09.251124490 +0100 +++ /var/tmp/diff_new_pack.OFhPDg/_new 2025-03-13 15:08:09.255124658 +0100 @@ -1,5 +1,5 @@ name: apko -version: 0.25.2 -mtime: 1741419742 -commit: c524373d42a781ac36cf5a8b57d3959e84288ba1 +version: 0.25.3 +mtime: 1741804278 +commit: 1df32e3292f9e12bfdb7dc609e5ccb59dd401b84 ++++++ vendor.tar.gz ++++++ /work/SRC/openSUSE:Factory/apko/vendor.tar.gz /work/SRC/openSUSE:Factory/.apko.new.19136/vendor.tar.gz differ: char 5, line 1