Skip to content

Commit a45d668

Browse files
Fix cargo add overwriting symlinked Cargo.toml files
1 parent ab1463d commit a45d668

File tree

3 files changed

+61
-2
lines changed

3 files changed

+61
-2
lines changed

src/cargo/util/toml_mut/manifest.rs

+9-2
Original file line numberDiff line numberDiff line change
@@ -323,9 +323,16 @@ impl LocalManifest {
323323
};
324324
let new_contents_bytes = raw.as_bytes();
325325

326-
cargo_util::paths::write_atomic(&self.path, new_contents_bytes)
327-
}
326+
// Check if the path is a symlink and follow it if it is
327+
let actual_path = if self.path.is_symlink() {
328+
std::fs::read_link(&self.path)?
329+
} else {
330+
self.path.clone()
331+
};
328332

333+
// Write to the actual target path instead of the symlink
334+
cargo_util::paths::write_atomic(&actual_path, new_contents_bytes)
335+
}
329336
/// Lookup a dependency.
330337
pub fn get_dependency_versions<'s>(
331338
&'s self,

tests/testsuite/cargo_add/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ mod script_bare;
145145
mod script_frontmatter;
146146
mod script_shebang;
147147
mod sorted_table_with_dotted_item;
148+
mod symlink;
148149
mod target;
149150
mod target_cfg;
150151
mod unknown_inherited_feature;

tests/testsuite/cargo_add/symlink.rs

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
use cargo_test_support::prelude::*;
2+
use cargo_test_support::project;
3+
use std::fs;
4+
5+
#[cargo_test]
6+
fn preserve_symlink_to_cargo_toml() {
7+
if !cargo_test_support::symlink_supported() {
8+
return;
9+
}
10+
11+
let project = project().file("src/lib.rs", "").build();
12+
13+
let target_dir = project.root().join("target_dir");
14+
fs::create_dir_all(&target_dir).unwrap();
15+
16+
// Create the target Cargo.toml
17+
fs::copy(
18+
project.root().join("Cargo.toml"),
19+
target_dir.join("Cargo.toml"),
20+
)
21+
.unwrap();
22+
23+
// Remove the original and create a symlink
24+
fs::remove_file(project.root().join("Cargo.toml")).unwrap();
25+
26+
#[cfg(unix)]
27+
{
28+
use std::os::unix::fs::symlink;
29+
symlink(
30+
target_dir.join("Cargo.toml"),
31+
project.root().join("Cargo.toml"),
32+
)
33+
.unwrap();
34+
}
35+
36+
#[cfg(windows)]
37+
{
38+
use std::os::windows::fs::symlink_file;
39+
symlink_file(
40+
target_dir.join("Cargo.toml"),
41+
project.root().join("Cargo.toml"),
42+
)
43+
.unwrap();
44+
}
45+
46+
// Add a dependency
47+
project.cargo("add rand").run();
48+
49+
// Verify the symlink is preserved
50+
assert!(project.root().join("Cargo.toml").is_symlink());
51+
}

0 commit comments

Comments
 (0)