aboutsummaryrefslogtreecommitdiff
path: root/vendor/github.com/containers/image/v5/docker/archive/dest.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/containers/image/v5/docker/archive/dest.go')
-rw-r--r--vendor/github.com/containers/image/v5/docker/archive/dest.go72
1 files changed, 72 insertions, 0 deletions
diff --git a/vendor/github.com/containers/image/v5/docker/archive/dest.go b/vendor/github.com/containers/image/v5/docker/archive/dest.go
new file mode 100644
index 000000000..5845f63be
--- /dev/null
+++ b/vendor/github.com/containers/image/v5/docker/archive/dest.go
@@ -0,0 +1,72 @@
+package archive
+
+import (
+ "context"
+ "io"
+ "os"
+
+ "github.com/containers/image/v5/docker/tarfile"
+ "github.com/containers/image/v5/types"
+ "github.com/pkg/errors"
+)
+
+type archiveImageDestination struct {
+ *tarfile.Destination // Implements most of types.ImageDestination
+ ref archiveReference
+ writer io.Closer
+}
+
+func newImageDestination(sys *types.SystemContext, ref archiveReference) (types.ImageDestination, error) {
+ // ref.path can be either a pipe or a regular file
+ // in the case of a pipe, we require that we can open it for write
+ // in the case of a regular file, we don't want to overwrite any pre-existing file
+ // so we check for Size() == 0 below (This is racy, but using O_EXCL would also be racy,
+ // only in a different way. Either way, it’s up to the user to not have two writers to the same path.)
+ fh, err := os.OpenFile(ref.path, os.O_WRONLY|os.O_CREATE, 0644)
+ if err != nil {
+ return nil, errors.Wrapf(err, "error opening file %q", ref.path)
+ }
+
+ fhStat, err := fh.Stat()
+ if err != nil {
+ return nil, errors.Wrapf(err, "error statting file %q", ref.path)
+ }
+
+ if fhStat.Mode().IsRegular() && fhStat.Size() != 0 {
+ return nil, errors.New("docker-archive doesn't support modifying existing images")
+ }
+
+ tarDest := tarfile.NewDestination(fh, ref.destinationRef)
+ if sys != nil && sys.DockerArchiveAdditionalTags != nil {
+ tarDest.AddRepoTags(sys.DockerArchiveAdditionalTags)
+ }
+ return &archiveImageDestination{
+ Destination: tarDest,
+ ref: ref,
+ writer: fh,
+ }, 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 {
+ return d.writer.Close()
+}
+
+// Commit marks the process of storing the image as successful and asks for the image to be persisted.
+// 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 {
+ return d.Destination.Commit(ctx)
+}