Skip to content

Commit de20b86

Browse files
committed
add canonical_home and compare against seen_dir
add test for cargo_home symlink duplicate load remove unintentional test
1 parent f7f3923 commit de20b86

File tree

2 files changed

+58
-1
lines changed

2 files changed

+58
-1
lines changed

src/cargo/util/context/mod.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1681,10 +1681,12 @@ impl GlobalContext {
16811681
seen_dir.insert(config_root);
16821682
}
16831683

1684+
let canonical_home = home.canonicalize().unwrap_or(home.to_path_buf());
1685+
16841686
// Once we're done, also be sure to walk the home directory even if it's not
16851687
// in our history to be sure we pick up that standard location for
16861688
// information.
1687-
if !seen_dir.contains(home) {
1689+
if !seen_dir.contains(&canonical_home) && !seen_dir.contains(home) {
16881690
if let Some(path) = self.get_file_path(home, "config", true)? {
16891691
walk(&path)?;
16901692
}

tests/testsuite/config.rs

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2589,3 +2589,58 @@ 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+
use std::os::unix::fs::symlink;
2600+
2601+
let p = project()
2602+
.file("Cargo.toml", &basic_manifest("foo", "0.1.0"))
2603+
.file("src/lib.rs", "")
2604+
.build();
2605+
2606+
// Create directory structure a/b/ and symlink c -> a
2607+
let a_dir = p.root().join("a");
2608+
let b_dir = a_dir.join("b");
2609+
let c_symlink = p.root().join("c");
2610+
2611+
fs::create_dir_all(&b_dir).unwrap();
2612+
symlink(&a_dir, &c_symlink).unwrap();
2613+
2614+
// Create config file in a/.cargo/
2615+
let cargo_config_dir = a_dir.join(".cargo");
2616+
fs::create_dir(&cargo_config_dir).unwrap();
2617+
let config_path = cargo_config_dir.join("config.toml");
2618+
fs::write(
2619+
&config_path,
2620+
r#"
2621+
[build]
2622+
rustdocflags = ["--default-theme=dark"]
2623+
"#,
2624+
)
2625+
.unwrap();
2626+
2627+
// Move the project into a/b/
2628+
let project_in_b = b_dir.join("foo");
2629+
fs::create_dir(&project_in_b).unwrap();
2630+
fs::write(
2631+
project_in_b.join("Cargo.toml"),
2632+
&basic_manifest("foo", "0.1.0"),
2633+
)
2634+
.unwrap();
2635+
fs::create_dir(project_in_b.join("src")).unwrap();
2636+
fs::write(project_in_b.join("src/lib.rs"), "").unwrap();
2637+
2638+
// Set CARGO_HOME to ../../c/.cargo (which is really a/.cargo via symlink)
2639+
let cargo_home = c_symlink.join(".cargo");
2640+
2641+
// If config is loaded twice, rustdocflags will be duplicated and cause an error
2642+
p.cargo("doc")
2643+
.cwd(&project_in_b)
2644+
.env("CARGO_HOME", &cargo_home)
2645+
.run();
2646+
}

0 commit comments

Comments
 (0)