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 <azr@users.noreply.github.com>
This commit is contained in:
Adrien Delorme 2024-01-19 11:35:52 +01:00
parent 0817c9798f
commit bb9d923aa6
No known key found for this signature in database

View File

@ -17,6 +17,7 @@
package content package content
import ( import (
"bytes"
"context" "context"
"errors" "errors"
"fmt" "fmt"
@ -55,6 +56,31 @@ func NewReader(ra ReaderAt) io.Reader {
return io.NewSectionReader(ra, 0, ra.Size()) 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. // ReadBlob retrieves the entire contents of the blob from the provider.
// //
// Avoid using this for large blobs, such as layers. // Avoid using this for large blobs, such as layers.