Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 45 additions & 2 deletions util/contentutil/copy.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,26 @@ import (

"github.com/containerd/containerd/v2/core/content"
"github.com/containerd/containerd/v2/core/images"
cerrdefs "github.com/containerd/errdefs"
"github.com/moby/buildkit/util/resolver/limited"
"github.com/moby/buildkit/util/resolver/retryhandler"
ocispecs "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
)

type CopyInfo struct {
Referrers content.ReferrersProvider
}

type CopyOption func(*CopyInfo) error

func WithReferrers(referrers content.ReferrersProvider) CopyOption {
return func(ci *CopyInfo) error {
ci.Referrers = referrers
return nil
}
}

func Copy(ctx context.Context, ingester content.Ingester, provider content.Provider, desc ocispecs.Descriptor, ref string, logger func([]byte)) error {
ctx = RegisterContentPayloadTypes(ctx)
if _, err := retryhandler.New(limited.FetchHandler(ingester, &localFetcher{provider}, ref), logger)(ctx, desc); err != nil {
Expand Down Expand Up @@ -59,13 +73,27 @@ func (r *rc) Seek(offset int64, whence int) (int64, error) {
}
return r.offset, nil
}
func CopyChain(ctx context.Context, ingester content.Ingester, provider content.Provider, desc ocispecs.Descriptor, opts ...CopyOption) error {
return copyChain(ctx, ingester, provider, desc, &sync.Map{}, opts...)
}

func copyChain(ctx context.Context, ingester content.Ingester, provider content.Provider, desc ocispecs.Descriptor, visited *sync.Map, opts ...CopyOption) error {
ci := &CopyInfo{}
for _, o := range opts {
if err := o(ci); err != nil {
return err
}
}

func CopyChain(ctx context.Context, ingester content.Ingester, provider content.Provider, desc ocispecs.Descriptor) error {
ctx = RegisterContentPayloadTypes(ctx)
var m sync.Mutex
manifestStack := []ocispecs.Descriptor{}

filterHandler := images.HandlerFunc(func(ctx context.Context, desc ocispecs.Descriptor) ([]ocispecs.Descriptor, error) {
if _, ok := visited.Load(desc.Digest); ok {
return nil, images.ErrStopHandler
}
visited.Store(desc.Digest, struct{}{})
switch desc.MediaType {
case images.MediaTypeDockerSchema2Manifest, ocispecs.MediaTypeImageManifest,
images.MediaTypeDockerSchema2ManifestList, ocispecs.MediaTypeImageIndex:
Expand All @@ -88,9 +116,24 @@ func CopyChain(ctx context.Context, ingester content.Ingester, provider content.
}

for i := len(manifestStack) - 1; i >= 0; i-- {
if err := Copy(ctx, ingester, provider, manifestStack[i], "", nil); err != nil {
desc := manifestStack[i]
if err := Copy(ctx, ingester, provider, desc, "", nil); err != nil {
return errors.WithStack(err)
}
if ci.Referrers != nil {
referrers, err := ci.Referrers.Referrers(ctx, desc)
if err != nil {
if errors.Is(err, cerrdefs.ErrNotFound) {
continue
}
return errors.WithStack(err)
}
for _, r := range referrers {
if err := copyChain(ctx, ingester, provider, r, visited, opts...); err != nil {
return errors.WithStack(err)
}
}
}
}

return nil
Expand Down
Loading