@@ -126,6 +126,13 @@ type Layer struct {
126
126
// as a DiffID.
127
127
UncompressedDigest digest.Digest `json:"diff-digest,omitempty"`
128
128
129
+ // TOCDigest represents the digest of the Table of Contents (TOC) of the blob.
130
+ // This digest is utilized when the UncompressedDigest is not
131
+ // validated during the partial image pull process, but the
132
+ // TOC itself is validated.
133
+ // It serves as an alternative reference under these specific conditions.
134
+ TOCDigest digest.Digest `json:"toc-digest,omitempty"`
135
+
129
136
// UncompressedSize is the length of the blob that was last passed to
130
137
// ApplyDiff() or create(), after we decompressed it. If
131
138
// UncompressedDigest is not set, this should be treated as if it were
@@ -228,6 +235,10 @@ type roLayerStore interface {
228
235
// specified uncompressed digest value recorded for them.
229
236
LayersByUncompressedDigest (d digest.Digest ) ([]Layer , error )
230
237
238
+ // LayersByTOCDigest returns a slice of the layers with the
239
+ // specified uncompressed digest value recorded for them.
240
+ LayersByTOCDigest (d digest.Digest ) ([]Layer , error )
241
+
231
242
// Layers returns a slice of the known layers.
232
243
Layers () ([]Layer , error )
233
244
}
@@ -296,13 +307,13 @@ type rwLayerStore interface {
296
307
297
308
// ApplyDiffWithDiffer applies the changes through the differ callback function.
298
309
// If to is the empty string, then a staging directory is created by the driver.
299
- ApplyDiffWithDiffer (to string , options * drivers.ApplyDiffOpts , differ drivers.Differ ) (* drivers.DriverWithDifferOutput , error )
310
+ ApplyDiffWithDiffer (to string , options * drivers.ApplyDiffWithDifferOpts , differ drivers.Differ ) (* drivers.DriverWithDifferOutput , error )
300
311
301
312
// CleanupStagingDirectory cleanups the staging directory. It can be used to cleanup the staging directory on errors
302
313
CleanupStagingDirectory (stagingDirectory string ) error
303
314
304
315
// ApplyDiffFromStagingDirectory uses stagingDirectory to create the diff.
305
- ApplyDiffFromStagingDirectory (id , stagingDirectory string , diffOutput * drivers.DriverWithDifferOutput , options * drivers.ApplyDiffOpts ) error
316
+ ApplyDiffFromStagingDirectory (id , stagingDirectory string , diffOutput * drivers.DriverWithDifferOutput , options * drivers.ApplyDiffWithDifferOpts ) error
306
317
307
318
// DifferTarget gets the location where files are stored for the layer.
308
319
DifferTarget (id string ) (string , error )
@@ -337,6 +348,7 @@ type layerStore struct {
337
348
bymount map [string ]* Layer
338
349
bycompressedsum map [digest.Digest ][]string
339
350
byuncompressedsum map [digest.Digest ][]string
351
+ bytocsum map [digest.Digest ][]string
340
352
layerspathsModified [numLayerLocationIndex ]time.Time
341
353
342
354
// FIXME: This field is only set when constructing layerStore, but locking rules of the driver
@@ -366,6 +378,7 @@ func copyLayer(l *Layer) *Layer {
366
378
CompressedSize : l .CompressedSize ,
367
379
UncompressedDigest : l .UncompressedDigest ,
368
380
UncompressedSize : l .UncompressedSize ,
381
+ TOCDigest : l .TOCDigest ,
369
382
CompressionType : l .CompressionType ,
370
383
ReadOnly : l .ReadOnly ,
371
384
volatileStore : l .volatileStore ,
@@ -745,6 +758,7 @@ func (r *layerStore) load(lockedForWriting bool) (bool, error) {
745
758
names := make (map [string ]* Layer )
746
759
compressedsums := make (map [digest.Digest ][]string )
747
760
uncompressedsums := make (map [digest.Digest ][]string )
761
+ tocsums := make (map [digest.Digest ][]string )
748
762
var errorToResolveBySaving error // == nil; if there are multiple errors, this is one of them.
749
763
if r .lockfile .IsReadWrite () {
750
764
selinux .ClearLabels ()
@@ -765,6 +779,9 @@ func (r *layerStore) load(lockedForWriting bool) (bool, error) {
765
779
if layer .UncompressedDigest != "" {
766
780
uncompressedsums [layer .UncompressedDigest ] = append (uncompressedsums [layer .UncompressedDigest ], layer .ID )
767
781
}
782
+ if layer .TOCDigest != "" {
783
+ tocsums [layer .TOCDigest ] = append (tocsums [layer .TOCDigest ], layer .ID )
784
+ }
768
785
if layer .MountLabel != "" {
769
786
selinux .ReserveLabel (layer .MountLabel )
770
787
}
@@ -792,6 +809,7 @@ func (r *layerStore) load(lockedForWriting bool) (bool, error) {
792
809
r .byname = names
793
810
r .bycompressedsum = compressedsums
794
811
r .byuncompressedsum = uncompressedsums
812
+ r .bytocsum = tocsums
795
813
796
814
// Load and merge information about which layers are mounted, and where.
797
815
if r .lockfile .IsReadWrite () {
@@ -1112,7 +1130,7 @@ func (r *layerStore) Size(name string) (int64, error) {
1112
1130
// We use the presence of a non-empty digest as an indicator that the size value was intentionally set, and that
1113
1131
// a zero value is not just present because it was never set to anything else (which can happen if the layer was
1114
1132
// created by a version of this library that didn't keep track of digest and size information).
1115
- if layer .UncompressedDigest != "" {
1133
+ if layer .TOCDigest != "" || layer . UncompressedDigest != "" {
1116
1134
return layer .UncompressedSize , nil
1117
1135
}
1118
1136
return - 1 , nil
@@ -1201,6 +1219,9 @@ func (r *layerStore) PutAdditionalLayer(id string, parentLayer *Layer, names []s
1201
1219
if layer .UncompressedDigest != "" {
1202
1220
r .byuncompressedsum [layer .UncompressedDigest ] = append (r .byuncompressedsum [layer .UncompressedDigest ], layer .ID )
1203
1221
}
1222
+ if layer .TOCDigest != "" {
1223
+ r .bytocsum [layer .TOCDigest ] = append (r .bytocsum [layer .TOCDigest ], layer .ID )
1224
+ }
1204
1225
if err := r .saveFor (layer ); err != nil {
1205
1226
if e := r .Delete (layer .ID ); e != nil {
1206
1227
logrus .Errorf ("While recovering from a failure to save layers, error deleting layer %#v: %v" , id , e )
@@ -1251,6 +1272,7 @@ func (r *layerStore) create(id string, parentLayer *Layer, names []string, mount
1251
1272
templateCompressedDigest digest.Digest
1252
1273
templateCompressedSize int64
1253
1274
templateUncompressedDigest digest.Digest
1275
+ templateTOCDigest digest.Digest
1254
1276
templateUncompressedSize int64
1255
1277
templateCompressionType archive.Compression
1256
1278
templateUIDs , templateGIDs []uint32
@@ -1263,6 +1285,7 @@ func (r *layerStore) create(id string, parentLayer *Layer, names []string, mount
1263
1285
}
1264
1286
templateMetadata = templateLayer .Metadata
1265
1287
templateIDMappings = idtools .NewIDMappingsFromMaps (templateLayer .UIDMap , templateLayer .GIDMap )
1288
+ templateTOCDigest = templateLayer .TOCDigest
1266
1289
templateCompressedDigest , templateCompressedSize = templateLayer .CompressedDigest , templateLayer .CompressedSize
1267
1290
templateUncompressedDigest , templateUncompressedSize = templateLayer .UncompressedDigest , templateLayer .UncompressedSize
1268
1291
templateCompressionType = templateLayer .CompressionType
@@ -1291,6 +1314,7 @@ func (r *layerStore) create(id string, parentLayer *Layer, names []string, mount
1291
1314
CompressedDigest : templateCompressedDigest ,
1292
1315
CompressedSize : templateCompressedSize ,
1293
1316
UncompressedDigest : templateUncompressedDigest ,
1317
+ TOCDigest : templateTOCDigest ,
1294
1318
UncompressedSize : templateUncompressedSize ,
1295
1319
CompressionType : templateCompressionType ,
1296
1320
UIDs : templateUIDs ,
@@ -1413,6 +1437,9 @@ func (r *layerStore) create(id string, parentLayer *Layer, names []string, mount
1413
1437
if layer .UncompressedDigest != "" {
1414
1438
r .byuncompressedsum [layer .UncompressedDigest ] = append (r .byuncompressedsum [layer .UncompressedDigest ], layer .ID )
1415
1439
}
1440
+ if layer .TOCDigest != "" {
1441
+ r .bytocsum [layer .TOCDigest ] = append (r .bytocsum [layer .TOCDigest ], layer .ID )
1442
+ }
1416
1443
}
1417
1444
1418
1445
delete (layer .Flags , incompleteFlag )
@@ -2197,6 +2224,25 @@ func (r *layerStore) DiffSize(from, to string) (size int64, err error) {
2197
2224
return r .driver .DiffSize (to , r .layerMappings (toLayer ), from , r .layerMappings (fromLayer ), toLayer .MountLabel )
2198
2225
}
2199
2226
2227
+ func updateDigestMap (m * map [digest.Digest ][]string , oldvalue , newvalue digest.Digest , id string ) {
2228
+ var newList []string
2229
+ if oldvalue != "" {
2230
+ for _ , value := range (* m )[oldvalue ] {
2231
+ if value != id {
2232
+ newList = append (newList , value )
2233
+ }
2234
+ }
2235
+ if len (newList ) > 0 {
2236
+ (* m )[oldvalue ] = newList
2237
+ } else {
2238
+ delete (* m , oldvalue )
2239
+ }
2240
+ }
2241
+ if newvalue != "" {
2242
+ (* m )[newvalue ] = append ((* m )[newvalue ], id )
2243
+ }
2244
+ }
2245
+
2200
2246
// Requires startWriting.
2201
2247
func (r * layerStore ) ApplyDiff (to string , diff io.Reader ) (size int64 , err error ) {
2202
2248
return r .applyDiffWithOptions (to , nil , diff )
@@ -2313,24 +2359,6 @@ func (r *layerStore) applyDiffWithOptions(to string, layerOptions *LayerOptions,
2313
2359
uncompressedDigest = uncompressedDigester .Digest ()
2314
2360
}
2315
2361
2316
- updateDigestMap := func (m * map [digest.Digest ][]string , oldvalue , newvalue digest.Digest , id string ) {
2317
- var newList []string
2318
- if oldvalue != "" {
2319
- for _ , value := range (* m )[oldvalue ] {
2320
- if value != id {
2321
- newList = append (newList , value )
2322
- }
2323
- }
2324
- if len (newList ) > 0 {
2325
- (* m )[oldvalue ] = newList
2326
- } else {
2327
- delete (* m , oldvalue )
2328
- }
2329
- }
2330
- if newvalue != "" {
2331
- (* m )[newvalue ] = append ((* m )[newvalue ], id )
2332
- }
2333
- }
2334
2362
updateDigestMap (& r .bycompressedsum , layer .CompressedDigest , compressedDigest , layer .ID )
2335
2363
layer .CompressedDigest = compressedDigest
2336
2364
layer .CompressedSize = compressedCounter .Count
@@ -2372,7 +2400,7 @@ func (r *layerStore) DifferTarget(id string) (string, error) {
2372
2400
}
2373
2401
2374
2402
// Requires startWriting.
2375
- func (r * layerStore ) ApplyDiffFromStagingDirectory (id , stagingDirectory string , diffOutput * drivers.DriverWithDifferOutput , options * drivers.ApplyDiffOpts ) error {
2403
+ func (r * layerStore ) ApplyDiffFromStagingDirectory (id , stagingDirectory string , diffOutput * drivers.DriverWithDifferOutput , options * drivers.ApplyDiffWithDifferOpts ) error {
2376
2404
ddriver , ok := r .driver .(drivers.DriverWithDiffer )
2377
2405
if ! ok {
2378
2406
return ErrNotSupported
@@ -2382,20 +2410,35 @@ func (r *layerStore) ApplyDiffFromStagingDirectory(id, stagingDirectory string,
2382
2410
return ErrLayerUnknown
2383
2411
}
2384
2412
if options == nil {
2385
- options = & drivers.ApplyDiffOpts {
2386
- Mappings : r .layerMappings (layer ),
2387
- MountLabel : layer .MountLabel ,
2413
+ options = & drivers.ApplyDiffWithDifferOpts {
2414
+ ApplyDiffOpts : drivers.ApplyDiffOpts {
2415
+ Mappings : r .layerMappings (layer ),
2416
+ MountLabel : layer .MountLabel ,
2417
+ },
2418
+ Flags : nil ,
2388
2419
}
2389
2420
}
2421
+
2390
2422
err := ddriver .ApplyDiffFromStagingDirectory (layer .ID , layer .Parent , stagingDirectory , diffOutput , options )
2391
2423
if err != nil {
2392
2424
return err
2393
2425
}
2394
2426
layer .UIDs = diffOutput .UIDs
2395
2427
layer .GIDs = diffOutput .GIDs
2428
+ updateDigestMap (& r .byuncompressedsum , layer .UncompressedDigest , diffOutput .UncompressedDigest , layer .ID )
2396
2429
layer .UncompressedDigest = diffOutput .UncompressedDigest
2430
+ updateDigestMap (& r .bytocsum , diffOutput .TOCDigest , diffOutput .TOCDigest , layer .ID )
2431
+ layer .TOCDigest = diffOutput .TOCDigest
2397
2432
layer .UncompressedSize = diffOutput .Size
2398
2433
layer .Metadata = diffOutput .Metadata
2434
+ if options != nil && options .Flags != nil {
2435
+ if layer .Flags == nil {
2436
+ layer .Flags = make (map [string ]interface {})
2437
+ }
2438
+ for k , v := range options .Flags {
2439
+ layer .Flags [k ] = v
2440
+ }
2441
+ }
2399
2442
if len (diffOutput .TarSplit ) != 0 {
2400
2443
tsdata := bytes.Buffer {}
2401
2444
compressor , err := pgzip .NewWriterLevel (& tsdata , pgzip .BestSpeed )
@@ -2432,7 +2475,7 @@ func (r *layerStore) ApplyDiffFromStagingDirectory(id, stagingDirectory string,
2432
2475
}
2433
2476
2434
2477
// Requires startWriting.
2435
- func (r * layerStore ) ApplyDiffWithDiffer (to string , options * drivers.ApplyDiffOpts , differ drivers.Differ ) (* drivers.DriverWithDifferOutput , error ) {
2478
+ func (r * layerStore ) ApplyDiffWithDiffer (to string , options * drivers.ApplyDiffWithDifferOpts , differ drivers.Differ ) (* drivers.DriverWithDifferOutput , error ) {
2436
2479
ddriver , ok := r .driver .(drivers.DriverWithDiffer )
2437
2480
if ! ok {
2438
2481
return nil , ErrNotSupported
@@ -2448,9 +2491,11 @@ func (r *layerStore) ApplyDiffWithDiffer(to string, options *drivers.ApplyDiffOp
2448
2491
return nil , ErrLayerUnknown
2449
2492
}
2450
2493
if options == nil {
2451
- options = & drivers.ApplyDiffOpts {
2452
- Mappings : r .layerMappings (layer ),
2453
- MountLabel : layer .MountLabel ,
2494
+ options = & drivers.ApplyDiffWithDifferOpts {
2495
+ ApplyDiffOpts : drivers.ApplyDiffOpts {
2496
+ Mappings : r .layerMappings (layer ),
2497
+ MountLabel : layer .MountLabel ,
2498
+ },
2454
2499
}
2455
2500
}
2456
2501
output , err := ddriver .ApplyDiffWithDiffer (layer .ID , layer .Parent , options , differ )
@@ -2494,6 +2539,11 @@ func (r *layerStore) LayersByUncompressedDigest(d digest.Digest) ([]Layer, error
2494
2539
return r .layersByDigestMap (r .byuncompressedsum , d )
2495
2540
}
2496
2541
2542
+ // Requires startReading or startWriting.
2543
+ func (r * layerStore ) LayersByTOCDigest (d digest.Digest ) ([]Layer , error ) {
2544
+ return r .layersByDigestMap (r .bytocsum , d )
2545
+ }
2546
+
2497
2547
func closeAll (closes ... func () error ) (rErr error ) {
2498
2548
for _ , f := range closes {
2499
2549
if err := f (); err != nil {
0 commit comments