Skip to content

Commit 6b6fd18

Browse files
authored
Merge pull request #2807 from mtrmac/tarball-compression-5.34
[5.34] Correctly compute DiffID, and try to set the correct MIME type, for non-gzip input to `tarball:`
2 parents 0cf7de7 + 3b3e6d3 commit 6b6fd18

File tree

1 file changed

+39
-22
lines changed

1 file changed

+39
-22
lines changed

tarball/tarball_src.go

+39-22
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,9 @@ import (
1414

1515
"github.com/containers/image/v5/internal/imagesource/impl"
1616
"github.com/containers/image/v5/internal/imagesource/stubs"
17+
"github.com/containers/image/v5/pkg/compression"
18+
compressionTypes "github.com/containers/image/v5/pkg/compression/types"
1719
"github.com/containers/image/v5/types"
18-
"github.com/klauspost/pgzip"
1920
digest "github.com/opencontainers/go-digest"
2021
imgspecs "github.com/opencontainers/image-spec/specs-go"
2122
imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1"
@@ -82,31 +83,47 @@ func (r *tarballReference) NewImageSource(ctx context.Context, sys *types.System
8283
}
8384
}
8485

85-
// Default to assuming the layer is compressed.
86-
layerType := imgspecv1.MediaTypeImageLayerGzip
87-
8886
// Set up to digest the file as it is.
8987
blobIDdigester := digest.Canonical.Digester()
9088
reader = io.TeeReader(reader, blobIDdigester.Hash())
9189

92-
// Set up to digest the file after we maybe decompress it.
93-
diffIDdigester := digest.Canonical.Digester()
94-
uncompressed, err := pgzip.NewReader(reader)
95-
if err == nil {
96-
// It is compressed, so the diffID is the digest of the uncompressed version
97-
reader = io.TeeReader(uncompressed, diffIDdigester.Hash())
98-
} else {
99-
// It is not compressed, so the diffID and the blobID are going to be the same
100-
diffIDdigester = blobIDdigester
101-
layerType = imgspecv1.MediaTypeImageLayer
102-
uncompressed = nil
103-
}
104-
// TODO: This can take quite some time, and should ideally be cancellable using ctx.Done().
105-
if _, err := io.Copy(io.Discard, reader); err != nil {
106-
return nil, fmt.Errorf("error reading %q: %w", filename, err)
107-
}
108-
if uncompressed != nil {
109-
uncompressed.Close()
90+
var layerType string
91+
var diffIDdigester digest.Digester
92+
// If necessary, digest the file after we decompress it.
93+
if err := func() error { // A scope for defer
94+
format, decompressor, reader, err := compression.DetectCompressionFormat(reader)
95+
if err != nil {
96+
return err
97+
}
98+
if decompressor != nil {
99+
uncompressed, err := decompressor(reader)
100+
if err != nil {
101+
return err
102+
}
103+
defer uncompressed.Close()
104+
// It is compressed, so the diffID is the digest of the uncompressed version
105+
diffIDdigester = digest.Canonical.Digester()
106+
reader = io.TeeReader(uncompressed, diffIDdigester.Hash())
107+
switch format.Name() {
108+
case compressionTypes.GzipAlgorithmName:
109+
layerType = imgspecv1.MediaTypeImageLayerGzip
110+
case compressionTypes.ZstdAlgorithmName:
111+
layerType = imgspecv1.MediaTypeImageLayerZstd
112+
default: // This is incorrect, but we have no good options, and it is what this transport was historically doing.
113+
layerType = imgspecv1.MediaTypeImageLayerGzip
114+
}
115+
} else {
116+
// It is not compressed, so the diffID and the blobID are going to be the same
117+
diffIDdigester = blobIDdigester
118+
layerType = imgspecv1.MediaTypeImageLayer
119+
}
120+
// TODO: This can take quite some time, and should ideally be cancellable using ctx.Done().
121+
if _, err := io.Copy(io.Discard, reader); err != nil {
122+
return fmt.Errorf("error reading %q: %w", filename, err)
123+
}
124+
return nil
125+
}(); err != nil {
126+
return nil, err
110127
}
111128

112129
// Grab our uncompressed and possibly-compressed digests and sizes.

0 commit comments

Comments
 (0)