diff --git a/pkg/artifact/layer.go b/pkg/artifact/layer.go index c2becb5..0ae46dc 100644 --- a/pkg/artifact/layer.go +++ b/pkg/artifact/layer.go @@ -2,11 +2,10 @@ package artifact import ( "bytes" - "fmt" + "io" + v1 "github.com/google/go-containerregistry/pkg/v1" - "github.com/google/go-containerregistry/pkg/v1/partial" "github.com/google/go-containerregistry/pkg/v1/types" - "io" ) type Layer = v1.Layer @@ -43,26 +42,6 @@ func (a *artifact) Uncompressed() (io.ReadCloser, error) { return a.uncompressed() } -func Gzipped(l Layer) (Layer, error) { - gziped, err := partial.UncompressedToLayer(l) - if err != nil { - return gziped, nil - } - return &compressed{Layer: l}, nil -} - -type compressed struct { - Layer -} - -func (a *compressed) MediaType() (types.MediaType, error) { - m, err := a.Layer.MediaType() - if err != nil { - return "", err - } - return types.MediaType(fmt.Sprintf("%s+gzip", m)), nil -} - func WithDescriptor(l Layer, descriptor v1.Descriptor) Layer { return &artifactWithDescriptor{ desc: descriptor, diff --git a/pkg/artifact/layer__compressed.go b/pkg/artifact/layer__compressed.go new file mode 100644 index 0000000..681b3f5 --- /dev/null +++ b/pkg/artifact/layer__compressed.go @@ -0,0 +1,63 @@ +package artifact + +import ( + "fmt" + "io" + "sync" + + containerregistryv1 "github.com/google/go-containerregistry/pkg/v1" + "github.com/google/go-containerregistry/pkg/v1/partial" + "github.com/google/go-containerregistry/pkg/v1/types" +) + +func Gzipped(l Layer) (Layer, error) { + return &compressedLayerWithoutDiff{Layer: l}, nil +} + +type compressedLayerWithoutDiff struct { + Layer + + once sync.Once + hash containerregistryv1.Hash + size int64 + hashSizeError error +} + +func (a *compressedLayerWithoutDiff) MediaType() (types.MediaType, error) { + m, err := a.Layer.MediaType() + if err != nil { + return "", err + } + return types.MediaType(fmt.Sprintf("%s+gzip", m)), nil +} + +func (ule *compressedLayerWithoutDiff) Compressed() (io.ReadCloser, error) { + u, err := partial.UncompressedToLayer(ule.Layer) + if err != nil { + return nil, err + } + return u.Compressed() +} + +func (ule *compressedLayerWithoutDiff) Digest() (containerregistryv1.Hash, error) { + ule.calcSizeHash() + return ule.hash, ule.hashSizeError +} + +// Size implements v1.Layer +func (ule *compressedLayerWithoutDiff) Size() (int64, error) { + ule.calcSizeHash() + return ule.size, ule.hashSizeError +} + +func (ule *compressedLayerWithoutDiff) calcSizeHash() { + ule.once.Do(func() { + var r io.ReadCloser + r, ule.hashSizeError = ule.Compressed() + if ule.hashSizeError != nil { + return + } + defer r.Close() + ule.hash, ule.size, ule.hashSizeError = containerregistryv1.SHA256(r) + }) +} diff --git a/pkg/artifact/layer__uncompressed.go b/pkg/artifact/layer__uncompressed.go index 5395a41..647ad1c 100644 --- a/pkg/artifact/layer__uncompressed.go +++ b/pkg/artifact/layer__uncompressed.go @@ -4,52 +4,43 @@ import ( "io" "sync" - v1 "github.com/google/go-containerregistry/pkg/v1" + containerregistryv1 "github.com/google/go-containerregistry/pkg/v1" "github.com/google/go-containerregistry/pkg/v1/types" ) type UncompressedLayer interface { MediaType() (types.MediaType, error) - Uncompressed() (io.ReadCloser, error) } -func NonCompressedLayer(u UncompressedLayer) v1.Layer { - return &nonCompressedLayer{ +func NonCompressedLayer(u UncompressedLayer) containerregistryv1.Layer { + return &uncompressedLayer{ UncompressedLayer: u, } } -type nonCompressedLayer struct { +type uncompressedLayer struct { UncompressedLayer hashSizeError error - hash v1.Hash + hash containerregistryv1.Hash size int64 once sync.Once } -func (a *nonCompressedLayer) DiffID() (v1.Hash, error) { +func (a *uncompressedLayer) DiffID() (containerregistryv1.Hash, error) { a.calcSizeHash() return a.hash, a.hashSizeError } -func (a *nonCompressedLayer) Size() (int64, error) { +func (a *uncompressedLayer) Size() (int64, error) { a.calcSizeHash() return a.size, a.hashSizeError } -func (a *nonCompressedLayer) Digest() (v1.Hash, error) { - return a.DiffID() -} - -func (a *nonCompressedLayer) Compressed() (io.ReadCloser, error) { - return a.Uncompressed() -} - -func (a *nonCompressedLayer) calcSizeHash() { +func (a *uncompressedLayer) calcSizeHash() { a.once.Do(func() { r, err := a.Uncompressed() if err != nil { @@ -57,6 +48,14 @@ func (a *nonCompressedLayer) calcSizeHash() { return } defer r.Close() - a.hash, a.size, a.hashSizeError = v1.SHA256(r) + a.hash, a.size, a.hashSizeError = containerregistryv1.SHA256(r) }) } + +func (a *uncompressedLayer) Digest() (containerregistryv1.Hash, error) { + return a.DiffID() +} + +func (a *uncompressedLayer) Compressed() (io.ReadCloser, error) { + return a.Uncompressed() +}