@@ -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" ;
@@ -375,8 +377,6 @@ async fn deploy(
375377 image : & ImageState ,
376378 origin : & glib:: KeyFile ,
377379) -> Result < Deployment > {
378- let stateroot = Some ( stateroot) ;
379- let mut opts = ostree:: SysrootDeployTreeOpts :: default ( ) ;
380380 // Compute the kernel argument overrides. In practice today this API is always expecting
381381 // a merge deployment. The kargs code also always looks at the booted root (which
382382 // is a distinct minor issue, but not super important as right now the install path
@@ -386,26 +386,49 @@ async fn deploy(
386386 } else {
387387 None
388388 } ;
389- // Because the C API expects a Vec<&str>, we need to generate a new Vec<>
390- // that borrows.
391- let override_kargs = override_kargs
392- . as_deref ( )
393- . map ( |v| v. iter ( ) . map ( |s| s. as_str ( ) ) . collect :: < Vec < _ > > ( ) ) ;
394- if let Some ( kargs) = override_kargs. as_deref ( ) {
395- opts. override_kernel_argv = Some ( & kargs) ;
396- }
397- // Copy to move into thread
398- let cancellable = gio:: Cancellable :: NONE ;
399- return sysroot
400- . stage_tree_with_options (
401- stateroot,
402- image. ostree_commit . as_str ( ) ,
403- Some ( origin) ,
404- merge_deployment,
405- & opts,
406- cancellable,
407- )
408- . 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)
409432}
410433
411434#[ context( "Generating origin" ) ]
0 commit comments