Files
podman/vendor/github.com/containers/image/v5/docker/archive/reader.go
dependabot[bot] 23a938fa26 Bump github.com/containers/image/v5 from 5.13.2 to 5.14.0
Bumps [github.com/containers/image/v5](https://github.com/containers/image) from 5.13.2 to 5.14.0.
- [Release notes](https://github.com/containers/image/releases)
- [Commits](https://github.com/containers/image/compare/v5.13.2...v5.14.0)

---
updated-dependencies:
- dependency-name: github.com/containers/image/v5
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-07-25 04:54:29 -04:00

121 lines
4.5 KiB
Go

package archive
import (
"github.com/containers/image/v5/docker/internal/tarfile"
"github.com/containers/image/v5/docker/reference"
"github.com/containers/image/v5/transports"
"github.com/containers/image/v5/types"
"github.com/pkg/errors"
)
// Reader manages a single Docker archive, allows listing its contents and accessing
// individual images with less overhead than creating image references individually
// (because the archive is, if necessary, copied or decompressed only once).
type Reader struct {
path string // The original, user-specified path; not the maintained temporary file, if any
archive *tarfile.Reader
}
// NewReader returns a Reader for path.
// The caller should call .Close() on the returned object.
func NewReader(sys *types.SystemContext, path string) (*Reader, error) {
archive, err := tarfile.NewReaderFromFile(sys, path)
if err != nil {
return nil, err
}
return &Reader{
path: path,
archive: archive,
}, nil
}
// Close deletes temporary files associated with the Reader, if any.
func (r *Reader) Close() error {
return r.archive.Close()
}
// NewReaderForReference creates a Reader from a Reader-independent imageReference, which must be from docker/archive.Transport,
// and a variant of imageReference that points at the same image within the reader.
// The caller should call .Close() on the returned Reader.
func NewReaderForReference(sys *types.SystemContext, ref types.ImageReference) (*Reader, types.ImageReference, error) {
standalone, ok := ref.(archiveReference)
if !ok {
return nil, nil, errors.Errorf("Internal error: NewReaderForReference called for a non-docker/archive ImageReference %s", transports.ImageName(ref))
}
if standalone.archiveReader != nil {
return nil, nil, errors.Errorf("Internal error: NewReaderForReference called for a reader-bound reference %s", standalone.StringWithinTransport())
}
reader, err := NewReader(sys, standalone.path)
if err != nil {
return nil, nil, err
}
succeeded := false
defer func() {
if !succeeded {
reader.Close()
}
}()
readerRef, err := newReference(standalone.path, standalone.ref, standalone.sourceIndex, reader.archive, nil)
if err != nil {
return nil, nil, err
}
succeeded = true
return reader, readerRef, nil
}
// List returns the a set of references for images in the Reader,
// grouped by the image the references point to.
// The references are valid only until the Reader is closed.
func (r *Reader) List() ([][]types.ImageReference, error) {
res := [][]types.ImageReference{}
for imageIndex, image := range r.archive.Manifest {
refs := []types.ImageReference{}
for _, tag := range image.RepoTags {
parsedTag, err := reference.ParseNormalizedNamed(tag)
if err != nil {
return nil, errors.Wrapf(err, "Invalid tag %#v in manifest item @%d", tag, imageIndex)
}
nt, ok := parsedTag.(reference.NamedTagged)
if !ok {
return nil, errors.Errorf("Invalid tag %s (%s): does not contain a tag", tag, parsedTag.String())
}
ref, err := newReference(r.path, nt, -1, r.archive, nil)
if err != nil {
return nil, errors.Wrapf(err, "creating a reference for tag %#v in manifest item @%d", tag, imageIndex)
}
refs = append(refs, ref)
}
if len(refs) == 0 {
ref, err := newReference(r.path, nil, imageIndex, r.archive, nil)
if err != nil {
return nil, errors.Wrapf(err, "creating a reference for manifest item @%d", imageIndex)
}
refs = append(refs, ref)
}
res = append(res, refs)
}
return res, nil
}
// ManifestTagsForReference returns the set of tags “matching” ref in reader, as strings
// (i.e. exposing the short names before normalization).
// The function reports an error if ref does not identify a single image.
// If ref contains a NamedTagged reference, only a single tag “matching” ref is returned;
// If ref contains a source index, or neither a NamedTagged nor a source index, all tags
// matching the image are returned.
// Almost all users should use List() or ImageReference.DockerReference() instead.
func (r *Reader) ManifestTagsForReference(ref types.ImageReference) ([]string, error) {
archiveRef, ok := ref.(archiveReference)
if !ok {
return nil, errors.Errorf("Internal error: ManifestTagsForReference called for a non-docker/archive ImageReference %s", transports.ImageName(ref))
}
manifestItem, tagIndex, err := r.archive.ChooseManifestItem(archiveRef.ref, archiveRef.sourceIndex)
if err != nil {
return nil, err
}
if tagIndex != -1 {
return []string{manifestItem.RepoTags[tagIndex]}, nil
}
return manifestItem.RepoTags, nil
}