Skip to content

Commit 7afa6bb

Browse files
committed
add canonical_home and compare against seen_dir
add test for cargo_home symlink duplicate load remove unintentional test add windows config test for config_symlink_home_no_duplicate_load fix canonicalize root path of config before inserting
1 parent 2a1789f commit 7afa6bb

File tree

2 files changed

+66
-2
lines changed

2 files changed

+66
-2
lines changed

src/cargo/util/context/mod.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1678,13 +1678,17 @@ impl GlobalContext {
16781678
if let Some(path) = self.get_file_path(&config_root, "config", true)? {
16791679
walk(&path)?;
16801680
}
1681-
seen_dir.insert(config_root);
1681+
1682+
let canonical_root = config_root.canonicalize().unwrap_or(config_root);
1683+
seen_dir.insert(canonical_root);
16821684
}
16831685

1686+
let canonical_home = home.canonicalize().unwrap_or(home.to_path_buf());
1687+
16841688
// Once we're done, also be sure to walk the home directory even if it's not
16851689
// in our history to be sure we pick up that standard location for
16861690
// information.
1687-
if !seen_dir.contains(home) {
1691+
if !seen_dir.contains(&canonical_home) && !seen_dir.contains(home) {
16881692
if let Some(path) = self.get_file_path(home, "config", true)? {
16891693
walk(&path)?;
16901694
}

tests/testsuite/config.rs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2589,3 +2589,63 @@ fn mixed_type_array() {
25892589
}
25902590
);
25912591
}
2592+
2593+
#[cargo_test]
2594+
fn config_symlink_home_no_duplicate_load() {
2595+
// Test that when CARGO_HOME is accessed via a symlink that points to a directory
2596+
// already in the config search path, the config file is not loaded twice.
2597+
2598+
use cargo_test_support::basic_manifest;
2599+
2600+
#[cfg(unix)]
2601+
use std::os::unix::fs::symlink;
2602+
2603+
#[cfg(windows)]
2604+
use std::os::windows::fs::symlink_dir as symlink;
2605+
2606+
let p = project()
2607+
.file("Cargo.toml", &basic_manifest("foo", "0.1.0"))
2608+
.file("src/lib.rs", "")
2609+
.build();
2610+
2611+
// Create directory structure a/b/ and symlink c -> a
2612+
let a_dir = p.root().join("a");
2613+
let b_dir = a_dir.join("b");
2614+
let c_symlink = p.root().join("c");
2615+
2616+
fs::create_dir_all(&b_dir).unwrap();
2617+
symlink(&a_dir, &c_symlink).unwrap();
2618+
2619+
// Create config file in a/.cargo/
2620+
let cargo_config_dir = a_dir.join(".cargo");
2621+
fs::create_dir(&cargo_config_dir).unwrap();
2622+
let config_path = cargo_config_dir.join("config.toml");
2623+
fs::write(
2624+
&config_path,
2625+
r#"
2626+
[build]
2627+
rustdocflags = ["--default-theme=dark"]
2628+
"#,
2629+
)
2630+
.unwrap();
2631+
2632+
// Move the project into a/b/
2633+
let project_in_b = b_dir.join("foo");
2634+
fs::create_dir(&project_in_b).unwrap();
2635+
fs::write(
2636+
project_in_b.join("Cargo.toml"),
2637+
&basic_manifest("foo", "0.1.0"),
2638+
)
2639+
.unwrap();
2640+
fs::create_dir(project_in_b.join("src")).unwrap();
2641+
fs::write(project_in_b.join("src/lib.rs"), "").unwrap();
2642+
2643+
// Set CARGO_HOME to ../../c/.cargo (which is really a/.cargo via symlink)
2644+
let cargo_home = c_symlink.join(".cargo");
2645+
2646+
// If config is loaded twice, rustdocflags will be duplicated and cause an error
2647+
p.cargo("doc")
2648+
.cwd(&project_in_b)
2649+
.env("CARGO_HOME", &cargo_home)
2650+
.run();
2651+
}

0 commit comments

Comments
 (0)