ostree/ostree_src.go
func (s *ostreeImageSource) GetBlob(ctx context.Context, info types.BlobInfo, cache types.BlobInfoCache) (io.ReadCloser, int64, error) {

	blob := info.Digest.Hex()

	// Ensure s.compressed is initialized.  It is build by LayerInfosForCopy.
	if s.compressed == nil {
		_, err := s.LayerInfosForCopy(ctx)
		if err != nil {
			return nil, -1, err
		}

	}
	compressedBlob, found := s.compressed[info.Digest]
	if found {
		blob = compressedBlob.Hex()
	}
	branch := fmt.Sprintf("ociimage/%s", blob)

	if s.repo == nil {
		repo, err := openRepo(s.ref.repo)
		if err != nil {
			return nil, 0, err
		}
		s.repo = repo
	}

	layerSize, err := s.getLayerSize(blob)
	if err != nil {
		return nil, 0, err
	}

	tarsplit, err := s.getTarSplitData(blob)
	if err != nil {
		return nil, 0, err
	}

	// if tarsplit is nil we are looking at the manifest.  Return directly the file in /content
	if tarsplit == nil {
		file, err := s.readSingleFile(branch, "/content")
		if err != nil {
			return nil, 0, err
		}
		return file, layerSize, nil
	}

	mf := bytes.NewReader(tarsplit)
	mfz, err := pgzip.NewReader(mf)
	if err != nil {
		return nil, 0, err
	}
	metaUnpacker := storage.NewJSONUnpacker(mfz)

	getter, err := newOSTreePathFileGetter(s.repo, branch)
	if err != nil {
		mfz.Close()
		return nil, 0, err
	}

	ots := asm.NewOutputTarStream(getter, metaUnpacker)

	rc := ioutils.NewReadCloserWrapper(ots, func() error {
		getter.Close()
		mfz.Close()
		return ots.Close()
	})
	return rc, layerSize, nil
}
func (s *ostreeImageSource) GetBlob(ctx context.Context, info types.BlobInfo, cache types.BlobInfoCache) (io.ReadCloser, int64, error) {

	blob := info.Digest.Hex()

	// Ensure s.compressed is initialized.  It is build by LayerInfosForCopy.
	if s.compressed == nil {
		_, err := s.LayerInfosForCopy(ctx)
		if err != nil {
			return nil, -1, err
		}

	}
	compressedBlob, found := s.compressed[info.Digest]
	if found {
		blob = compressedBlob.Hex()
	}
	branch := fmt.Sprintf("ociimage/%s", blob)

	if s.repo == nil {
		repo, err := openRepo(s.ref.repo)
		if err != nil {
			return nil, 0, err
		}
		s.repo = repo
	}

	layerSize, err := s.getLayerSize(blob)
	if err != nil {
		return nil, 0, err
	}

	tarsplit, err := s.getTarSplitData(blob)
	if err != nil {
		return nil, 0, err
	}

	// if tarsplit is nil we are looking at the manifest.  Return directly the file in /content
	if tarsplit == nil {
		file, err := s.readSingleFile(branch, "/content")
		if err != nil {
			return nil, 0, err
		}
		return file, layerSize, nil
	}

	mf := bytes.NewReader(tarsplit)
	mfz, err := pgzip.NewReader(mf)
	if err != nil {
		return nil, 0, err
	}
	metaUnpacker := storage.NewJSONUnpacker(mfz)

	getter, err := newOSTreePathFileGetter(s.repo, branch)
	if err != nil {
		mfz.Close()
		return nil, 0, err
	}

	ots := asm.NewOutputTarStream(getter, metaUnpacker)

	rc := ioutils.NewReadCloserWrapper(ots, func() error {
		getter.Close()
		mfz.Close()
		return ots.Close()
	})
	return rc, layerSize, nil
}
// GetBlob returns a stream for the specified blob, and the blob’s size (or -1 if unknown).
// The Digest field in BlobInfo is guaranteed to be provided, Size may be -1 and MediaType may be optionally provided.
// May update BlobInfoCache, preferably after it knows for certain that a blob truly exists at a specific location.