@@ -203,6 +203,17 @@ type stagedLayerOptions struct {
203203 DiffOptions * drivers.ApplyDiffWithDifferOpts
204204}
205205
206+ type applyDiffResult struct {
207+ compressedDigest digest.Digest
208+ compressedSize int64
209+ compressionType archive.Compression
210+ uncompressedDigest digest.Digest
211+ uncompressedSize int64
212+ size int64
213+ uids []uint32
214+ gids []uint32
215+ }
216+
206217// roLayerStore wraps a graph driver, adding the ability to refer to layers by
207218// name, and keeping track of parent-child relationships, along with a list of
208219// all known layers.
@@ -2406,37 +2417,27 @@ func createTarSplitFile(r *layerStore, layerID string) (*os.File, error) {
24062417 return os .OpenFile (r .tspath (layerID ), os .O_CREATE | os .O_WRONLY | os .O_TRUNC , 0o600 )
24072418}
24082419
2409- // Requires startWriting.
2410- func (r * layerStore ) applyDiffWithOptions (to string , layerOptions * LayerOptions , diff io.Reader ) (size int64 , err error ) {
2411- if ! r .lockfile .IsReadWrite () {
2412- return - 1 , fmt .Errorf ("not allowed to modify layer contents at %q: %w" , r .layerdir , ErrStoreIsReadOnly )
2413- }
2414-
2415- layer , ok := r .lookup (to )
2416- if ! ok {
2417- return - 1 , ErrLayerUnknown
2418- }
2419-
2420+ func applyDiff (layerOptions * LayerOptions , diff io.Reader , tarSplitFile * os.File , applyDriverFunc func (io.Reader ) (int64 , error )) (* applyDiffResult , error ) {
24202421 header := make ([]byte , 10240 )
24212422 n , err := diff .Read (header )
24222423 if err != nil && err != io .EOF {
2423- return - 1 , err
2424+ return nil , err
24242425 }
24252426 compression := archive .DetectCompression (header [:n ])
24262427 defragmented := io .MultiReader (bytes .NewReader (header [:n ]), diff )
24272428
2428- // Decide if we need to compute digests
2429- var compressedDigest , uncompressedDigest digest. Digest // = ""
2429+ result := applyDiffResult {}
2430+
24302431 var compressedDigester , uncompressedDigester digest.Digester // = nil
24312432 if layerOptions != nil && layerOptions .OriginalDigest != "" &&
24322433 layerOptions .OriginalDigest .Algorithm () == digest .Canonical {
2433- compressedDigest = layerOptions .OriginalDigest
2434+ result . compressedDigest = layerOptions .OriginalDigest
24342435 } else {
24352436 compressedDigester = digest .Canonical .Digester ()
24362437 }
24372438 if layerOptions != nil && layerOptions .UncompressedDigest != "" &&
24382439 layerOptions .UncompressedDigest .Algorithm () == digest .Canonical {
2439- uncompressedDigest = layerOptions .UncompressedDigest
2440+ result . uncompressedDigest = layerOptions .UncompressedDigest
24402441 } else if compression != archive .Uncompressed {
24412442 uncompressedDigester = digest .Canonical .Digester ()
24422443 }
@@ -2450,18 +2451,13 @@ func (r *layerStore) applyDiffWithOptions(to string, layerOptions *LayerOptions,
24502451 compressedCounter := ioutils .NewWriteCounter (compressedWriter )
24512452 defragmented = io .TeeReader (defragmented , compressedCounter )
24522453
2453- tarSplitFile , err := createTarSplitFile (r , layer .ID )
2454- if err != nil {
2455- return - 1 , err
2456- }
2457- defer tarSplitFile .Close ()
24582454 tarSplitWriter := pools .BufioWriter32KPool .Get (tarSplitFile )
24592455
24602456 uidLog := make (map [uint32 ]struct {})
24612457 gidLog := make (map [uint32 ]struct {})
24622458 var uncompressedCounter * ioutils.WriteCounter
24632459
2464- size , err = func () (int64 , error ) { // A scope for defer
2460+ size , err : = func () (int64 , error ) { // A scope for defer
24652461 compressor , err := pgzip .NewWriterLevel (tarSplitWriter , pgzip .BestSpeed )
24662462 if err != nil {
24672463 return - 1 , err
@@ -2495,63 +2491,105 @@ func (r *layerStore) applyDiffWithOptions(to string, layerOptions *LayerOptions,
24952491 if err != nil {
24962492 return - 1 , err
24972493 }
2498- options := drivers.ApplyDiffOpts {
2499- Diff : payload ,
2500- Mappings : r .layerMappings (layer ),
2501- MountLabel : layer .MountLabel ,
2502- }
2503- size , err := r .driver .ApplyDiff (layer .ID , layer .Parent , options )
2504- if err != nil {
2505- return - 1 , err
2506- }
2507- return size , err
2494+
2495+ return applyDriverFunc (payload )
25082496 }()
25092497 if err != nil {
2510- return - 1 , err
2498+ return nil , err
25112499 }
25122500
25132501 if err := tarSplitWriter .Flush (); err != nil {
2514- return - 1 , fmt .Errorf ("failed to flush tar split writer buffer: %w" , err )
2515- }
2516- if err := tarSplitFile .Sync (); err != nil {
2517- return - 1 , fmt .Errorf ("sync tar split file: %w" , err )
2502+ return nil , fmt .Errorf ("failed to flush tar split writer buffer: %w" , err )
25182503 }
25192504
25202505 if compressedDigester != nil {
2521- compressedDigest = compressedDigester .Digest ()
2506+ result . compressedDigest = compressedDigester .Digest ()
25222507 }
25232508 if uncompressedDigester != nil {
2524- uncompressedDigest = uncompressedDigester .Digest ()
2509+ result . uncompressedDigest = uncompressedDigester .Digest ()
25252510 }
2526- if uncompressedDigest == "" && compression == archive .Uncompressed {
2527- uncompressedDigest = compressedDigest
2511+ if result . uncompressedDigest == "" && compression == archive .Uncompressed {
2512+ result . uncompressedDigest = result . compressedDigest
25282513 }
25292514
2530- updateDigestMap (& r .bycompressedsum , layer .CompressedDigest , compressedDigest , layer .ID )
2531- layer .CompressedDigest = compressedDigest
25322515 if layerOptions != nil && layerOptions .OriginalDigest != "" && layerOptions .OriginalSize != nil {
2533- layer . CompressedSize = * layerOptions .OriginalSize
2516+ result . compressedSize = * layerOptions .OriginalSize
25342517 } else {
2535- layer . CompressedSize = compressedCounter .Count
2518+ result . compressedSize = compressedCounter .Count
25362519 }
2537- updateDigestMap (& r .byuncompressedsum , layer .UncompressedDigest , uncompressedDigest , layer .ID )
2538- layer .UncompressedDigest = uncompressedDigest
2539- layer .UncompressedSize = uncompressedCounter .Count
2540- layer .CompressionType = compression
2541- layer .UIDs = make ([]uint32 , 0 , len (uidLog ))
2520+ result .uncompressedSize = uncompressedCounter .Count
2521+ result .compressionType = compression
2522+
2523+ result .uids = make ([]uint32 , 0 , len (uidLog ))
25422524 for uid := range uidLog {
2543- layer . UIDs = append (layer . UIDs , uid )
2525+ result . uids = append (result . uids , uid )
25442526 }
2545- slices .Sort (layer . UIDs )
2546- layer . GIDs = make ([]uint32 , 0 , len (gidLog ))
2527+ slices .Sort (result . uids )
2528+ result . gids = make ([]uint32 , 0 , len (gidLog ))
25472529 for gid := range gidLog {
2548- layer . GIDs = append (layer . GIDs , gid )
2530+ result . gids = append (result . gids , gid )
25492531 }
2550- slices .Sort (layer .GIDs )
2532+ slices .Sort (result .gids )
2533+
2534+ result .size = size
2535+
2536+ return & result , err
2537+ }
2538+
2539+ // Requires startWriting.
2540+ func (r * layerStore ) applyDiffWithOptions (to string , layerOptions * LayerOptions , diff io.Reader ) (int64 , error ) {
2541+ if ! r .lockfile .IsReadWrite () {
2542+ return - 1 , fmt .Errorf ("not allowed to modify layer contents at %q: %w" , r .layerdir , ErrStoreIsReadOnly )
2543+ }
2544+
2545+ layer , ok := r .lookup (to )
2546+ if ! ok {
2547+ return - 1 , ErrLayerUnknown
2548+ }
2549+
2550+ tarSplitFile , err := createTarSplitFile (r , layer .ID )
2551+ if err != nil {
2552+ return - 1 , err
2553+ }
2554+ defer tarSplitFile .Close ()
2555+
2556+ result , err := applyDiff (layerOptions , diff , tarSplitFile , func (payload io.Reader ) (int64 , error ) {
2557+ options := drivers.ApplyDiffOpts {
2558+ Diff : payload ,
2559+ Mappings : r .layerMappings (layer ),
2560+ MountLabel : layer .MountLabel ,
2561+ }
2562+ return r .driver .ApplyDiff (layer .ID , layer .Parent , options )
2563+ })
2564+ if err != nil {
2565+ return - 1 , err
2566+ }
2567+
2568+ if err := tarSplitFile .Sync (); err != nil {
2569+ return - 1 , fmt .Errorf ("sync tar split file: %w" , err )
2570+ }
2571+
2572+ applyDiffResultToLayer (r , layer , layerOptions , result )
25512573
25522574 err = r .saveFor (layer )
25532575
2554- return size , err
2576+ return result .size , err
2577+ }
2578+
2579+ func applyDiffResultToLayer (r * layerStore , layer * Layer , layerOptions * LayerOptions , result * applyDiffResult ) {
2580+ updateDigestMap (& r .bycompressedsum , layer .CompressedDigest , result .compressedDigest , layer .ID )
2581+ layer .CompressedDigest = result .compressedDigest
2582+ if layerOptions != nil && layerOptions .OriginalDigest != "" && layerOptions .OriginalSize != nil {
2583+ layer .CompressedSize = * layerOptions .OriginalSize
2584+ } else {
2585+ layer .CompressedSize = result .compressedSize
2586+ }
2587+ updateDigestMap (& r .byuncompressedsum , layer .UncompressedDigest , result .uncompressedDigest , layer .ID )
2588+ layer .UncompressedDigest = result .uncompressedDigest
2589+ layer .UncompressedSize = result .uncompressedSize
2590+ layer .CompressionType = result .compressionType
2591+ layer .UIDs = result .uids
2592+ layer .GIDs = result .gids
25552593}
25562594
25572595// Requires (startReading or?) startWriting.
0 commit comments