func LayerConvertFunc(opts ...estargz.Option) converter.ConvertFunc {
	return func(ctx context.Context, cs content.Store, desc ocispec.Descriptor) (*ocispec.Descriptor, error) {
		if !images.IsLayerType(desc.MediaType) {
			// No conversion. No need to return an error here.
			return nil, nil
		}
		info, err := cs.Info(ctx, desc.Digest)
		if err != nil {
			return nil, err
		}
		labelz := info.Labels
		if labelz == nil {
			labelz = make(map[string]string)
		}

		ra, err := cs.ReaderAt(ctx, desc)
		if err != nil {
			return nil, err
		}
		defer ra.Close()
		sr := io.NewSectionReader(ra, 0, desc.Size)
		blob, err := estargz.Build(sr, opts...)
		if err != nil {
			return nil, err
		}
		defer blob.Close()
		ref := fmt.Sprintf("convert-estargz-from-%s", desc.Digest)
		w, err := content.OpenWriter(ctx, cs, content.WithRef(ref))
		if err != nil {
			return nil, err
		}
		defer w.Close()

		// Reset the writing position
		// Old writer possibly remains without aborted
		// (e.g. conversion interrupted by a signal)
		if err := w.Truncate(0); err != nil {
			return nil, err
		}

		// Copy and count the contents
		pr, pw := io.Pipe()
		c := new(counter)
		doneCount := make(chan struct{})
		go func() {
			defer close(doneCount)
			defer pr.Close()
			decompressR, err := compression.DecompressStream(pr)
			if err != nil {
				pr.CloseWithError(err)
				return
			}
			defer decompressR.Close()
			if _, err := io.Copy(c, decompressR); err != nil {
				pr.CloseWithError(err)
				return
			}
		}()
		n, err := io.Copy(w, io.TeeReader(blob, pw))
		if err != nil {
			return nil, err
		}
		if err := blob.Close(); err != nil {
			return nil, err
		}
		if err := pw.Close(); err != nil {
			return nil, err
		}
		<-doneCount

		// update diffID label
		labelz[labels.LabelUncompressed] = blob.DiffID().String()
		if err = w.Commit(ctx, n, "", content.WithLabels(labelz)); err != nil && !errdefs.IsAlreadyExists(err) {
			return nil, err
		}
		if err := w.Close(); err != nil {
			return nil, err
		}
		newDesc := desc
		if uncompress.IsUncompressedType(newDesc.MediaType) {
			if images.IsDockerType(newDesc.MediaType) {
				newDesc.MediaType += ".gzip"
			} else {
				newDesc.MediaType += "+gzip"
			}
		}
		newDesc.Digest = w.Digest()
		newDesc.Size = n
		if newDesc.Annotations == nil {
			newDesc.Annotations = make(map[string]string, 1)
		}
		newDesc.Annotations[estargz.TOCJSONDigestAnnotation] = blob.TOCDigest().String()
		newDesc.Annotations[estargz.StoreUncompressedSizeAnnotation] = fmt.Sprintf("%d", c.size())
		return &newDesc, nil
	}
}
// LayerConvertFunc converts legacy tar.gz layers into eStargz tar.gz layers.
// Media type is unchanged.
//
// Should be used in conjunction with WithDockerToOCI().
//
// Otherwise "containerd.io/snapshot/stargz/toc.digest" annotation will be lost,
// because the Docker media type does not support layer annotations.
LayerConvertFunc converts legacy tar.gz layers into eStargz tar.gz layers.
Media type is unchanged.

Should be used in conjunction with WithDockerToOCI().

