@@ -11,7 +11,6 @@ import (
11
11
12
12
"github.com/containers/storage/pkg/chunked/internal/minimal"
13
13
"github.com/containers/storage/pkg/ioutils"
14
- "github.com/klauspost/compress/zstd"
15
14
"github.com/opencontainers/go-digest"
16
15
"github.com/vbatts/tar-split/archive/tar"
17
16
"github.com/vbatts/tar-split/tar/asm"
@@ -202,15 +201,15 @@ type tarSplitData struct {
202
201
compressed * bytes.Buffer
203
202
digester digest.Digester
204
203
uncompressedCounter * ioutils.WriteCounter
205
- zstd * zstd. Encoder
204
+ zstd minimal. ZstdWriter
206
205
packer storage.Packer
207
206
}
208
207
209
- func newTarSplitData (level int ) (* tarSplitData , error ) {
208
+ func newTarSplitData (createZstdWriter minimal. CreateZstdWriterFunc ) (* tarSplitData , error ) {
210
209
compressed := bytes .NewBuffer (nil )
211
210
digester := digest .Canonical .Digester ()
212
211
213
- zstdWriter , err := minimal . ZstdWriterWithLevel (io .MultiWriter (compressed , digester .Hash ()), level )
212
+ zstdWriter , err := createZstdWriter (io .MultiWriter (compressed , digester .Hash ()))
214
213
if err != nil {
215
214
return nil , err
216
215
}
@@ -227,11 +226,11 @@ func newTarSplitData(level int) (*tarSplitData, error) {
227
226
}, nil
228
227
}
229
228
230
- func writeZstdChunkedStream (destFile io.Writer , outMetadata map [string ]string , reader io.Reader , level int ) error {
229
+ func writeZstdChunkedStream (destFile io.Writer , outMetadata map [string ]string , reader io.Reader , createZstdWriter minimal. CreateZstdWriterFunc ) error {
231
230
// total written so far. Used to retrieve partial offsets in the file
232
231
dest := ioutils .NewWriteCounter (destFile )
233
232
234
- tarSplitData , err := newTarSplitData (level )
233
+ tarSplitData , err := newTarSplitData (createZstdWriter )
235
234
if err != nil {
236
235
return err
237
236
}
@@ -251,7 +250,7 @@ func writeZstdChunkedStream(destFile io.Writer, outMetadata map[string]string, r
251
250
252
251
buf := make ([]byte , 4096 )
253
252
254
- zstdWriter , err := minimal . ZstdWriterWithLevel (dest , level )
253
+ zstdWriter , err := createZstdWriter (dest )
255
254
if err != nil {
256
255
return err
257
256
}
@@ -404,18 +403,11 @@ func writeZstdChunkedStream(destFile io.Writer, outMetadata map[string]string, r
404
403
return err
405
404
}
406
405
407
- if err := zstdWriter .Flush (); err != nil {
408
- zstdWriter .Close ()
409
- return err
410
- }
411
406
if err := zstdWriter .Close (); err != nil {
412
407
return err
413
408
}
414
409
zstdWriter = nil
415
410
416
- if err := tarSplitData .zstd .Flush (); err != nil {
417
- return err
418
- }
419
411
if err := tarSplitData .zstd .Close (); err != nil {
420
412
return err
421
413
}
@@ -427,7 +419,7 @@ func writeZstdChunkedStream(destFile io.Writer, outMetadata map[string]string, r
427
419
UncompressedSize : tarSplitData .uncompressedCounter .Count ,
428
420
}
429
421
430
- return minimal .WriteZstdChunkedManifest (dest , outMetadata , uint64 (dest .Count ), & ts , metadata , level )
422
+ return minimal .WriteZstdChunkedManifest (dest , outMetadata , uint64 (dest .Count ), & ts , metadata , createZstdWriter )
431
423
}
432
424
433
425
type zstdChunkedWriter struct {
@@ -454,7 +446,7 @@ func (w zstdChunkedWriter) Write(p []byte) (int, error) {
454
446
}
455
447
}
456
448
457
- // zstdChunkedWriterWithLevel writes a zstd compressed tarball where each file is
449
+ // makeZstdChunkedWriter writes a zstd compressed tarball where each file is
458
450
// compressed separately so it can be addressed separately. Idea based on CRFS:
459
451
// https://github.com/google/crfs
460
452
// The difference with CRFS is that the zstd compression is used instead of gzip.
@@ -469,12 +461,12 @@ func (w zstdChunkedWriter) Write(p []byte) (int, error) {
469
461
// [SKIPPABLE FRAME 1]: [ZSTD SKIPPABLE FRAME, SIZE=MANIFEST LENGTH][MANIFEST]
470
462
// [SKIPPABLE FRAME 2]: [ZSTD SKIPPABLE FRAME, SIZE=16][MANIFEST_OFFSET][MANIFEST_LENGTH][MANIFEST_LENGTH_UNCOMPRESSED][MANIFEST_TYPE][CHUNKED_ZSTD_MAGIC_NUMBER]
471
463
// MANIFEST_OFFSET, MANIFEST_LENGTH, MANIFEST_LENGTH_UNCOMPRESSED and CHUNKED_ZSTD_MAGIC_NUMBER are 64 bits unsigned in little endian format.
472
- func zstdChunkedWriterWithLevel (out io.Writer , metadata map [string ]string , level int ) (io.WriteCloser , error ) {
464
+ func makeZstdChunkedWriter (out io.Writer , metadata map [string ]string , createZstdWriter minimal. CreateZstdWriterFunc ) (io.WriteCloser , error ) {
473
465
ch := make (chan error , 1 )
474
466
r , w := io .Pipe ()
475
467
476
468
go func () {
477
- ch <- writeZstdChunkedStream (out , metadata , r , level )
469
+ ch <- writeZstdChunkedStream (out , metadata , r , createZstdWriter )
478
470
_ , _ = io .Copy (io .Discard , r ) // Ordinarily writeZstdChunkedStream consumes all of r. If it fails, ensure the write end never blocks and eventually terminates.
479
471
r .Close ()
480
472
close (ch )
@@ -493,5 +485,40 @@ func ZstdCompressor(r io.Writer, metadata map[string]string, level *int) (io.Wri
493
485
level = & l
494
486
}
495
487
496
- return zstdChunkedWriterWithLevel (r , metadata , * level )
488
+ createZstdWriter := func (dest io.Writer ) (minimal.ZstdWriter , error ) {
489
+ return minimal .ZstdWriterWithLevel (dest , * level )
490
+ }
491
+
492
+ return makeZstdChunkedWriter (r , metadata , createZstdWriter )
493
+ }
494
+
495
+ type noCompression struct {
496
+ dest io.Writer
497
+ }
498
+
499
+ func (n * noCompression ) Write (p []byte ) (int , error ) {
500
+ return n .dest .Write (p )
501
+ }
502
+
503
+ func (n * noCompression ) Close () error {
504
+ return nil
505
+ }
506
+
507
+ func (n * noCompression ) Flush () error {
508
+ return nil
509
+ }
510
+
511
+ func (n * noCompression ) Reset (dest io.Writer ) {
512
+ n .dest = dest
513
+ }
514
+
515
+ // NoCompression writes directly to the output file without any compression
516
+ //
517
+ // Such an output does not follow the zstd:chunked spec and cannot be generally consumed; this function
518
+ // only exists for internal purposes and should not be called from outside c/storage.
519
+ func NoCompression (r io.Writer , metadata map [string ]string ) (io.WriteCloser , error ) {
520
+ createZstdWriter := func (dest io.Writer ) (minimal.ZstdWriter , error ) {
521
+ return & noCompression {dest : dest }, nil
522
+ }
523
+ return makeZstdChunkedWriter (r , metadata , createZstdWriter )
497
524
}
0 commit comments