@@ -190,9 +190,20 @@ pub fn write<P: AsRef<Path>, C: AsRef<[u8]>>(path: P, contents: C) -> Result<()>
190190/// Writes a file to disk atomically. 
191191/// 
192192/// This uses `tempfile::persist` to accomplish atomic writes. 
193+ /// If the path is a symlink, it will follow the symlink and write to the actual target. 
193194pub  fn  write_atomic < P :  AsRef < Path > ,  C :  AsRef < [ u8 ] > > ( path :  P ,  contents :  C )  -> Result < ( ) >  { 
194195    let  path = path. as_ref ( ) ; 
195196
197+     // Check if the path is a symlink and follow it if it is 
198+     let  resolved_path; 
199+     let  path = if  path. is_symlink ( )  { 
200+         resolved_path = fs:: read_link ( path) 
201+             . with_context ( || format ! ( "failed to read symlink at `{}`" ,  path. display( ) ) ) ?; 
202+         & resolved_path
203+     }  else  { 
204+         path
205+     } ; 
206+ 
196207    // On unix platforms, get the permissions of the original file. Copy only the user/group/other 
197208    // read/write/execute permission bits. The tempfile lib defaults to an initial mode of 0o600, 
198209    // and we'll set the proper permissions after creating the file. 
@@ -983,6 +994,34 @@ mod tests {
983994        } 
984995    } 
985996
997+ 
998+     #[ test]  
999+ fn  write_atomic_symlink ( )  { 
1000+     let  tmpdir = tempfile:: tempdir ( ) . unwrap ( ) ; 
1001+     let  target_path = tmpdir. path ( ) . join ( "target.txt" ) ; 
1002+     let  symlink_path = tmpdir. path ( ) . join ( "symlink.txt" ) ; 
1003+     
1004+     // Create initial file 
1005+     write ( & target_path,  "initial" ) . unwrap ( ) ; 
1006+     
1007+     // Create symlink 
1008+     #[ cfg( unix) ]  
1009+     std:: os:: unix:: fs:: symlink ( & target_path,  & symlink_path) . unwrap ( ) ; 
1010+     #[ cfg( windows) ]  
1011+     std:: os:: windows:: fs:: symlink_file ( & target_path,  & symlink_path) . unwrap ( ) ; 
1012+     
1013+     // Write through symlink 
1014+     write_atomic ( & symlink_path,  "updated" ) . unwrap ( ) ; 
1015+     
1016+     // Verify both paths show the updated content 
1017+     assert_eq ! ( std:: fs:: read_to_string( & target_path) . unwrap( ) ,  "updated" ) ; 
1018+     assert_eq ! ( std:: fs:: read_to_string( & symlink_path) . unwrap( ) ,  "updated" ) ; 
1019+     
1020+     // Verify symlink still exists and points to the same target 
1021+     assert ! ( symlink_path. is_symlink( ) ) ; 
1022+     assert_eq ! ( std:: fs:: read_link( & symlink_path) . unwrap( ) ,  target_path) ; 
1023+ } 
1024+ 
9861025    #[ test]  
9871026    #[ cfg( windows) ]  
9881027    fn  test_remove_symlink_dir ( )  { 
0 commit comments