copyLayer copies a layer with srcInfo (with known Digest and Annotations and possibly known Size) in src to dest, perhaps (de/re/)compressing it, and returns a complete blobInfo of the copied layer, and a value for LayerDiffIDs if diffIDIsNeeded srcRef can be used as an additional hint to the destin
(ctx context.Context, srcInfo types.BlobInfo, toEncrypt bool, pool *mpb.Progress, layerIndex int, srcRef reference.Named, emptyLayer bool)
| 694 | // and returns a complete blobInfo of the copied layer, and a value for LayerDiffIDs if diffIDIsNeeded |
| 695 | // srcRef can be used as an additional hint to the destination during checking whether a layer can be reused but srcRef can be nil. |
| 696 | func (ic *imageCopier) copyLayer(ctx context.Context, srcInfo types.BlobInfo, toEncrypt bool, pool *mpb.Progress, layerIndex int, srcRef reference.Named, emptyLayer bool) (types.BlobInfo, digest.Digest, error) { |
| 697 | // If the srcInfo doesn't contain compression information, try to compute it from the |
| 698 | // MediaType, which was either read from a manifest by way of LayerInfos() or constructed |
| 699 | // by LayerInfosForCopy(), if it was supplied at all. If we succeed in copying the blob, |
| 700 | // the BlobInfo we return will be passed to UpdatedImage() and then to UpdateLayerInfos(), |
| 701 | // which uses the compression information to compute the updated MediaType values. |
| 702 | // (Sadly UpdatedImage() is documented to not update MediaTypes from |
| 703 | // ManifestUpdateOptions.LayerInfos[].MediaType, so we are doing it indirectly.) |
| 704 | if srcInfo.CompressionOperation == types.PreserveOriginal && srcInfo.CompressionAlgorithm == nil { |
| 705 | op, algo, err := compressionEditsFromBlobInfo(srcInfo) |
| 706 | if err != nil { |
| 707 | return types.BlobInfo{}, "", err |
| 708 | } |
| 709 | srcInfo.CompressionOperation = op |
| 710 | srcInfo.CompressionAlgorithm = algo |
| 711 | } |
| 712 | |
| 713 | ic.c.printCopyInfo("blob", srcInfo) |
| 714 | |
| 715 | diffIDIsNeeded := false |
| 716 | var cachedDiffID digest.Digest = "" |
| 717 | if ic.diffIDsAreNeeded { |
| 718 | cachedDiffID = ic.c.blobInfoCache.UncompressedDigest(srcInfo.Digest) // May be "" |
| 719 | diffIDIsNeeded = cachedDiffID == "" |
| 720 | } |
| 721 | // When encrypting to decrypting, only use the simple code path. We might be able to optimize more |
| 722 | // (e.g. if we know the DiffID of an encrypted compressed layer, it might not be necessary to pull, decrypt and decompress again), |
| 723 | // but it’s not trivially safe to do such things, so until someone takes the effort to make a comprehensive argument, let’s not. |
| 724 | encryptingOrDecrypting := toEncrypt || (isOciEncrypted(srcInfo.MediaType) && ic.c.options.OciDecryptConfig != nil) |
| 725 | canAvoidProcessingCompleteLayer := !diffIDIsNeeded && !encryptingOrDecrypting |
| 726 | |
| 727 | // Don’t read the layer from the source if we already have the blob, and optimizations are acceptable. |
| 728 | if canAvoidProcessingCompleteLayer { |
| 729 | canChangeLayerCompression := ic.src.CanChangeLayerCompression(srcInfo.MediaType) |
| 730 | logrus.Debugf("Checking if we can reuse blob %s: general substitution = %v, compression for MIME type %q = %v", |
| 731 | srcInfo.Digest, ic.canSubstituteBlobs, srcInfo.MediaType, canChangeLayerCompression) |
| 732 | canSubstitute := ic.canSubstituteBlobs && canChangeLayerCompression |
| 733 | |
| 734 | var requiredCompression *compressiontypes.Algorithm |
| 735 | if ic.requireCompressionFormatMatch { |
| 736 | requiredCompression = ic.compressionFormat |
| 737 | } |
| 738 | |
| 739 | var tocDigest digest.Digest |
| 740 | |
| 741 | // Check if we have a chunked layer in storage that's based on that blob. These layers are stored by their TOC digest. |
| 742 | d, err := chunkedToc.GetTOCDigest(srcInfo.Annotations) |
| 743 | if err != nil { |
| 744 | return types.BlobInfo{}, "", err |
| 745 | } |
| 746 | if d != nil { |
| 747 | tocDigest = *d |
| 748 | } |
| 749 | |
| 750 | reused, reusedBlob, err := ic.c.dest.TryReusingBlobWithOptions(ctx, srcInfo, private.TryReusingBlobOptions{ |
| 751 | Cache: ic.c.blobInfoCache, |
| 752 | CanSubstitute: canSubstitute, |
| 753 | EmptyLayer: emptyLayer, |
no test coverage detected