From bb9d923aa6ce34b6fa047999f766d851e4df8160 Mon Sep 17 00:00:00 2001 From: Adrien Delorme Date: Fri, 19 Jan 2024 11:35:52 +0100 Subject: [PATCH] content: add a BlobReadSeeker func to allow multipart blob streaming A downstream library (s3) needs a read seeker to be able to do its own multipart upload. See: https://github.com/moby/buildkit/pull/4551 Signed-off-by: Adrien Delorme --- core/content/helpers.go | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/core/content/helpers.go b/core/content/helpers.go index 514127d0a..447f4e544 100644 --- a/core/content/helpers.go +++ b/core/content/helpers.go @@ -17,6 +17,7 @@ package content import ( + "bytes" "context" "errors" "fmt" @@ -55,6 +56,31 @@ func NewReader(ra ReaderAt) io.Reader { return io.NewSectionReader(ra, 0, ra.Size()) } +type nopCloserBytesReader struct { + *bytes.Reader +} + +func (*nopCloserBytesReader) Close() error { return nil } + +type nopCloserSectionReader struct { + *io.SectionReader +} + +func (*nopCloserSectionReader) Close() error { return nil } + +// BlobReadSeeker returns a read seeker for the blob from the provider. +func BlobReadSeeker(ctx context.Context, provider Provider, desc ocispec.Descriptor) (io.ReadSeekCloser, error) { + if int64(len(desc.Data)) == desc.Size && digest.FromBytes(desc.Data) == desc.Digest { + return &nopCloserBytesReader{bytes.NewReader(desc.Data)}, nil + } + + ra, err := provider.ReaderAt(ctx, desc) + if err != nil { + return nil, err + } + return &nopCloserSectionReader{io.NewSectionReader(ra, 0, ra.Size())}, nil +} + // ReadBlob retrieves the entire contents of the blob from the provider. // // Avoid using this for large blobs, such as layers.