copyLayers copies layers from ic.src/ic.c.rawSource to dest, using and updating ic.manifestUpdates if necessary and ic.cannotModifyManifestReason == "".
(ctx context.Context)
| 434 | |
| 435 | // copyLayers copies layers from ic.src/ic.c.rawSource to dest, using and updating ic.manifestUpdates if necessary and ic.cannotModifyManifestReason == "". |
| 436 | func (ic *imageCopier) copyLayers(ctx context.Context) ([]compressiontypes.Algorithm, error) { |
| 437 | srcInfos := ic.src.LayerInfos() |
| 438 | updatedSrcInfos, err := ic.src.LayerInfosForCopy(ctx) |
| 439 | if err != nil { |
| 440 | return nil, err |
| 441 | } |
| 442 | srcInfosUpdated := false |
| 443 | if updatedSrcInfos != nil && !reflect.DeepEqual(srcInfos, updatedSrcInfos) { |
| 444 | if ic.cannotModifyManifestReason != "" { |
| 445 | return nil, fmt.Errorf("Copying this image would require changing layer representation, which we cannot do: %q", ic.cannotModifyManifestReason) |
| 446 | } |
| 447 | srcInfos = updatedSrcInfos |
| 448 | srcInfosUpdated = true |
| 449 | } |
| 450 | |
| 451 | type copyLayerData struct { |
| 452 | destInfo types.BlobInfo |
| 453 | diffID digest.Digest |
| 454 | err error |
| 455 | } |
| 456 | |
| 457 | // The manifest is used to extract the information whether a given |
| 458 | // layer is empty. |
| 459 | man, err := manifest.FromBlob(ic.src.ManifestBlob, ic.src.ManifestMIMEType) |
| 460 | if err != nil { |
| 461 | return nil, err |
| 462 | } |
| 463 | manifestLayerInfos := man.LayerInfos() |
| 464 | |
| 465 | // copyGroup is used to determine if all layers are copied |
| 466 | copyGroup := sync.WaitGroup{} |
| 467 | |
| 468 | data := make([]copyLayerData, len(srcInfos)) |
| 469 | copyLayerHelper := func(index int, srcLayer types.BlobInfo, toEncrypt bool, pool *mpb.Progress, srcRef reference.Named) { |
| 470 | defer ic.c.concurrentBlobCopiesSemaphore.Release(1) |
| 471 | defer copyGroup.Done() |
| 472 | cld := copyLayerData{} |
| 473 | if !ic.c.options.DownloadForeignLayers && ic.c.dest.AcceptsForeignLayerURLs() && len(srcLayer.URLs) != 0 { |
| 474 | // DiffIDs are, currently, needed only when converting from schema1. |
| 475 | // In which case src.LayerInfos will not have URLs because schema1 |
| 476 | // does not support them. |
| 477 | if ic.diffIDsAreNeeded { |
| 478 | cld.err = errors.New("getting DiffID for foreign layers is unimplemented") |
| 479 | } else { |
| 480 | cld.destInfo = srcLayer |
| 481 | logrus.Debugf("Skipping foreign layer %q copy to %s", cld.destInfo.Digest, ic.c.dest.Reference().Transport().Name()) |
| 482 | } |
| 483 | } else { |
| 484 | cld.destInfo, cld.diffID, cld.err = ic.copyLayer(ctx, srcLayer, toEncrypt, pool, index, srcRef, manifestLayerInfos[index].EmptyLayer) |
| 485 | } |
| 486 | data[index] = cld |
| 487 | } |
| 488 | |
| 489 | // Decide which layers to encrypt |
| 490 | layersToEncrypt := set.New[int]() |
| 491 | if ic.c.options.OciEncryptLayers != nil { |
| 492 | totalLayers := len(srcInfos) |
| 493 | for _, l := range *ic.c.options.OciEncryptLayers { |
no test coverage detected