@@ -26,11 +26,11 @@ use schemars::schema_for;
2626use serde:: { Deserialize , Serialize } ;
2727
2828use crate :: deploy:: RequiredHostSpec ;
29- use crate :: lints;
3029use crate :: progress_jsonl:: { ProgressWriter , RawProgressFd } ;
3130use crate :: spec:: Host ;
3231use crate :: spec:: ImageReference ;
3332use crate :: utils:: sigpolicy_from_opt;
33+ use crate :: { lints, reboot} ;
3434
3535/// Shared progress options
3636#[ derive( Debug , Parser , PartialEq , Eq ) ]
@@ -536,7 +536,7 @@ pub(crate) enum Opt {
536536 Note on Rollbacks and the `/etc` Directory:
537537
538538 When you perform a rollback (e.g., with `bootc rollback`), any
539- changes made to files in the `/etc` directory won’ t carry over
539+ changes made to files in the `/etc` directory won' t carry over
540540 to the rolled-back deployment. The `/etc` files will revert
541541 to their state from that previous deployment instead.
542542
@@ -835,6 +835,31 @@ async fn upgrade(opts: UpgradeOpts) -> Result<()> {
835835 println ! ( "Staged update present, not changed." ) ;
836836
837837 if opts. apply {
838+ // Check if we can do a soft-reboot instead of a full reboot
839+ let can_soft_reboot = host
840+ . status
841+ . staged
842+ . as_ref ( )
843+ . map ( |s| s. soft_reboot_capable )
844+ . unwrap_or ( false ) ;
845+
846+ if can_soft_reboot {
847+ println ! ( "Staged deployment is soft-reboot capable, performing soft-reboot..." ) ;
848+
849+ // Find the staged deployment
850+ let deployments_list = sysroot. deployments ( ) ;
851+ let staged_deployment = deployments_list
852+ . iter ( )
853+ . find ( |d| d. is_staged ( ) )
854+ . ok_or_else ( || anyhow:: anyhow!( "Failed to find staged deployment" ) ) ?;
855+
856+ // Prepare the soft-reboot using native ostree bindings
857+ let cancellable = ostree:: gio:: Cancellable :: NONE ;
858+ sysroot
859+ . sysroot
860+ . deployment_prepare_next_root ( staged_deployment, false , cancellable)
861+ . context ( "Failed to prepare soft-reboot" ) ?;
862+ }
838863 crate :: reboot:: reboot ( ) ?;
839864 }
840865 } else if booted_unchanged {
@@ -931,6 +956,33 @@ async fn switch(opts: SwitchOpts) -> Result<()> {
931956 sysroot. update_mtime ( ) ?;
932957
933958 if opts. apply {
959+ // Get updated status to check for soft-reboot capability
960+ let ( _updated_deployments, updated_host) =
961+ crate :: status:: get_status ( sysroot, Some ( & booted_deployment) ) ?;
962+ let can_soft_reboot = updated_host
963+ . status
964+ . staged
965+ . as_ref ( )
966+ . map ( |s| s. soft_reboot_capable )
967+ . unwrap_or ( false ) ;
968+
969+ if can_soft_reboot {
970+ println ! ( "Staged deployment is soft-reboot capable, performing soft-reboot..." ) ;
971+
972+ // Find the staged deployment
973+ let deployments_list = sysroot. deployments ( ) ;
974+ let staged_deployment = deployments_list
975+ . iter ( )
976+ . find ( |d| d. is_staged ( ) )
977+ . ok_or_else ( || anyhow:: anyhow!( "Failed to find staged deployment" ) ) ?;
978+
979+ // Prepare the soft-reboot using native ostree bindings
980+ let cancellable = ostree:: gio:: Cancellable :: NONE ;
981+ sysroot
982+ . sysroot
983+ . deployment_prepare_next_root ( staged_deployment, false , cancellable)
984+ . context ( "Failed to prepare soft-reboot" ) ?;
985+ }
934986 crate :: reboot:: reboot ( ) ?;
935987 }
936988
@@ -941,10 +993,40 @@ async fn switch(opts: SwitchOpts) -> Result<()> {
941993#[ context( "Rollback" ) ]
942994async fn rollback ( opts : RollbackOpts ) -> Result < ( ) > {
943995 let sysroot = & get_storage ( ) . await ?;
944- crate :: deploy:: rollback ( sysroot) . await ?;
945996
946997 if opts. apply {
998+ // Get status before rollback to check soft-reboot capability
999+ let ( _booted_deployment, _deployments, host) =
1000+ crate :: status:: get_status_require_booted ( sysroot) ?;
1001+ let can_soft_reboot = host
1002+ . status
1003+ . rollback
1004+ . as_ref ( )
1005+ . map ( |r| r. soft_reboot_capable )
1006+ . unwrap_or ( false ) ;
1007+
1008+ // Perform the rollback
1009+ crate :: deploy:: rollback ( sysroot) . await ?;
1010+
1011+ if can_soft_reboot {
1012+ println ! ( "Rollback deployment is soft-reboot capable, performing soft-reboot..." ) ;
1013+
1014+ // For rollback, get the current first deployment after rollback
1015+ let deployments_list = sysroot. deployments ( ) ;
1016+ let target_deployment = deployments_list
1017+ . first ( )
1018+ . ok_or_else ( || anyhow:: anyhow!( "No deployments found after rollback" ) ) ?;
1019+
1020+ // Prepare the soft-reboot using native ostree bindings
1021+ let cancellable = ostree:: gio:: Cancellable :: NONE ;
1022+ sysroot
1023+ . sysroot
1024+ . deployment_prepare_next_root ( target_deployment, false , cancellable)
1025+ . context ( "Failed to prepare soft-reboot" ) ?;
1026+ }
9471027 crate :: reboot:: reboot ( ) ?;
1028+ } else {
1029+ crate :: deploy:: rollback ( sysroot) . await ?;
9481030 }
9491031
9501032 Ok ( ( ) )
0 commit comments