func (d *ostreeImageDestination) PutBlob(ctx context.Context, stream io.Reader, inputInfo types.BlobInfo, cache types.BlobInfoCache, isConfig bool) (types.BlobInfo, error) {
	tmpDir, err := ioutil.TempDir(d.tmpDirPath, "blob")
	if err != nil {
		return types.BlobInfo{}, err
	}

	blobPath := filepath.Join(tmpDir, "content")
	blobFile, err := os.Create(blobPath)
	if err != nil {
		return types.BlobInfo{}, err
	}
	defer blobFile.Close()

	digester := digest.Canonical.Digester()
	tee := io.TeeReader(stream, digester.Hash())

	// TODO: This can take quite some time, and should ideally be cancellable using ctx.Done().
	size, err := io.Copy(blobFile, tee)
	if err != nil {
		return types.BlobInfo{}, err
	}
	computedDigest := digester.Digest()
	if inputInfo.Size != -1 && size != inputInfo.Size {
		return types.BlobInfo{}, errors.Errorf("Size mismatch when copying %s, expected %d, got %d", computedDigest, inputInfo.Size, size)
	}
	if err := blobFile.Sync(); err != nil {
		return types.BlobInfo{}, err
	}

	hash := computedDigest.Hex()
	d.blobs[hash] = &blobToImport{Size: size, Digest: computedDigest, BlobPath: blobPath}
	return types.BlobInfo{Digest: computedDigest, Size: size}, nil
}
func (d *ostreeImageDestination) PutBlob(ctx context.Context, stream io.Reader, inputInfo types.BlobInfo, cache types.BlobInfoCache, isConfig bool) (types.BlobInfo, error) {
	tmpDir, err := ioutil.TempDir(d.tmpDirPath, "blob")
	if err != nil {
		return types.BlobInfo{}, err
	}

	blobPath := filepath.Join(tmpDir, "content")
	blobFile, err := os.Create(blobPath)
	if err != nil {
		return types.BlobInfo{}, err
	}
	defer blobFile.Close()

	digester := digest.Canonical.Digester()
	tee := io.TeeReader(stream, digester.Hash())

	
	size, err := io.Copy(blobFile, tee)
	if err != nil {
		return types.BlobInfo{}, err
	}
	computedDigest := digester.Digest()
	if inputInfo.Size != -1 && size != inputInfo.Size {
		return types.BlobInfo{}, errors.Errorf("Size mismatch when copying %s, expected %d, got %d", computedDigest, inputInfo.Size, size)
	}
	if err := blobFile.Sync(); err != nil {
		return types.BlobInfo{}, err
	}

	hash := computedDigest.Hex()
	d.blobs[hash] = &blobToImport{Size: size, Digest: computedDigest, BlobPath: blobPath}
	return types.BlobInfo{Digest: computedDigest, Size: size}, nil
}
func ( d * ostreeImageDestination ) PutBlob ( ctx context . Context , stream io . Reader , inputInfo types . BlobInfo , cache types . BlobInfoCache , isConfig bool ) ( types . BlobInfo , error ) { tmpDir , err := ioutil . TempDir ( d . tmpDirPath , " " ) if err != nil { return types . BlobInfo { } , err } blobPath := filepath . Join ( tmpDir , " " ) blobFile , err := os . Create ( blobPath ) if err != nil { return types . BlobInfo { } , err } defer blobFile . Close ( ) digester := digest . Canonical . Digester ( ) tee := io . TeeReader ( stream , digester . Hash ( ) ) // TODO: This can take quite some time, and should ideally be cancellable using ctx.Done(). size , err := io . Copy ( blobFile , tee ) if err != nil { return types . BlobInfo { } , err } computedDigest := digester . Digest ( ) if inputInfo . Size != - 1 && size != inputInfo . Size { return types . BlobInfo { } , errors . Errorf ( " " , computedDigest , inputInfo . Size , size ) } if err := blobFile . Sync ( ) ; err != nil { return types . BlobInfo { } , err } hash := computedDigest . Hex ( ) d . blobs [ hash ] = & blobToImport { Size : size , Digest : computedDigest , BlobPath : blobPath } return types . BlobInfo { Digest : computedDigest , Size : size } , nil }
// PutBlob writes contents of stream and returns data representing the result.
// inputInfo.Digest can be optionally provided if known; it is not mandatory for the implementation to verify it.
// inputInfo.Size is the expected length of stream, if known.
// inputInfo.MediaType describes the blob format, if known.
// May update cache.
// WARNING: The contents of stream are being verified on the fly.  Until stream.Read() returns io.EOF, the contents of the data SHOULD NOT be available
// to any other readers for download using the supplied digest.
// If stream.Read() at any time, ESPECIALLY at end of input, returns an error, PutBlob MUST 1) fail, and 2) delete any data stored so far.
PutBlob writes contents of stream and returns data representing the result . inputInfo . Digest can be optionally provided if known ; it is not mandatory for the implementation to verify it . inputInfo . Size is the expected length of stream if known . inputInfo . MediaType describes the blob format if known . May update cache . WARNING : The contents of stream are being verified on the fly . Until stream . Read () returns io . EOF the contents of the data SHOULD NOT be available to any other readers for download using the supplied digest . If stream . Read () at any time ESPECIALLY at end of input returns an error PutBlob MUST 1 ) fail and 2 ) delete any data stored so far .