@@ -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 ()
571573 }
572- return filepath .Join (workDir , digestHex )
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 )
581+ }
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 {
@@ -588,17 +603,22 @@ func Merge(ctx context.Context, layers []Layer, dest io.Writer, opt MergeOption)
588603 rafsBlobDigests = append (rafsBlobDigests , layers [idx ].Digest .Hex ())
589604 rafsBlobSizes = append (rafsBlobSizes , layers [idx ].ReaderAt .Size ())
590605 }
606+
591607 eg .Go (func (idx int ) func () error {
592608 return func () error {
593609 // 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" )
610+ if err := unpackLayerEntry (idx , EntryBootstrap , getLayerPath (idx , "" )); err != nil {
611+ return err
597612 }
598- defer bootstrap .Close ()
599613
600- if _ , err := UnpackEntry (layers [idx ].ReaderAt , EntryBootstrap , bootstrap ); err != nil {
601- return errors .Wrap (err , "unpack nydus tar" )
614+ if opt .FsVersion == "6" {
615+ if err := unpackLayerEntry (idx , EntryBlobMeta , getLayerPath (idx , ".blob.meta" )); err != nil {
616+ fmt .Printf ("Warning: Failed to extract blob.meta.header for layer %d: %v\n " , idx , err )
617+ }
618+
619+ if err := unpackLayerEntry (idx , EntryBlobMetaHeader , getLayerPath (idx , ".blob.meta.header" )); err != nil {
620+ fmt .Printf ("Warning: Failed to extract blob.meta.header for layer %d: %v\n " , idx , err )
621+ }
602622 }
603623
604624 return nil
@@ -637,13 +657,89 @@ func Merge(ctx context.Context, layers []Layer, dest io.Writer, opt MergeOption)
637657 }
638658 defer bootstrapRa .Close ()
639659
640- files := append ( []File {
660+ files := []File {
641661 {
642662 Name : EntryBootstrap ,
643663 Reader : content .NewReader (bootstrapRa ),
644664 Size : bootstrapRa .Size (),
645665 },
646- }, opt .AppendFiles ... )
666+ }
667+
668+ if opt .FsVersion == "6" {
669+ metaRas := make ([]io.Closer , 0 , len (layers )* 2 )
670+ defer func () {
671+ for _ , closer := range metaRas {
672+ closer .Close ()
673+ }
674+ }()
675+
676+ for idx := range layers {
677+ digestHex := layers [idx ].Digest .Hex ()
678+ blobMetaPath := getLayerPath (idx , ".blob.meta" )
679+ blobMetaHeaderPath := getLayerPath (idx , ".blob.meta.header" )
680+
681+ metaContent , err := os .ReadFile (blobMetaPath )
682+ if err != nil {
683+ return nil , errors .Wrap (err , "read blob.meta" )
684+ }
685+
686+ headerContent , err := os .ReadFile (blobMetaHeaderPath )
687+ if err != nil {
688+ return nil , errors .Wrap (err , "read blob.meta.header" )
689+ }
690+ uncompressedSize := len (metaContent )
691+ alignedUncompressedSize := (uncompressedSize + 4095 ) &^ 4095
692+ totalSize := alignedUncompressedSize + len (headerContent )
693+
694+ if totalSize == 0 {
695+ fmt .Printf ("Warning: blob data for layer %s is empty, skipping\n " , digestHex )
696+ }
697+
698+ assembledFileName := fmt .Sprintf ("%s.blob.meta" , digestHex )
699+ assembledFilePath := filepath .Join (workDir , assembledFileName )
700+
701+ if err := func () error {
702+ f , err := os .Create (assembledFilePath )
703+ if err != nil {
704+ return err
705+ }
706+ defer f .Close ()
707+
708+ if _ , err := f .Write (metaContent ); err != nil {
709+ return err
710+ }
711+
712+ if padding := alignedUncompressedSize - uncompressedSize ; padding > 0 {
713+ if _ , err := f .Write (make ([]byte , padding )); err != nil {
714+ return err
715+ }
716+ }
717+
718+ if _ , err := f .Write (headerContent ); err != nil {
719+ return err
720+ }
721+
722+ return f .Sync ()
723+ }(); err != nil {
724+ return nil , errors .Wrap (err , "write blob meta file" )
725+ }
726+
727+ assembledRa , err := local .OpenReader (assembledFilePath )
728+ if err != nil {
729+ return nil , errors .Wrap (err , "open blob meta file" )
730+ }
731+
732+ metaRas = append (metaRas , assembledRa )
733+
734+ files = append (files , File {
735+ Name : assembledFileName ,
736+ Reader : content .NewReader (assembledRa ),
737+ Size : int64 (totalSize ),
738+ })
739+ }
740+ }
741+
742+ files = append (files , opt .AppendFiles ... )
647743 var rc io.ReadCloser
648744
649745 if opt .WithTar {
@@ -661,7 +757,6 @@ func Merge(ctx context.Context, layers []Layer, dest io.Writer, opt MergeOption)
661757 if _ , err = io .CopyBuffer (dest , rc , * buffer ); err != nil {
662758 return nil , errors .Wrap (err , "copy merged bootstrap" )
663759 }
664-
665760 return blobDigests , nil
666761}
667762
0 commit comments