@@ -19,11 +19,13 @@ use ostree_ext::oci_spec::image::{Descriptor, Digest};
1919use ostree_ext:: ostree:: Deployment ;
2020use ostree_ext:: ostree:: { self , Sysroot } ;
2121use ostree_ext:: sysroot:: SysrootLock ;
22+ use ostree_ext:: tokio_util:: spawn_blocking_cancellable_flatten;
2223
2324use crate :: spec:: ImageReference ;
2425use crate :: spec:: { BootOrder , HostSpec } ;
2526use crate :: status:: labels_of_config;
2627use crate :: store:: Storage ;
28+ use crate :: utils:: async_task_with_spinner;
2729
2830// TODO use https://github.com/ostreedev/ostree-rs-ext/pull/493/commits/afc1837ff383681b947de30c0cefc70080a4f87a
2931const BASE_IMAGE_PREFIX : & str = "ostree/container/baseimage/bootc" ;
@@ -211,12 +213,14 @@ async fn handle_layer_progress_print(
211213 let elapsed = end. duration_since ( start) ;
212214 let persec = total_read as f64 / elapsed. as_secs_f64 ( ) ;
213215 let persec = indicatif:: HumanBytes ( persec as u64 ) ;
214- println ! (
216+ if let Err ( e ) = bar . println ( & format ! (
215217 "Fetched layers: {} in {} ({}/s)" ,
216218 indicatif:: HumanBytes ( total_read) ,
217219 indicatif:: HumanDuration ( elapsed) ,
218220 persec,
219- ) ;
221+ ) ) {
222+ tracing:: warn!( "writing to stdout: {e}" ) ;
223+ }
220224}
221225
222226/// Wrapper for pulling a container image, wiring up status output.
@@ -373,8 +377,6 @@ async fn deploy(
373377 image : & ImageState ,
374378 origin : & glib:: KeyFile ,
375379) -> Result < Deployment > {
376- let stateroot = Some ( stateroot) ;
377- let mut opts = ostree:: SysrootDeployTreeOpts :: default ( ) ;
378380 // Compute the kernel argument overrides. In practice today this API is always expecting
379381 // a merge deployment. The kargs code also always looks at the booted root (which
380382 // is a distinct minor issue, but not super important as right now the install path
@@ -384,26 +386,49 @@ async fn deploy(
384386 } else {
385387 None
386388 } ;
387- // Because the C API expects a Vec<&str>, we need to generate a new Vec<>
388- // that borrows.
389- let override_kargs = override_kargs
390- . as_deref ( )
391- . map ( |v| v. iter ( ) . map ( |s| s. as_str ( ) ) . collect :: < Vec < _ > > ( ) ) ;
392- if let Some ( kargs) = override_kargs. as_deref ( ) {
393- opts. override_kernel_argv = Some ( & kargs) ;
394- }
395- // Copy to move into thread
396- let cancellable = gio:: Cancellable :: NONE ;
397- return sysroot
398- . stage_tree_with_options (
399- stateroot,
400- image. ostree_commit . as_str ( ) ,
401- Some ( origin) ,
402- merge_deployment,
403- & opts,
404- cancellable,
405- )
406- . map_err ( Into :: into) ;
389+ // Clone all the things to move to worker thread
390+ let sysroot_clone = sysroot. sysroot . clone ( ) ;
391+ // ostree::Deployment is incorrently !Send 😢 so convert it to an integer
392+ let merge_deployment = merge_deployment. map ( |d| d. index ( ) as usize ) ;
393+ let stateroot = stateroot. to_string ( ) ;
394+ let ostree_commit = image. ostree_commit . to_string ( ) ;
395+ // GKeyFile also isn't Send! So we serialize that as a string...
396+ let origin_data = origin. to_data ( ) ;
397+ let r = async_task_with_spinner (
398+ "Deploying" ,
399+ spawn_blocking_cancellable_flatten ( move |cancellable| -> Result < _ > {
400+ let sysroot = sysroot_clone;
401+ let stateroot = Some ( stateroot) ;
402+ let mut opts = ostree:: SysrootDeployTreeOpts :: default ( ) ;
403+
404+ // Because the C API expects a Vec<&str>, we need to generate a new Vec<>
405+ // that borrows.
406+ let override_kargs = override_kargs
407+ . as_deref ( )
408+ . map ( |v| v. iter ( ) . map ( |s| s. as_str ( ) ) . collect :: < Vec < _ > > ( ) ) ;
409+ if let Some ( kargs) = override_kargs. as_deref ( ) {
410+ opts. override_kernel_argv = Some ( & kargs) ;
411+ }
412+ let deployments = sysroot. deployments ( ) ;
413+ let merge_deployment = merge_deployment. map ( |m| & deployments[ m] ) ;
414+ let origin = glib:: KeyFile :: new ( ) ;
415+ origin. load_from_data ( & origin_data, glib:: KeyFileFlags :: NONE ) ?;
416+ let d = sysroot. stage_tree_with_options (
417+ stateroot. as_deref ( ) ,
418+ & ostree_commit,
419+ Some ( & origin) ,
420+ merge_deployment,
421+ & opts,
422+ Some ( cancellable) ,
423+ ) ?;
424+ Ok ( d. index ( ) )
425+ } ) ,
426+ )
427+ . await ?;
428+ // SAFETY: We must have a staged deployment
429+ let staged = sysroot. staged_deployment ( ) . unwrap ( ) ;
430+ assert_eq ! ( staged. index( ) , r) ;
431+ Ok ( staged)
407432}
408433
409434#[ context( "Generating origin" ) ]
0 commit comments