func (is *tarballImageSource) HasThreadSafeGetBlob() bool {
	return false
}
HasThreadSafeGetBlob indicates whether GetBlob can be executed concurrently.
package tarball
import (
	"bytes"
	"context"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"runtime"
	"strings"
	"time"
	"github.com/containers/image/v5/types"
	"github.com/klauspost/pgzip"
	digest "github.com/opencontainers/go-digest"
	imgspecs "github.com/opencontainers/image-spec/specs-go"
	imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1"
)
type tarballImageSource struct {
	reference  tarballReference
	filenames  []string
	diffIDs    []digest.Digest
	diffSizes  []int64
	blobIDs    []digest.Digest
	blobSizes  []int64
	blobTypes  []string
	config     []byte
	configID   digest.Digest
	configSize int64
	manifest   []byte
}
func (r *tarballReference) NewImageSource(ctx context.Context, sys *types.SystemContext) (types.ImageSource, error) {
	filenames := []string{}
	diffIDs := []digest.Digest{}
	diffSizes := []int64{}
	blobIDs := []digest.Digest{}
	blobSizes := []int64{}
	blobTimes := []time.Time{}
	blobTypes := []string{}
	for _, filename := range r.filenames {
		var file *os.File
		var err error
		var blobSize int64
		var blobTime time.Time
		var reader io.Reader
		if filename == "-" {
			blobSize = int64(len(r.stdin))
			blobTime = time.Now()
			reader = bytes.NewReader(r.stdin)
		} else {
			file, err = os.Open(filename)
			if err != nil {
				return nil, fmt.Errorf("error opening %q for reading: %v", filename, err)
			}
			defer file.Close()
			reader = file
			fileinfo, err := file.Stat()
			if err != nil {
				return nil, fmt.Errorf("error reading size of %q: %v", filename, err)
			}
			blobSize = fileinfo.Size()
			blobTime = fileinfo.ModTime()
		}
		layerType := imgspecv1.MediaTypeImageLayerGzip
		blobIDdigester := digest.Canonical.Digester()
		reader = io.TeeReader(reader, blobIDdigester.Hash())
		diffIDdigester := digest.Canonical.Digester()
		uncompressed, err := pgzip.NewReader(reader)
		if err == nil {
			reader = io.TeeReader(uncompressed, diffIDdigester.Hash())
		} else {
			diffIDdigester = blobIDdigester
			layerType = imgspecv1.MediaTypeImageLayer
			uncompressed = nil
		}
		n, err := io.Copy(ioutil.Discard, reader)
		if err != nil {
			return nil, fmt.Errorf("error reading %q: %v", filename, err)
		}
		if uncompressed != nil {
			uncompressed.Close()
		}
		filenames = append(filenames, filename)
		diffIDs = append(diffIDs, diffIDdigester.Digest())
		diffSizes = append(diffSizes, n)
		blobIDs = append(blobIDs, blobIDdigester.Digest())
		blobSizes = append(blobSizes, blobSize)
		blobTimes = append(blobTimes, blobTime)
		blobTypes = append(blobTypes, layerType)
	}
	rootfs := imgspecv1.RootFS{
		Type:    "layers",
		DiffIDs: diffIDs,
	}
	created := time.Time{}
	history := []imgspecv1.History{}
	comment := "imported from tarball"
	if len(r.config.History) > 0 && r.config.History[0].Comment != "" {
		comment = r.config.History[0].Comment
	}
	for i := range diffIDs {
		createdBy := fmt.Sprintf("/bin/sh -c #(nop) ADD file:%s in %c", diffIDs[i].Hex(), os.PathSeparator)
		history = append(history, imgspecv1.History{
			Created:   &blobTimes[i],
			CreatedBy: createdBy,
			Comment:   comment,
		})
		if created.Before(blobTimes[i]) {
			created = blobTimes[i]
		}
	}
	config := r.config
	if config.Created == nil {
		config.Created = &created
	}
	if config.Architecture == "" {
		config.Architecture = runtime.GOARCH
	}
	if config.OS == "" {
		config.OS = runtime.GOOS
	}
	config.RootFS = rootfs
	config.History = history
	configBytes, err := json.Marshal(&config)
	if err != nil {
		return nil, fmt.Errorf("error generating configuration blob for %q: %v", strings.Join(r.filenames, separator), err)
	}
	configID := digest.Canonical.FromBytes(configBytes)
	configSize := int64(len(configBytes))
	layerDescriptors := []imgspecv1.Descriptor{}
	for i := range blobIDs {
		layerDescriptors = append(layerDescriptors, imgspecv1.Descriptor{
			Digest:    blobIDs[i],
			Size:      blobSizes[i],
			MediaType: blobTypes[i],
		})
	}
	annotations := make(map[string]string)
	for k, v := range r.annotations {
		annotations[k] = v
	}
	manifest := imgspecv1.Manifest{
		Versioned: imgspecs.Versioned{
			SchemaVersion: 2,
		},
		Config: imgspecv1.Descriptor{
			Digest:    configID,
			Size:      configSize,
			MediaType: imgspecv1.MediaTypeImageConfig,
		},
		Layers:      layerDescriptors,
		Annotations: annotations,
	}
	manifestBytes, err := json.Marshal(&manifest)
	if err != nil {
		return nil, fmt.Errorf("error generating manifest for %q: %v", strings.Join(r.filenames, separator), err)
	}
	src := &tarballImageSource{
		reference:  *r,
		filenames:  filenames,
		diffIDs:    diffIDs,
		diffSizes:  diffSizes,
		blobIDs:    blobIDs,
		blobSizes:  blobSizes,
		blobTypes:  blobTypes,
		config:     configBytes,
		configID:   configID,
		configSize: configSize,
		manifest:   manifestBytes,
	}
	return src, nil
}
func (is *tarballImageSource) Close() error {
	return nil
}