@@ -190,14 +190,22 @@ 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 actual_path = if path. is_symlink ( ) {
199+ std:: fs:: read_link ( path) ?
200+ } else {
201+ path. to_path_buf ( )
202+ } ;
203+
196204 // On unix platforms, get the permissions of the original file. Copy only the user/group/other
197205 // read/write/execute permission bits. The tempfile lib defaults to an initial mode of 0o600,
198206 // and we'll set the proper permissions after creating the file.
199207 #[ cfg( unix) ]
200- let perms = path . metadata ( ) . ok ( ) . map ( |meta| {
208+ let perms = actual_path . metadata ( ) . ok ( ) . map ( |meta| {
201209 use std:: os:: unix:: fs:: PermissionsExt ;
202210
203211 // these constants are u16 on macOS
@@ -208,8 +216,8 @@ pub fn write_atomic<P: AsRef<Path>, C: AsRef<[u8]>>(path: P, contents: C) -> Res
208216 } ) ;
209217
210218 let mut tmp = TempFileBuilder :: new ( )
211- . prefix ( path . file_name ( ) . unwrap ( ) )
212- . tempfile_in ( path . parent ( ) . unwrap ( ) ) ?;
219+ . prefix ( actual_path . file_name ( ) . unwrap ( ) )
220+ . tempfile_in ( actual_path . parent ( ) . unwrap ( ) ) ?;
213221 tmp. write_all ( contents. as_ref ( ) ) ?;
214222
215223 // On unix platforms, set the permissions on the newly created file. We can use fchmod (called
@@ -220,10 +228,9 @@ pub fn write_atomic<P: AsRef<Path>, C: AsRef<[u8]>>(path: P, contents: C) -> Res
220228 tmp. as_file ( ) . set_permissions ( perms) ?;
221229 }
222230
223- tmp. persist ( path ) ?;
231+ tmp. persist ( & actual_path ) ?;
224232 Ok ( ( ) )
225233}
226-
227234/// Equivalent to [`write()`], but does not write anything if the file contents
228235/// are identical to the given contents.
229236pub fn write_if_changed < P : AsRef < Path > , C : AsRef < [ u8 ] > > ( path : P , contents : C ) -> Result < ( ) > {
0 commit comments