@@ -190,14 +190,22 @@ pub fn write<P: AsRef<Path>, C: AsRef<[u8]>>(path: P, contents: C) -> Result<()>
190
190
/// Writes a file to disk atomically.
191
191
///
192
192
/// 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.
193
194
pub fn write_atomic < P : AsRef < Path > , C : AsRef < [ u8 ] > > ( path : P , contents : C ) -> Result < ( ) > {
194
195
let path = path. as_ref ( ) ;
195
196
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
+
196
204
// On unix platforms, get the permissions of the original file. Copy only the user/group/other
197
205
// read/write/execute permission bits. The tempfile lib defaults to an initial mode of 0o600,
198
206
// and we'll set the proper permissions after creating the file.
199
207
#[ cfg( unix) ]
200
- let perms = path . metadata ( ) . ok ( ) . map ( |meta| {
208
+ let perms = actual_path . metadata ( ) . ok ( ) . map ( |meta| {
201
209
use std:: os:: unix:: fs:: PermissionsExt ;
202
210
203
211
// 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
208
216
} ) ;
209
217
210
218
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 ( ) ) ?;
213
221
tmp. write_all ( contents. as_ref ( ) ) ?;
214
222
215
223
// 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
220
228
tmp. as_file ( ) . set_permissions ( perms) ?;
221
229
}
222
230
223
- tmp. persist ( path ) ?;
231
+ tmp. persist ( & actual_path ) ?;
224
232
Ok ( ( ) )
225
233
}
226
-
227
234
/// Equivalent to [`write()`], but does not write anything if the file contents
228
235
/// are identical to the given contents.
229
236
pub fn write_if_changed < P : AsRef < Path > , C : AsRef < [ u8 ] > > ( path : P , contents : C ) -> Result < ( ) > {
0 commit comments