55//! resolution we need here.
66
77use std:: fs;
8+ use std:: path:: PathBuf ;
89
910use clap:: ValueEnum ;
1011use xshell:: Shell ;
@@ -18,6 +19,41 @@ const CARGO_LOCK: &str = "Cargo.lock";
1819/// The temporary backup file for Cargo.lock.
1920const CARGO_LOCK_BACKUP : & str = "Cargo.lock.backup" ;
2021
22+ /// RAII guard that backs up and restores the original Cargo.lock file.
23+ struct LockFileGuard {
24+ backup_path : PathBuf ,
25+ restore_path : PathBuf ,
26+ }
27+
28+ impl LockFileGuard {
29+ fn new ( sh : & Shell ) -> Result < Self , Box < dyn std:: error:: Error > > {
30+ let source = sh. current_dir ( ) . join ( CARGO_LOCK ) ;
31+ let backup = sh. current_dir ( ) . join ( CARGO_LOCK_BACKUP ) ;
32+
33+ // Backup the existing Cargo.lock file if it exists.
34+ if source. exists ( ) {
35+ fs:: copy ( & source, & backup) ?;
36+ }
37+
38+ Ok ( Self { backup_path : backup, restore_path : source } )
39+ }
40+ }
41+
42+ impl Drop for LockFileGuard {
43+ fn drop ( & mut self ) {
44+ // Restore the existing Cargo.lock file from backup (best effort).
45+ if self . backup_path . exists ( ) {
46+ if let Err ( e) = fs:: copy ( & self . backup_path , & self . restore_path ) {
47+ eprintln ! ( "Warning: Failed to restore Cargo.lock from backup: {}" , e) ;
48+ return ;
49+ }
50+ if let Err ( e) = fs:: remove_file ( & self . backup_path ) {
51+ eprintln ! ( "Warning: Failed to remove Cargo.lock backup: {}" , e) ;
52+ }
53+ }
54+ }
55+ }
56+
2157/// Represents the different types of managed lock files.
2258#[ derive( Debug , Clone , Copy , ValueEnum , Default ) ]
2359pub enum LockFile {
@@ -86,13 +122,13 @@ pub fn run(sh: &Shell) -> Result<(), Box<dyn std::error::Error>> {
86122 let repo_dir = sh. current_dir ( ) ;
87123 quiet_println ( & format ! ( "Updating lock files in: {}" , repo_dir. display( ) ) ) ;
88124
89- backup_existing ( sh) ?;
125+ // Create guard to back up and ensure restoration, even on error.
126+ let _guard = LockFileGuard :: new ( sh) ?;
127+
90128 LockFile :: Minimal . derive ( sh) ?;
91129 LockFile :: Recent . derive ( sh) ?;
92- restore_existing ( sh) ?;
93130
94131 quiet_println ( "Lock files updated successfully" ) ;
95-
96132 Ok ( ( ) )
97133}
98134
@@ -168,24 +204,3 @@ fn copy_lock_file(sh: &Shell, target: LockFile) -> Result<(), Box<dyn std::error
168204 fs:: copy ( & source, & dest) ?;
169205 Ok ( ( ) )
170206}
171-
172- /// Backup the existing Cargo.lock file.
173- fn backup_existing ( sh : & Shell ) -> Result < ( ) , Box < dyn std:: error:: Error > > {
174- let source = sh. current_dir ( ) . join ( CARGO_LOCK ) ;
175- let backup = sh. current_dir ( ) . join ( CARGO_LOCK_BACKUP ) ;
176- if source. exists ( ) {
177- fs:: copy ( & source, & backup) ?;
178- }
179- Ok ( ( ) )
180- }
181-
182- /// Restore the existing Cargo.lock file from backup.
183- fn restore_existing ( sh : & Shell ) -> Result < ( ) , Box < dyn std:: error:: Error > > {
184- let backup = sh. current_dir ( ) . join ( CARGO_LOCK_BACKUP ) ;
185- let dest = sh. current_dir ( ) . join ( CARGO_LOCK ) ;
186- if backup. exists ( ) {
187- fs:: copy ( & backup, & dest) ?;
188- fs:: remove_file ( & backup) ?;
189- }
190- Ok ( ( ) )
191- }
0 commit comments