MCPcopy Create free account
hub / github.com/containers/image / LayerInfosForCopy

Method LayerInfosForCopy

storage/storage_src.go:284–355  ·  view source on GitHub ↗

LayerInfosForCopy() returns the list of layer blobs that make up the root filesystem of the image, after they've been decompressed.

(ctx context.Context, instanceDigest *digest.Digest)

Source from the content-addressed store, hash-verified

282// LayerInfosForCopy() returns the list of layer blobs that make up the root filesystem of
283// the image, after they've been decompressed.
284func (s *storageImageSource) LayerInfosForCopy(ctx context.Context, instanceDigest *digest.Digest) ([]types.BlobInfo, error) {
285 manifestBlob, manifestType, err := s.GetManifest(ctx, instanceDigest)
286 if err != nil {
287 return nil, fmt.Errorf("reading image manifest for %q: %w", s.image.ID, err)
288 }
289 if manifest.MIMETypeIsMultiImage(manifestType) {
290 return nil, errors.New("can't copy layers for a manifest list (shouldn't be attempted)")
291 }
292 man, err := manifest.FromBlob(manifestBlob, manifestType)
293 if err != nil {
294 return nil, fmt.Errorf("parsing image manifest for %q: %w", s.image.ID, err)
295 }
296
297 uncompressedLayerType := ""
298 switch manifestType {
299 case imgspecv1.MediaTypeImageManifest:
300 uncompressedLayerType = imgspecv1.MediaTypeImageLayer
301 case manifest.DockerV2Schema1MediaType, manifest.DockerV2Schema1SignedMediaType, manifest.DockerV2Schema2MediaType:
302 uncompressedLayerType = manifest.DockerV2SchemaLayerMediaTypeUncompressed
303 }
304
305 physicalBlobInfos := []types.BlobInfo{} // Built reversed
306 layerID := s.image.TopLayer
307 for layerID != "" {
308 layer, err := s.imageRef.transport.store.Layer(layerID)
309 if err != nil {
310 return nil, fmt.Errorf("reading layer %q in image %q: %w", layerID, s.image.ID, err)
311 }
312
313 blobDigest := layer.UncompressedDigest
314 if blobDigest == "" {
315 if layer.TOCDigest == "" {
316 return nil, fmt.Errorf("uncompressed digest and TOC digest for layer %q is unknown", layerID)
317 }
318 if layer.Flags == nil || layer.Flags[expectedLayerDiffIDFlag] == nil {
319 return nil, fmt.Errorf("TOC digest %q for layer %q is present but %q flag is not set", layer.TOCDigest, layerID, expectedLayerDiffIDFlag)
320 }
321 expectedDigest, ok := layer.Flags[expectedLayerDiffIDFlag].(string)
322 if !ok {
323 return nil, fmt.Errorf("TOC digest %q for layer %q is present but %q flag is not a string", layer.TOCDigest, layerID, expectedLayerDiffIDFlag)
324 }
325 // If the layer is stored by its TOC, report the expected diffID as the layer Digest;
326 // the generic code is responsible for validating the digest.
327 // We can locate the layer without further c/storage help using s.getBlobMutexProtected.digestToLayerID.
328 blobDigest, err = digest.Parse(expectedDigest)
329 if err != nil {
330 return nil, fmt.Errorf("parsing expected diffID %q for layer %q: %w", expectedDigest, layerID, err)
331 }
332 }
333 size := layer.UncompressedSize
334 if size < 0 {
335 size = -1
336 }
337 s.getBlobMutex.Lock()
338 s.getBlobMutexProtected.digestToLayerID[blobDigest] = layer.ID
339 s.getBlobMutex.Unlock()
340 blobInfo := types.BlobInfo{
341 Digest: blobDigest,

Callers

nothing calls this directly

Calls 5

GetManifestMethod · 0.95
MIMETypeIsMultiImageFunction · 0.92
FromBlobFunction · 0.92
buildLayerInfosForCopyFunction · 0.85
LayerInfosMethod · 0.65

Tested by

no test coverage detected