@@ -14,7 +14,7 @@ use fn_error_context::context;
14
14
use ostree:: { gio, glib} ;
15
15
use ostree_container:: OstreeImageReference ;
16
16
use ostree_ext:: container as ostree_container;
17
- use ostree_ext:: container:: store:: { ImportProgress , PrepareResult } ;
17
+ use ostree_ext:: container:: store:: { ImageImporter , ImportProgress , PrepareResult , PreparedImport } ;
18
18
use ostree_ext:: oci_spec:: image:: { Descriptor , Digest } ;
19
19
use ostree_ext:: ostree:: Deployment ;
20
20
use ostree_ext:: ostree:: { self , Sysroot } ;
@@ -301,15 +301,45 @@ async fn handle_layer_progress_print(
301
301
prog
302
302
}
303
303
304
- /// Wrapper for pulling a container image, wiring up status output.
305
- #[ context( "Pulling" ) ]
306
- pub ( crate ) async fn pull (
304
+ /// Gather all bound images in all deployments, then prune the image store,
305
+ /// using the gathered images as the roots (that will not be GC'd).
306
+ pub ( crate ) async fn prune_container_store ( sysroot : & Storage ) -> Result < ( ) > {
307
+ let deployments = sysroot. deployments ( ) ;
308
+ let mut all_bound_images = Vec :: new ( ) ;
309
+ for deployment in deployments {
310
+ let bound = crate :: boundimage:: query_bound_images_for_deployment ( sysroot, & deployment) ?;
311
+ all_bound_images. extend ( bound. into_iter ( ) ) ;
312
+ }
313
+ // Convert to a hashset of just the image names
314
+ let image_names = HashSet :: from_iter ( all_bound_images. iter ( ) . map ( |img| img. image . as_str ( ) ) ) ;
315
+ let pruned = sysroot
316
+ . get_ensure_imgstore ( ) ?
317
+ . prune_except_roots ( & image_names)
318
+ . await ?;
319
+ tracing:: debug!( "Pruned images: {}" , pruned. len( ) ) ;
320
+ Ok ( ( ) )
321
+ }
322
+
323
+ pub ( crate ) struct PreparedImportMeta {
324
+ pub imp : ImageImporter ,
325
+ pub prep : Box < PreparedImport > ,
326
+ pub digest : Digest ,
327
+ pub n_layers_to_fetch : usize ,
328
+ pub layers_total : usize ,
329
+ pub bytes_to_fetch : u64 ,
330
+ pub bytes_total : u64 ,
331
+ }
332
+
333
+ pub ( crate ) enum PreparedPullResult {
334
+ Ready ( PreparedImportMeta ) ,
335
+ AlreadyPresent ( Box < ImageState > ) ,
336
+ }
337
+
338
+ pub ( crate ) async fn prepare_for_pull (
307
339
repo : & ostree:: Repo ,
308
340
imgref : & ImageReference ,
309
341
target_imgref : Option < & OstreeImageReference > ,
310
- quiet : bool ,
311
- prog : ProgressWriter ,
312
- ) -> Result < Box < ImageState > > {
342
+ ) -> Result < PreparedPullResult > {
313
343
let ostree_imgref = & OstreeImageReference :: from ( imgref. clone ( ) ) ;
314
344
let mut imp = new_importer ( repo, ostree_imgref) . await ?;
315
345
if let Some ( target) = target_imgref {
@@ -318,7 +348,7 @@ pub(crate) async fn pull(
318
348
let prep = match imp. prepare ( ) . await ? {
319
349
PrepareResult :: AlreadyPresent ( c) => {
320
350
println ! ( "No changes in {imgref:#} => {}" , c. manifest_digest) ;
321
- return Ok ( Box :: new ( ( * c) . into ( ) ) ) ;
351
+ return Ok ( PreparedPullResult :: AlreadyPresent ( Box :: new ( ( * c) . into ( ) ) ) ) ;
322
352
}
323
353
PrepareResult :: Ready ( p) => p,
324
354
} ;
@@ -328,30 +358,49 @@ pub(crate) async fn pull(
328
358
}
329
359
ostree_ext:: cli:: print_layer_status ( & prep) ;
330
360
let layers_to_fetch = prep. layers_to_fetch ( ) . collect :: < Result < Vec < _ > > > ( ) ?;
331
- let n_layers_to_fetch = layers_to_fetch. len ( ) ;
332
- let layers_total = prep. all_layers ( ) . count ( ) ;
333
- let bytes_to_fetch: u64 = layers_to_fetch. iter ( ) . map ( |( l, _) | l. layer . size ( ) ) . sum ( ) ;
334
- let bytes_total: u64 = prep. all_layers ( ) . map ( |l| l. layer . size ( ) ) . sum ( ) ;
335
-
336
- let digest = prep. manifest_digest . clone ( ) ;
337
- let digest_imp = prep. manifest_digest . clone ( ) ;
338
- let layer_progress = imp. request_progress ( ) ;
339
- let layer_byte_progress = imp. request_layer_progress ( ) ;
361
+
362
+ let prepared_image = PreparedImportMeta {
363
+ imp,
364
+ n_layers_to_fetch : layers_to_fetch. len ( ) ,
365
+ layers_total : prep. all_layers ( ) . count ( ) ,
366
+ bytes_to_fetch : layers_to_fetch. iter ( ) . map ( |( l, _) | l. layer . size ( ) ) . sum ( ) ,
367
+ bytes_total : prep. all_layers ( ) . map ( |l| l. layer . size ( ) ) . sum ( ) ,
368
+ digest : prep. manifest_digest . clone ( ) ,
369
+ prep,
370
+ } ;
371
+
372
+ Ok ( PreparedPullResult :: Ready ( prepared_image) )
373
+ }
374
+
375
+ #[ context( "Pulling" ) ]
376
+ pub ( crate ) async fn pull_from_prepared (
377
+ repo : & ostree:: Repo ,
378
+ imgref : & ImageReference ,
379
+ target_imgref : Option < & OstreeImageReference > ,
380
+ quiet : bool ,
381
+ prog : ProgressWriter ,
382
+ mut prepared_image : PreparedImportMeta ,
383
+ ) -> Result < Box < ImageState > > {
384
+ let layer_progress = prepared_image. imp . request_progress ( ) ;
385
+ let layer_byte_progress = prepared_image. imp . request_layer_progress ( ) ;
386
+ let digest = prepared_image. digest . clone ( ) ;
387
+ let digest_imp = prepared_image. digest . clone ( ) ;
388
+
340
389
let printer = tokio:: task:: spawn ( async move {
341
390
handle_layer_progress_print (
342
391
layer_progress,
343
392
layer_byte_progress,
344
393
digest. as_ref ( ) . into ( ) ,
345
- n_layers_to_fetch,
346
- layers_total,
347
- bytes_to_fetch,
348
- bytes_total,
394
+ prepared_image . n_layers_to_fetch ,
395
+ prepared_image . layers_total ,
396
+ prepared_image . bytes_to_fetch ,
397
+ prepared_image . bytes_total ,
349
398
prog,
350
399
quiet,
351
400
)
352
401
. await
353
402
} ) ;
354
- let import = imp. import ( prep) . await ;
403
+ let import = prepared_image . imp . import ( prepared_image . prep ) . await ;
355
404
let prog = printer. await ?;
356
405
// Both the progress and the import are done, so import is done as well
357
406
prog. send ( Event :: ProgressSteps {
@@ -371,6 +420,7 @@ pub(crate) async fn pull(
371
420
} )
372
421
. await ;
373
422
let import = import?;
423
+ let ostree_imgref = & OstreeImageReference :: from ( imgref. clone ( ) ) ;
374
424
let wrote_imgref = target_imgref. as_ref ( ) . unwrap_or ( & ostree_imgref) ;
375
425
376
426
if let Some ( msg) =
@@ -382,23 +432,26 @@ pub(crate) async fn pull(
382
432
Ok ( Box :: new ( ( * import) . into ( ) ) )
383
433
}
384
434
385
- /// Gather all bound images in all deployments, then prune the image store,
386
- /// using the gathered images as the roots (that will not be GC'd).
387
- pub ( crate ) async fn prune_container_store ( sysroot : & Storage ) -> Result < ( ) > {
388
- let deployments = sysroot. deployments ( ) ;
389
- let mut all_bound_images = Vec :: new ( ) ;
390
- for deployment in deployments {
391
- let bound = crate :: boundimage:: query_bound_images_for_deployment ( sysroot, & deployment) ?;
392
- all_bound_images. extend ( bound. into_iter ( ) ) ;
435
+ /// Wrapper for pulling a container image, wiring up status output.
436
+ pub ( crate ) async fn pull (
437
+ repo : & ostree:: Repo ,
438
+ imgref : & ImageReference ,
439
+ target_imgref : Option < & OstreeImageReference > ,
440
+ quiet : bool ,
441
+ prog : ProgressWriter ,
442
+ ) -> Result < Box < ImageState > > {
443
+ match prepare_for_pull ( repo, imgref, target_imgref) . await ? {
444
+ PreparedPullResult :: AlreadyPresent ( existing) => Ok ( existing) ,
445
+ PreparedPullResult :: Ready ( prepared_image_meta) => Ok ( pull_from_prepared (
446
+ repo,
447
+ imgref,
448
+ target_imgref,
449
+ quiet,
450
+ prog,
451
+ prepared_image_meta,
452
+ )
453
+ . await ?) ,
393
454
}
394
- // Convert to a hashset of just the image names
395
- let image_names = HashSet :: from_iter ( all_bound_images. iter ( ) . map ( |img| img. image . as_str ( ) ) ) ;
396
- let pruned = sysroot
397
- . get_ensure_imgstore ( ) ?
398
- . prune_except_roots ( & image_names)
399
- . await ?;
400
- tracing:: debug!( "Pruned images: {}" , pruned. len( ) ) ;
401
- Ok ( ( ) )
402
455
}
403
456
404
457
pub ( crate ) async fn wipe_ostree ( sysroot : Sysroot ) -> Result < ( ) > {
0 commit comments