@@ -25,6 +25,9 @@ pub fn snapshot(
2525 }
2626 copy_dir_recursive ( & src, & dst) ?;
2727 } else if src. is_file ( ) {
28+ if let Some ( parent) = dst. parent ( ) {
29+ std:: fs:: create_dir_all ( parent) ?;
30+ }
2831 std:: fs:: copy ( & src, & dst) ?;
2932 }
3033 // Missing items are OK — not all items exist on all platforms
@@ -69,36 +72,55 @@ pub fn restore(
6972 let src = data_dir. join ( item) ;
7073 let dst = holding_dir. path ( ) . join ( item) ;
7174 if src. exists ( ) {
72- if src. is_dir ( ) {
73- copy_dir_recursive ( & src, & dst) ?;
74- std:: fs:: remove_dir_all ( & src) ?;
75+ if let Some ( parent) = dst. parent ( ) {
76+ std:: fs:: create_dir_all ( parent) ?;
77+ }
78+ let copy_result = if src. is_dir ( ) {
79+ copy_dir_recursive ( & src, & dst)
80+ . and_then ( |_| std:: fs:: remove_dir_all ( & src) )
7581 } else {
76- std:: fs:: copy ( & src, & dst) ?;
77- std:: fs:: remove_file ( & src) ?;
82+ std:: fs:: copy ( & src, & dst)
83+ . map ( |_| ( ) )
84+ . and_then ( |_| std:: fs:: remove_file ( & src) )
85+ } ;
86+ if let Err ( e) = copy_result {
87+ // Phase-2 failure: rollback already-moved items
88+ rollback ( data_dir, holding_dir. path ( ) , & moved) ;
89+ return Err ( DesktopSwapError :: FileCopyFailed (
90+ format ! ( "backup {item} failed: {e}" ) ,
91+ ) ) ;
7892 }
7993 moved. push ( item. to_string ( ) ) ;
8094 }
8195 }
8296
8397 // Phase 3: move staged items into data dir
98+ let mut restored: Vec < String > = Vec :: new ( ) ;
8499 for item in session_items {
85100 let src = stage_dir. path ( ) . join ( item) ;
86101 let dst = data_dir. join ( item) ;
87102 if src. exists ( ) {
88- if src. is_dir ( ) {
89- if let Err ( e) = copy_dir_recursive ( & src, & dst) {
90- // Rollback: restore from holding
91- rollback ( data_dir, holding_dir. path ( ) , & moved) ;
92- return Err ( DesktopSwapError :: FileCopyFailed (
93- format ! ( "restore {item} failed: {e}" ) ,
94- ) ) ;
103+ if let Some ( parent) = dst. parent ( ) {
104+ let _ = std:: fs:: create_dir_all ( parent) ;
105+ }
106+ let result = if src. is_dir ( ) {
107+ copy_dir_recursive ( & src, & dst)
108+ } else {
109+ std:: fs:: copy ( & src, & dst) . map ( |_| ( ) )
110+ } ;
111+ if let Err ( e) = result {
112+ // Phase-3 failure: clean up partially-restored targets, then rollback
113+ for r in & restored {
114+ let p = data_dir. join ( r) ;
115+ if p. is_dir ( ) { let _ = std:: fs:: remove_dir_all ( & p) ; }
116+ else if p. exists ( ) { let _ = std:: fs:: remove_file ( & p) ; }
95117 }
96- } else if let Err ( e) = std:: fs:: copy ( & src, & dst) {
97118 rollback ( data_dir, holding_dir. path ( ) , & moved) ;
98119 return Err ( DesktopSwapError :: FileCopyFailed (
99120 format ! ( "restore {item} failed: {e}" ) ,
100121 ) ) ;
101122 }
123+ restored. push ( item. to_string ( ) ) ;
102124 }
103125 }
104126
0 commit comments