docker/tarfile/src.go
func NewSourceFromStream(inputStream io.Reader) (*Source, error) {
	// FIXME: use SystemContext here.
	// Save inputStream to a temporary file
	tarCopyFile, err := ioutil.TempFile(tmpdir.TemporaryDirectoryForBigFiles(), "docker-tar")
	if err != nil {
		return nil, errors.Wrap(err, "error creating temporary file")
	}
	defer tarCopyFile.Close()

	succeeded := false
	defer func() {
		if !succeeded {
			os.Remove(tarCopyFile.Name())
		}
	}()

	// In order to be compatible with docker-load, we need to support
	// auto-decompression (it's also a nice quality-of-life thing to avoid
	// giving users really confusing "invalid tar header" errors).
	uncompressedStream, _, err := compression.AutoDecompress(inputStream)
	if err != nil {
		return nil, errors.Wrap(err, "Error auto-decompressing input")
	}
	defer uncompressedStream.Close()

	// Copy the plain archive to the temporary file.
	//
	// TODO: This can take quite some time, and should ideally be cancellable
	//       using a context.Context.
	if _, err := io.Copy(tarCopyFile, uncompressedStream); err != nil {
		return nil, errors.Wrapf(err, "error copying contents to temporary file %q", tarCopyFile.Name())
	}
	succeeded = true

	return &Source{
		tarPath:              tarCopyFile.Name(),
		removeTarPathOnClose: true,
	}, nil
}
func NewSourceFromStream(inputStream io.Reader) (*Source, error) {
	// FIXME: use SystemContext here.
	// Save inputStream to a temporary file
	tarCopyFile, err := ioutil.TempFile(tmpdir.TemporaryDirectoryForBigFiles(), "docker-tar")
	if err != nil {
		return nil, errors.Wrap(err, "error creating temporary file")
	}
	defer tarCopyFile.Close()

	succeeded := false
	defer func() {
		if !succeeded {
			os.Remove(tarCopyFile.Name())
		}
	}()

	// In order to be compatible with docker-load, we need to support
	// auto-decompression (it's also a nice quality-of-life thing to avoid
	// giving users really confusing "invalid tar header" errors).
	uncompressedStream, _, err := compression.AutoDecompress(inputStream)
	if err != nil {
		return nil, errors.Wrap(err, "Error auto-decompressing input")
	}
	defer uncompressedStream.Close()

	// Copy the plain archive to the temporary file.
	//
	// TODO: This can take quite some time, and should ideally be cancellable
	//       using a context.Context.
	if _, err := io.Copy(tarCopyFile, uncompressedStream); err != nil {
		return nil, errors.Wrapf(err, "error copying contents to temporary file %q", tarCopyFile.Name())
	}
	succeeded = true

	return &Source{
		tarPath:              tarCopyFile.Name(),
		removeTarPathOnClose: true,
	}, nil
}
// NewSourceFromStream returns a tarfile.Source for the specified inputStream,
// which can be either compressed or uncompressed. The caller can close the
// inputStream immediately after NewSourceFromFile returns.