imageCopyOpt is a thread safe copy of a manifest and nested content.
(ctx context.Context, refSrc ref.Ref, refTgt ref.Ref, d descriptor.Descriptor, child bool, parents []digest.Digest, opt *imageOpt)
| 560 | |
| 561 | // imageCopyOpt is a thread safe copy of a manifest and nested content. |
| 562 | func (rc *RegClient) imageCopyOpt(ctx context.Context, refSrc ref.Ref, refTgt ref.Ref, d descriptor.Descriptor, child bool, parents []digest.Digest, opt *imageOpt) (err error) { |
| 563 | var mSrc, mTgt manifest.Manifest |
| 564 | var sDig digest.Digest |
| 565 | refTgtRepo := refTgt.SetTag("").CommonName() |
| 566 | seenCB := func(error) {} |
| 567 | defer func() { |
| 568 | if seenCB != nil { |
| 569 | seenCB(err) |
| 570 | } |
| 571 | }() |
| 572 | // if digest is provided and we are already copying it, wait |
| 573 | if d.Digest != "" { |
| 574 | sDig = d.Digest |
| 575 | } else if refSrc.Digest != "" { |
| 576 | sDig = digest.Digest(refSrc.Digest) |
| 577 | } |
| 578 | if sDig != "" { |
| 579 | if seenCB, err = imageSeenOrWait(ctx, opt, refTgtRepo, refTgt.Tag, sDig, parents); seenCB == nil { |
| 580 | return err |
| 581 | } |
| 582 | } |
| 583 | // check target with head request |
| 584 | mTgt, err = rc.ManifestHead(ctx, refTgt, WithManifestRequireDigest()) |
| 585 | var urlError *url.Error |
| 586 | if err != nil && errors.As(err, &urlError) { |
| 587 | return fmt.Errorf("failed to access target registry: %w", err) |
| 588 | } |
| 589 | // for non-recursive copies, compare to source digest |
| 590 | if err == nil && (opt.fastCheck || (!opt.forceRecursive && opt.referrerConfs == nil && !opt.digestTags)) { |
| 591 | if sDig == "" { |
| 592 | mSrc, err = rc.ManifestHead(ctx, refSrc, WithManifestRequireDigest()) |
| 593 | if err != nil { |
| 594 | return fmt.Errorf("copy failed, error getting source: %w", err) |
| 595 | } |
| 596 | sDig = mSrc.GetDescriptor().Digest |
| 597 | if seenCB, err = imageSeenOrWait(ctx, opt, refTgtRepo, refTgt.Tag, sDig, parents); seenCB == nil { |
| 598 | return err |
| 599 | } |
| 600 | } |
| 601 | if sDig == mTgt.GetDescriptor().Digest { |
| 602 | if opt.callback != nil { |
| 603 | opt.callback(types.CallbackManifest, d.Digest.String(), types.CallbackSkipped, mTgt.GetDescriptor().Size, mTgt.GetDescriptor().Size) |
| 604 | } |
| 605 | return nil |
| 606 | } |
| 607 | } |
| 608 | // when copying/updating digest tags or referrers, only the source digest is needed for an image |
| 609 | if mTgt != nil && mSrc == nil && !opt.forceRecursive && sDig == "" { |
| 610 | mSrc, err = rc.ManifestHead(ctx, refSrc, WithManifestRequireDigest()) |
| 611 | if err != nil { |
| 612 | return fmt.Errorf("copy failed, error getting source: %w", err) |
| 613 | } |
| 614 | sDig = mSrc.GetDescriptor().Digest |
| 615 | if seenCB, err = imageSeenOrWait(ctx, opt, refTgtRepo, refTgt.Tag, sDig, parents); seenCB == nil { |
| 616 | return err |
| 617 | } |
| 618 | } |
| 619 | // get the source manifest when a copy is needed or recursion into the content is needed |
no test coverage detected