diff --git a/pkg/crane/export.go b/pkg/crane/export.go index 5d6da1dca..b5e1296d2 100644 --- a/pkg/crane/export.go +++ b/pkg/crane/export.go @@ -30,16 +30,23 @@ func Export(img v1.Image, w io.Writer) error { return err } if len(layers) == 1 { - // If it's a single layer, we don't have to flatten the filesystem. - // An added perk of skipping mutate.Extract here is that this works - // for non-tarball layers. + // If it's a single layer... l := layers[0] - rc, err := l.Uncompressed() + mt, err := l.MediaType() if err != nil { return err } - _, err = io.Copy(w, rc) - return err + + if !mt.IsLayer() { + // ...and isn't an OCI mediaType, we don't have to flatten it. + // This lets export work for single layer, non-tarball images. + rc, err := l.Uncompressed() + if err != nil { + return err + } + _, err = io.Copy(w, rc) + return err + } } fs := mutate.Extract(img) _, err = io.Copy(w, fs) diff --git a/pkg/v1/types/types.go b/pkg/v1/types/types.go index 92a4492af..c86657d7b 100644 --- a/pkg/v1/types/types.go +++ b/pkg/v1/types/types.go @@ -88,3 +88,11 @@ func (m MediaType) IsSchema1() bool { } return false } + +func (m MediaType) IsLayer() bool { + switch m { + case DockerLayer, DockerUncompressedLayer, OCILayer, OCILayerZStd, OCIUncompressedLayer, DockerForeignLayer, OCIRestrictedLayer, OCIUncompressedRestrictedLayer: + return true + } + return false +}