@@ -7,6 +7,13 @@ use crate::appimage::AppImage;
77use crate :: error:: { Error , Result } ;
88use crate :: update_info:: UpdateInfo ;
99
10+ struct UpdateContext {
11+ source_size : u64 ,
12+ target_size : u64 ,
13+ block_size : usize ,
14+ original_perms : Option < fs:: Permissions > ,
15+ }
16+
1017#[ derive( Debug ) ]
1118pub struct UpdateStats {
1219 pub source_path : PathBuf ,
@@ -124,7 +131,8 @@ impl Updater {
124131 return Ok ( false ) ;
125132 }
126133
127- if !self . overwrite {
134+ let same_file = self . appimage . path ( ) == output_path;
135+ if !same_file && !self . overwrite {
128136 return Err ( Error :: AppImage ( format ! (
129137 "Output file already exists: {}" ,
130138 output_path. display( )
@@ -175,29 +183,67 @@ impl Updater {
175183 return Ok ( ( output_path, stats) ) ;
176184 }
177185
178- if !self . overwrite {
186+ let same_file = self . appimage . path ( ) == output_path;
187+ if !same_file && !self . overwrite {
179188 return Err ( Error :: AppImage ( format ! (
180189 "Output file already exists: {}" ,
181190 output_path. display( )
182191 ) ) ) ;
183192 }
184193 }
185194
186- let original_perms = fs:: metadata ( self . appimage . path ( ) )
187- . map ( |m| m. permissions ( ) )
188- . ok ( ) ;
195+ let ctx = UpdateContext {
196+ source_size : self . source_size ( ) ,
197+ target_size : control. length ,
198+ block_size : control. blocksize ,
199+ original_perms : fs:: metadata ( self . appimage . path ( ) )
200+ . map ( |m| m. permissions ( ) )
201+ . ok ( ) ,
202+ } ;
203+
204+ let source_path = self . appimage . path ( ) ;
205+ let same_file = source_path == output_path;
206+
207+ let ( actual_source_path, backup_path) = if same_file {
208+ let filename = source_path
209+ . file_name ( )
210+ . and_then ( |n| n. to_str ( ) )
211+ . unwrap_or ( "appimage" ) ;
212+ let backup = source_path. with_file_name ( format ! ( "{}.old" , filename) ) ;
213+ let _ = fs:: remove_file ( & backup) ;
214+ fs:: rename ( source_path, & backup) ?;
215+ ( backup. clone ( ) , Some ( backup) )
216+ } else {
217+ ( source_path. to_path_buf ( ) , None )
218+ } ;
219+
220+ let result = self . do_update ( & actual_source_path, & output_path, & zsync_url, & ctx) ;
189221
190- let source_size = self . source_size ( ) ;
191- let target_size = control. length ;
192- let block_size = control. blocksize ;
222+ match result {
223+ Ok ( stats) => Ok ( ( output_path, stats) ) ,
224+ Err ( e) => {
225+ if let Some ( backup) = backup_path {
226+ let _ = fs:: rename ( & backup, source_path) ;
227+ }
228+ Err ( e)
229+ }
230+ }
231+ }
193232
194- let assembly = ZsyncAssembly :: from_url ( & zsync_url, & output_path)
233+ fn do_update (
234+ & self ,
235+ source_path : & Path ,
236+ output_path : & Path ,
237+ zsync_url : & str ,
238+ ctx : & UpdateContext ,
239+ ) -> Result < UpdateStats > {
240+ let assembly = ZsyncAssembly :: from_url ( zsync_url, output_path)
195241 . map_err ( |e| Error :: Zsync ( format ! ( "Failed to initialize zsync: {}" , e) ) ) ?;
196242
197243 let mut assembly = assembly;
198244
199245 let blocks_reused = assembly
200- . submit_source_file ( self . appimage . path ( ) )
246+ . submit_source_file ( source_path )
201247 . map_err ( |e| Error :: Zsync ( format ! ( "Failed to submit source file: {}" , e) ) ) ?;
202248
203249 let self_blocks = assembly
@@ -213,21 +259,19 @@ impl Updater {
213259 . complete ( )
214260 . map_err ( |e| Error :: Zsync ( format ! ( "Failed to complete assembly: {}" , e) ) ) ?;
215261
216- if let Some ( perms) = original_perms {
217- fs:: set_permissions ( & output_path, perms) ?;
262+ if let Some ( ref perms) = ctx . original_perms {
263+ fs:: set_permissions ( output_path, perms. clone ( ) ) ?;
218264 }
219265
220- let stats = UpdateStats {
266+ Ok ( UpdateStats {
221267 source_path : self . appimage . path ( ) . to_path_buf ( ) ,
222- source_size,
223- target_path : output_path. clone ( ) ,
224- target_size,
268+ source_size : ctx . source_size ,
269+ target_path : output_path. to_path_buf ( ) ,
270+ target_size : ctx . target_size ,
225271 blocks_reused,
226272 blocks_downloaded,
227- block_size,
228- } ;
229-
230- Ok ( ( output_path, stats) )
273+ block_size : ctx. block_size ,
274+ } )
231275 }
232276
233277 pub fn output_path ( & self ) -> Result < PathBuf > {
0 commit comments