@@ -95,7 +95,20 @@ impl ConfigStore {
95
95
Err ( error) => {
96
96
error ! ( "Unable to generate JSON from config file {}: {}" ,
97
97
file_name, error. to_string( ) ) ;
98
- empty_config
98
+ let mut backup_name = file_name. to_owned ( ) ;
99
+ backup_name. push_str ( "_BROKEN" ) ;
100
+ match fs:: rename ( file_name, & backup_name) {
101
+ Ok ( _) => {
102
+ warn ! ( "Moved broken config file to {}" , backup_name) ;
103
+ } ,
104
+ Err ( error) => {
105
+ error ! ( "Error while writing config backup to {}: {}" ,
106
+ backup_name, error. to_string( ) ) ;
107
+ panic ! ( "Unrecoverable error: unable to backup broken config" ) ;
108
+ }
109
+ }
110
+ warn ! ( "Continuing with empty config file" ) ;
111
+ empty_config
99
112
}
100
113
} ;
101
114
@@ -270,5 +283,28 @@ describe! config {
270
283
assert_eq!( foo_bar, "baz" ) ;
271
284
} ;
272
285
}
286
+
287
+ it "ConfigService should back-up broken config files" {
288
+ use std:: io:: { Read , Write } ;
289
+ use std:: path:: Path ;
290
+ // Create broken config file
291
+ let broken_conf = "{\" foo\" :\" bar\" ,}" . to_owned( ) ;
292
+ let mut file = fs:: File :: create( & Path :: new( & config_file_name) ) . ok( ) . unwrap( ) ;
293
+ let _ = file. write_all( & broken_conf. as_bytes( ) ) ;
294
+ // Block to make `config` go out of scope
295
+ {
296
+ let config = ConfigService :: new( & config_file_name) ;
297
+ config. set( "foo" , "bar" , "baz" ) ;
298
+ }
299
+ // `config` should now be out of scope and dropped
300
+ {
301
+ let mut backup_name = config_file_name. clone( ) ;
302
+ backup_name. push_str( "_BROKEN" ) ;
303
+ let mut file = fs:: File :: open( & Path :: new( & backup_name) ) . ok( ) . unwrap( ) ;
304
+ let mut moved_conf = String :: new( ) ;
305
+ let _ = file. read_to_string( & mut moved_conf) ;
306
+ assert_eq!( moved_conf, broken_conf) ;
307
+ } ;
308
+ }
273
309
}
274
310
}
0 commit comments