Add nested archive cataloging (#5260)

Signed-off-by: Kudryavcev Nikolay <kydry.nikolau@gmail.com>
Signed-off-by: Thomas Bechtold <thomasbechtold@jpberlin.de>
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
Signed-off-by: Keith Zantow <kzantow@gmail.com>
Co-authored-by: Kudryavcev Nikolay <kydry.nikolau@gmail.com>
Co-authored-by: Thomas Bechtold <thomasbechtold@jpberlin.de>
Co-authored-by: Alex Goodman <wagoodman@users.noreply.github.com>
This commit is contained in:
Keith Zantow
2026-10-29 17:33:07 -04:00
committed by GitHub
co-authored by Kudryavcev Nikolay Thomas Bechtold Alex Goodman
parent 14a0beb93c
commit 4b8a3db5f3
224 changed files with 15918 additions and 1281 deletions
+84
View File
@@ -0,0 +1,84 @@
package testutils
import (
"archive/tar"
"archive/zip"
"bytes"
"compress/gzip"
"fmt"
"io"
"sort"
"testing"
"github.com/stretchr/testify/require"
)
// Zip builds a zip of the entries in sorted name order: archive limits bite as entries are read, so
// order decides which land before a truncation.
func Zip[T ~string | ~[]byte](t testing.TB, entries map[string]T) []byte {
t.Helper()
var buf bytes.Buffer
zw := zip.NewWriter(&buf)
for _, name := range sortedNames(entries) {
w, err := zw.Create(name)
require.NoError(t, err)
_, err = w.Write([]byte(entries[name]))
require.NoError(t, err)
}
require.NoError(t, zw.Close())
return buf.Bytes()
}
// Tar builds a tar of the entries in sorted name order.
func Tar[T ~string | ~[]byte](t testing.TB, entries map[string]T) []byte {
t.Helper()
var buf bytes.Buffer
writeTar(t, &buf, entries)
return buf.Bytes()
}
// TarGz builds a gzipped tar of the entries in sorted name order.
func TarGz[T ~string | ~[]byte](t testing.TB, entries map[string]T) []byte {
t.Helper()
var buf bytes.Buffer
gw := gzip.NewWriter(&buf)
writeTar(t, gw, entries)
require.NoError(t, gw.Close())
return buf.Bytes()
}
// Jar is the smallest jar the java cataloger identifies, a manifest naming the artifact, plus extra.
func Jar(t testing.TB, title, version string, extra map[string][]byte) []byte {
t.Helper()
entries := map[string][]byte{"META-INF/MANIFEST.MF": Manifest(title, version)}
for name, body := range extra {
entries[name] = body
}
return Zip(t, entries)
}
// Manifest is a jar manifest naming the artifact.
func Manifest(title, version string) []byte {
return fmt.Appendf(nil, "Manifest-Version: 1.0\nImplementation-Title: %s\nImplementation-Version: %s\n", title, version)
}
func writeTar[T ~string | ~[]byte](t testing.TB, w io.Writer, entries map[string]T) {
t.Helper()
tw := tar.NewWriter(w)
for _, name := range sortedNames(entries) {
body := []byte(entries[name])
require.NoError(t, tw.WriteHeader(&tar.Header{Name: name, Mode: 0o644, Size: int64(len(body)), Typeflag: tar.TypeReg}))
_, err := tw.Write(body)
require.NoError(t, err)
}
require.NoError(t, tw.Close())
}
func sortedNames[T any](entries map[string]T) []string {
names := make([]string, 0, len(entries))
for name := range entries {
names = append(names, name)
}
sort.Strings(names)
return names
}