Otherwise "containerd.io/snapshot/stargz/toc.digest" annotation will be lost,
because the Docker media type does not support layer annotations.
// LayerConvertFunc converts legacy tar . gz layers into eStargz tar . gz layers . // Media type is unchanged . // // Should be used in conjunction with WithDockerToOCI () . // // Otherwise " containerd . io / snapshot / stargz / toc . digest " annotation will be lost // because the Docker media type does not support layer annotations .
func LayerConvertFunc(opts ...estargz.Option) converter.ConvertFunc {
	return func(ctx context.Context, cs content.Store, desc ocispec.Descriptor) (*ocispec.Descriptor, error) {
		if !images.IsLayerType(desc.MediaType) {
			return nil, nil
		}
		info, err := cs.Info(ctx, desc.Digest)
		if err != nil {
			return nil, err
		}
		labelz := info.Labels
		if labelz == nil {
			labelz = make(map[string]string)
		}
		ra, err := cs.ReaderAt(ctx, desc)
		if err != nil {
			return nil, err
		}
		defer ra.Close()
		sr := io.NewSectionReader(ra, 0, desc.Size)
		blob, err := estargz.Build(sr, opts...)
		if err != nil {
			return nil, err
		}
		defer blob.Close()
		ref := fmt.Sprintf("convert-estargz-from-%s", desc.Digest)
		w, err := content.OpenWriter(ctx, cs, content.WithRef(ref))
		if err != nil {
			return nil, err
		}
		defer w.Close()
		if err := w.Truncate(0); err != nil {
			return nil, err
		}
		pr, pw := io.Pipe()
		c := new(counter)
		doneCount := make(chan struct{})
		go func() {
			defer close(doneCount)
			defer pr.Close()
			decompressR, err := compression.DecompressStream(pr)
			if err != nil {
				pr.CloseWithError(err)
				return
			}
			defer decompressR.Close()
			if _, err := io.Copy(c, decompressR); err != nil {
				pr.CloseWithError(err)
				return
			}
		}()
		n, err := io.Copy(w, io.TeeReader(blob, pw))
		if err != nil {
			return nil, err
		}
		if err := blob.Close(); err != nil {
			return nil, err
		}
		if err := pw.Close(); err != nil {
			return nil, err
		}
		<-doneCount
		labelz[labels.LabelUncompressed] = blob.DiffID().String()
		if err = w.Commit(ctx, n, "", content.WithLabels(labelz)); err != nil && !errdefs.IsAlreadyExists(err) {
			return nil, err
		}
		if err := w.Close(); err != nil {
			return nil, err
		}
		newDesc := desc
		if uncompress.IsUncompressedType(newDesc.MediaType) {
			if images.IsDockerType(newDesc.MediaType) {
				newDesc.MediaType += ".gzip"
			} else {
				newDesc.MediaType += "+gzip"
			}
		}
		newDesc.Digest = w.Digest()
		newDesc.Size = n
		if newDesc.Annotations == nil {
			newDesc.Annotations = make(map[string]string, 1)
		}
		newDesc.Annotations[estargz.TOCJSONDigestAnnotation] = blob.TOCDigest().String()
		newDesc.Annotations[estargz.StoreUncompressedSizeAnnotation] = fmt.Sprintf("%d", c.size())
		return &newDesc, nil
	}
}
func LayerConvertFunc ( opts ... estargz . Option ) converter . ConvertFunc { return func ( ctx context . Context , cs content . Store , desc ocispec . Descriptor ) ( * ocispec . Descriptor , error ) { if ! images . IsLayerType ( desc . MediaType ) { return nil , nil } info , err := cs . Info ( ctx , desc . Digest ) if err != nil { return nil , err } labelz := info . Labels if labelz == nil { labelz = make ( map [ string ] string ) } ra , err := cs . ReaderAt ( ctx , desc ) if err != nil { return nil , err } defer ra . Close ( ) sr := io . NewSectionReader ( ra , 0 , desc . Size ) blob , err := estargz . Build ( sr , opts ... ) if err != nil { return nil , err } defer blob . Close ( ) ref := fmt . Sprintf ( " " , desc . Digest ) w , err := content . OpenWriter ( ctx , cs , content . WithRef ( ref ) ) if err != nil { return nil , err } defer w . Close ( ) if err := w . Truncate ( 0 ) ; err != nil { return nil , err } pr , pw := io . Pipe ( ) c := new ( counter ) doneCount := make ( chan struct { } ) go func ( ) { defer close ( doneCount ) defer pr . Close ( ) decompressR , err := compression . DecompressStream ( pr ) if err != nil { pr . CloseWithError ( err ) return } defer decompressR . Close ( ) if _ , err := io . Copy ( c , decompressR ) ; err != nil { pr . CloseWithError ( err ) return } } ( ) n , err := io . Copy ( w , io . TeeReader ( blob , pw ) ) if err != nil { return nil , err } if err := blob . Close ( ) ; err != nil { return nil , err } if err := pw . Close ( ) ; err != nil { return nil , err } <- doneCount labelz [ labels . LabelUncompressed ] = blob . DiffID ( ) . String ( ) if err = w . Commit ( ctx , n , " " , content . WithLabels ( labelz ) ) ; err != nil && ! errdefs . IsAlreadyExists ( err ) { return nil , err } if err := w . Close ( ) ; err != nil { return nil , err } newDesc := desc if uncompress . IsUncompressedType ( newDesc . MediaType ) { if images . IsDockerType ( newDesc . MediaType ) { newDesc . MediaType += " " } else { newDesc . MediaType += " " } } newDesc . Digest = w . Digest ( ) newDesc . Size = n if newDesc . Annotations == nil { newDesc . Annotations = make ( map [ string ] string , 1 ) } newDesc . Annotations [ estargz . TOCJSONDigestAnnotation ] = blob . TOCDigest ( ) . String ( ) newDesc . Annotations [ estargz . StoreUncompressedSizeAnnotation ] = fmt . Sprintf ( " " , c . size ( ) ) return & newDesc , nil } }
LayerConvertFunc converts legacy tar.gz layers into eStargz tar.gz layers.
LayerConvertFunc converts legacy tar . gz layers into eStargz tar . gz layers .
// No conversion. No need to return an error here. // Reset the writing position // Old writer possibly remains without aborted // (e.g. conversion interrupted by a signal) // Copy and count the contents // update diffID label