@@ -14,7 +14,7 @@ use fn_error_context::context;
1414use ostree:: { gio, glib} ;
1515use ostree_container:: OstreeImageReference ;
1616use ostree_ext:: container as ostree_container;
17- use ostree_ext:: container:: store:: { ImportProgress , PrepareResult } ;
17+ use ostree_ext:: container:: store:: { ImageImporter , ImportProgress , PrepareResult , PreparedImport } ;
1818use ostree_ext:: oci_spec:: image:: { Descriptor , Digest } ;
1919use ostree_ext:: ostree:: Deployment ;
2020use ostree_ext:: ostree:: { self , Sysroot } ;
@@ -301,15 +301,45 @@ async fn handle_layer_progress_print(
301301 prog
302302}
303303
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 (
307339 repo : & ostree:: Repo ,
308340 imgref : & ImageReference ,
309341 target_imgref : Option < & OstreeImageReference > ,
310- quiet : bool ,
311- prog : ProgressWriter ,
312- ) -> Result < Box < ImageState > > {
342+ ) -> Result < PreparedPullResult > {
313343 let ostree_imgref = & OstreeImageReference :: from ( imgref. clone ( ) ) ;
314344 let mut imp = new_importer ( repo, ostree_imgref) . await ?;
315345 if let Some ( target) = target_imgref {
@@ -318,7 +348,7 @@ pub(crate) async fn pull(
318348 let prep = match imp. prepare ( ) . await ? {
319349 PrepareResult :: AlreadyPresent ( c) => {
320350 println ! ( "No changes in {imgref:#} => {}" , c. manifest_digest) ;
321- return Ok ( Box :: new ( ( * c) . into ( ) ) ) ;
351+ return Ok ( PreparedPullResult :: AlreadyPresent ( Box :: new ( ( * c) . into ( ) ) ) ) ;
322352 }
323353 PrepareResult :: Ready ( p) => p,
324354 } ;
@@ -328,30 +358,49 @@ pub(crate) async fn pull(
328358 }
329359 ostree_ext:: cli:: print_layer_status ( & prep) ;
330360 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+
340389 let printer = tokio:: task:: spawn ( async move {
341390 handle_layer_progress_print (
342391 layer_progress,
343392 layer_byte_progress,
344393 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 ,
349398 prog,
350399 quiet,
351400 )
352401 . await
353402 } ) ;
354- let import = imp. import ( prep) . await ;
403+ let import = prepared_image . imp . import ( prepared_image . prep ) . await ;
355404 let prog = printer. await ?;
356405 // Both the progress and the import are done, so import is done as well
357406 prog. send ( Event :: ProgressSteps {
@@ -371,6 +420,7 @@ pub(crate) async fn pull(
371420 } )
372421 . await ;
373422 let import = import?;
423+ let ostree_imgref = & OstreeImageReference :: from ( imgref. clone ( ) ) ;
374424 let wrote_imgref = target_imgref. as_ref ( ) . unwrap_or ( & ostree_imgref) ;
375425
376426 if let Some ( msg) =
@@ -382,23 +432,26 @@ pub(crate) async fn pull(
382432 Ok ( Box :: new ( ( * import) . into ( ) ) )
383433}
384434
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 ?) ,
393454 }
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 ( ( ) )
402455}
403456
404457pub ( crate ) async fn wipe_ostree ( sysroot : Sysroot ) -> Result < ( ) > {
0 commit comments