Skip to content

Commit 976b828

Browse files
fix: Preserve symlinks when running cargo add
1 parent 26bd6b5 commit 976b828

File tree

1 file changed

+12
-5
lines changed

1 file changed

+12
-5
lines changed

crates/cargo-util/src/paths.rs

+12-5
Original file line numberDiff line numberDiff line change
@@ -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.
193194
pub 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.
229236
pub fn write_if_changed<P: AsRef<Path>, C: AsRef<[u8]>>(path: P, contents: C) -> Result<()> {

0 commit comments

Comments
 (0)