@@ -406,8 +406,31 @@ func (p *v2Puller) pullSchema2(ctx context.Context, ref reference.Named, mfst *s
406406 descriptors = append (descriptors , layerDescriptor )
407407 }
408408
409- rootFS , release , err := p .config .DownloadManager .Download (ctx , * image .NewRootFS (), descriptors , p .config .ProgressOutput )
409+ var (
410+ configJSON []byte // raw serialized image config
411+ unmarshalledConfig image.Image // deserialized image config
412+ downloadRootFS image.RootFS // rootFS to use for registering layers.
413+ )
414+ if runtime .GOOS == "windows" {
415+ configJSON , unmarshalledConfig , err = receiveConfig (configChan , errChan )
416+ if err != nil {
417+ return "" , "" , err
418+ }
419+ if unmarshalledConfig .RootFS == nil {
420+ return "" , "" , errors .New ("image config has no rootfs section" )
421+ }
422+ downloadRootFS = * unmarshalledConfig .RootFS
423+ downloadRootFS .DiffIDs = []layer.DiffID {}
424+ } else {
425+ downloadRootFS = * image .NewRootFS ()
426+ }
427+
428+ rootFS , release , err := p .config .DownloadManager .Download (ctx , downloadRootFS , descriptors , p .config .ProgressOutput )
410429 if err != nil {
430+ if configJSON != nil {
431+ // Already received the config
432+ return "" , "" , err
433+ }
411434 select {
412435 case err = <- errChan :
413436 return "" , "" , err
@@ -422,23 +445,16 @@ func (p *v2Puller) pullSchema2(ctx context.Context, ref reference.Named, mfst *s
422445 }
423446 defer release ()
424447
425- var configJSON []byte
426- select {
427- case configJSON = <- configChan :
428- case err = <- errChan :
429- return "" , "" , err
430- // Don't need a case for ctx.Done in the select because cancellation
431- // will trigger an error in p.pullSchema2ImageConfig.
448+ if configJSON == nil {
449+ configJSON , unmarshalledConfig , err = receiveConfig (configChan , errChan )
450+ if err != nil {
451+ return "" , "" , err
452+ }
432453 }
433454
434455 // The DiffIDs returned in rootFS MUST match those in the config.
435456 // Otherwise the image config could be referencing layers that aren't
436457 // included in the manifest.
437- var unmarshalledConfig image.Image
438- if err = json .Unmarshal (configJSON , & unmarshalledConfig ); err != nil {
439- return "" , "" , err
440- }
441-
442458 if len (rootFS .DiffIDs ) != len (unmarshalledConfig .RootFS .DiffIDs ) {
443459 return "" , "" , errRootFSMismatch
444460 }
@@ -457,6 +473,21 @@ func (p *v2Puller) pullSchema2(ctx context.Context, ref reference.Named, mfst *s
457473 return imageID , manifestDigest , nil
458474}
459475
476+ func receiveConfig (configChan <- chan []byte , errChan <- chan error ) ([]byte , image.Image , error ) {
477+ select {
478+ case configJSON := <- configChan :
479+ var unmarshalledConfig image.Image
480+ if err := json .Unmarshal (configJSON , & unmarshalledConfig ); err != nil {
481+ return nil , image.Image {}, err
482+ }
483+ return configJSON , unmarshalledConfig , nil
484+ case err := <- errChan :
485+ return nil , image.Image {}, err
486+ // Don't need a case for ctx.Done in the select because cancellation
487+ // will trigger an error in p.pullSchema2ImageConfig.
488+ }
489+ }
490+
460491// pullManifestList handles "manifest lists" which point to various
461492// platform-specifc manifests.
462493func (p * v2Puller ) pullManifestList (ctx context.Context , ref reference.Named , mfstList * manifestlist.DeserializedManifestList ) (imageID image.ID , manifestListDigest digest.Digest , err error ) {
0 commit comments