@@ -564,12 +564,27 @@ func Merge(ctx context.Context, layers []Layer, dest io.Writer, opt MergeOption)
564564 }
565565 defer os .RemoveAll (workDir )
566566
567- getBootstrapPath := func (layerIdx int ) string {
568- digestHex := layers [layerIdx ].Digest .Hex ()
569- if originalDigest := layers [layerIdx ].OriginalDigest ; originalDigest != nil {
570- return filepath .Join (workDir , originalDigest .Hex ())
567+ getLayerPath := func (layerIdx int , suffix string ) string {
568+ var digestHex string
569+ if suffix == "" && layers [layerIdx ].OriginalDigest != nil {
570+ digestHex = layers [layerIdx ].OriginalDigest .Hex ()
571+ } else {
572+ digestHex = layers [layerIdx ].Digest .Hex ()
573+ }
574+ return filepath .Join (workDir , digestHex + suffix )
575+ }
576+
577+ unpackLayerEntry := func (layerIdx int , entryName string , filePath string ) error {
578+ file , err := os .Create (filePath )
579+ if err != nil {
580+ return errors .Wrapf (err , "create %s file" , entryName )
571581 }
572- return filepath .Join (workDir , digestHex )
582+ defer file .Close ()
583+
584+ if _ , err := UnpackEntry (layers [layerIdx ].ReaderAt , entryName , file ); err != nil {
585+ return errors .Wrapf (err , "unpack %s" , entryName )
586+ }
587+ return nil
573588 }
574589
575590 eg , _ := errgroup .WithContext (ctx )
@@ -578,7 +593,7 @@ func Merge(ctx context.Context, layers []Layer, dest io.Writer, opt MergeOption)
578593 rafsBlobSizes := []int64 {}
579594 rafsBlobTOCDigests := []string {}
580595 for idx := range layers {
581- sourceBootstrapPaths = append (sourceBootstrapPaths , getBootstrapPath (idx ))
596+ sourceBootstrapPaths = append (sourceBootstrapPaths , getLayerPath (idx , "" ))
582597 if layers [idx ].OriginalDigest != nil {
583598 rafsBlobTOCDigest , err := calcBlobTOCDigest (layers [idx ].ReaderAt )
584599 if err != nil {
@@ -591,14 +606,18 @@ func Merge(ctx context.Context, layers []Layer, dest io.Writer, opt MergeOption)
591606 eg .Go (func (idx int ) func () error {
592607 return func () error {
593608 // Use the hex hash string of whole tar blob as the bootstrap name.
594- bootstrap , err := os .Create (getBootstrapPath (idx ))
595- if err != nil {
596- return errors .Wrap (err , "create source bootstrap" )
609+ if err := unpackLayerEntry (idx , EntryBootstrap , getLayerPath (idx , "" )); err != nil {
610+ return err
597611 }
598- defer bootstrap .Close ()
599612
600- if _ , err := UnpackEntry (layers [idx ].ReaderAt , EntryBootstrap , bootstrap ); err != nil {
601- return errors .Wrap (err , "unpack nydus tar" )
613+ if opt .FsVersion == "6" {
614+ if err := unpackLayerEntry (idx , EntryBlobMeta , getLayerPath (idx , ".blob.meta" )); err != nil {
615+ return err
616+ }
617+
618+ if err := unpackLayerEntry (idx , EntryBlobMetaHeader , getLayerPath (idx , ".blob.meta.header" )); err != nil {
619+ return err
620+ }
602621 }
603622
604623 return nil
@@ -637,13 +656,74 @@ func Merge(ctx context.Context, layers []Layer, dest io.Writer, opt MergeOption)
637656 }
638657 defer bootstrapRa .Close ()
639658
640- files := append ( []File {
659+ files := []File {
641660 {
642661 Name : EntryBootstrap ,
643662 Reader : content .NewReader (bootstrapRa ),
644663 Size : bootstrapRa .Size (),
645664 },
646- }, opt .AppendFiles ... )
665+ }
666+
667+ if opt .FsVersion == "6" {
668+ metaRas := make ([]io.Closer , 0 , len (layers )* 2 )
669+ defer func () {
670+ for _ , closer := range metaRas {
671+ closer .Close ()
672+ }
673+ }()
674+
675+ for idx := range layers {
676+ digestHex := layers [idx ].Digest .Hex ()
677+ blobMetaPath := getLayerPath (idx , ".blob.meta" )
678+ blobMetaHeaderPath := getLayerPath (idx , ".blob.meta.header" )
679+ _ , err := os .Stat (blobMetaPath )
680+ if err != nil {
681+ return nil , errors .Wrap (err , "check blob.meta existence" )
682+ }
683+
684+ _ , err = os .Stat (blobMetaHeaderPath )
685+ if err != nil {
686+ return nil , errors .Wrap (err , "check blob.meta.header existence" )
687+ }
688+
689+ metaContent , err := os .ReadFile (blobMetaPath )
690+ if err != nil {
691+ return nil , errors .Wrap (err , "read blob.meta" )
692+ }
693+
694+ headerContent , err := os .ReadFile (blobMetaHeaderPath )
695+ if err != nil {
696+ return nil , errors .Wrap (err , "read blob.meta.header" )
697+ }
698+
699+ uncompressedSize := len (metaContent )
700+ alignedUncompressedSize := (uncompressedSize + 4095 ) &^ 4095
701+ totalSize := alignedUncompressedSize + len (headerContent )
702+ assembledBuffer := make ([]byte , totalSize )
703+
704+ copy (assembledBuffer [0 :uncompressedSize ], metaContent )
705+ copy (assembledBuffer [alignedUncompressedSize :alignedUncompressedSize + len (headerContent )], headerContent )
706+ assembledFileName := fmt .Sprintf ("%s.blob.meta" , digestHex )
707+ assembledFilePath := filepath .Join (workDir , assembledFileName )
708+ if err := os .WriteFile (assembledFilePath , assembledBuffer , 0644 ); err != nil {
709+ return nil , errors .Wrap (err , "write assembled meta file" )
710+ }
711+
712+ assembledRa , err := local .OpenReader (assembledFilePath )
713+ if err != nil {
714+ return nil , errors .Wrap (err , "open assembled meta file" )
715+ }
716+ metaRas = append (metaRas , assembledRa )
717+
718+ files = append (files , File {
719+ Name : assembledFileName ,
720+ Reader : content .NewReader (assembledRa ),
721+ Size : int64 (totalSize ),
722+ })
723+ }
724+ }
725+
726+ files = append (files , opt .AppendFiles ... )
647727 var rc io.ReadCloser
648728
649729 if opt .WithTar {
@@ -661,7 +741,6 @@ func Merge(ctx context.Context, layers []Layer, dest io.Writer, opt MergeOption)
661741 if _ , err = io .CopyBuffer (dest , rc , * buffer ); err != nil {
662742 return nil , errors .Wrap (err , "copy merged bootstrap" )
663743 }
664-
665744 return blobDigests , nil
666745}
667746
0 commit comments