mirror of https://github.com/containers/image.git
82 lines
2.8 KiB
Go
82 lines
2.8 KiB
Go
package archive
|
|
|
|
import (
|
|
"context"
|
|
"io"
|
|
|
|
"github.com/containers/image/v5/docker/internal/tarfile"
|
|
"github.com/containers/image/v5/types"
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
type archiveImageDestination struct {
|
|
*tarfile.Destination // Implements most of types.ImageDestination
|
|
ref archiveReference
|
|
archive *tarfile.Writer // Should only be closed if writer != nil
|
|
writer io.Closer // May be nil if the archive is shared
|
|
}
|
|
|
|
func newImageDestination(sys *types.SystemContext, ref archiveReference) (types.ImageDestination, error) {
|
|
if ref.sourceIndex != -1 {
|
|
return nil, errors.Errorf("Destination reference must not contain a manifest index @%d", ref.sourceIndex)
|
|
}
|
|
|
|
var archive *tarfile.Writer
|
|
var writer io.Closer
|
|
if ref.archiveWriter != nil {
|
|
archive = ref.archiveWriter
|
|
writer = nil
|
|
} else {
|
|
fh, err := openArchiveForWriting(ref.path)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
archive = tarfile.NewWriter(fh)
|
|
writer = fh
|
|
}
|
|
tarDest := tarfile.NewDestination(sys, archive, ref.ref)
|
|
if sys != nil && sys.DockerArchiveAdditionalTags != nil {
|
|
tarDest.AddRepoTags(sys.DockerArchiveAdditionalTags)
|
|
}
|
|
return &archiveImageDestination{
|
|
Destination: tarDest,
|
|
ref: ref,
|
|
archive: archive,
|
|
writer: writer,
|
|
}, nil
|
|
}
|
|
|
|
// DesiredLayerCompression indicates if layers must be compressed, decompressed or preserved
|
|
func (d *archiveImageDestination) DesiredLayerCompression() types.LayerCompression {
|
|
return types.Decompress
|
|
}
|
|
|
|
// Reference returns the reference used to set up this destination. Note that this should directly correspond to user's intent,
|
|
// e.g. it should use the public hostname instead of the result of resolving CNAMEs or following redirects.
|
|
func (d *archiveImageDestination) Reference() types.ImageReference {
|
|
return d.ref
|
|
}
|
|
|
|
// Close removes resources associated with an initialized ImageDestination, if any.
|
|
func (d *archiveImageDestination) Close() error {
|
|
if d.writer != nil {
|
|
return d.writer.Close()
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Commit marks the process of storing the image as successful and asks for the image to be persisted.
|
|
// unparsedToplevel contains data about the top-level manifest of the source (which may be a single-arch image or a manifest list
|
|
// if PutManifest was only called for the single-arch image with instanceDigest == nil), primarily to allow lookups by the
|
|
// original manifest list digest, if desired.
|
|
// WARNING: This does not have any transactional semantics:
|
|
// - Uploaded data MAY be visible to others before Commit() is called
|
|
// - Uploaded data MAY be removed or MAY remain around if Close() is called without Commit() (i.e. rollback is allowed but not guaranteed)
|
|
func (d *archiveImageDestination) Commit(ctx context.Context, unparsedToplevel types.UnparsedImage) error {
|
|
if d.writer != nil {
|
|
return d.archive.Close()
|
|
}
|
|
return nil
|
|
}
|