Skip to content

Commit 9960b05

Browse files
committed
Check for [workspace] when finding workspace root
Before, the top-most `Cargo.toml` file was used. Now we use the nearest `Cargo.toml` file which contain a line saying `[workspace]`. This should avoid false positives when Cargo workspaces are nested inside each other: in this case, the inner package will have an empty `[workspace]` table.
1 parent ec83506 commit 9960b05

2 files changed

Lines changed: 40 additions & 8 deletions

File tree

Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,6 @@ members = ["xtask"]
1717
[dependencies]
1818
once_cell = "1"
1919
dissimilar = "1"
20+
21+
[dev-dependencies]
22+
tempfile = "3"

src/lib.rs

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -644,17 +644,23 @@ fn to_abs_ws_path(path: &Path) -> PathBuf {
644644
static WORKSPACE_ROOT: OnceCell<PathBuf> = OnceCell::new();
645645
WORKSPACE_ROOT
646646
.get_or_try_init(|| {
647-
let my_manifest = env::var("CARGO_MANIFEST_DIR")?;
647+
let manifest_dir = env::var("CARGO_MANIFEST_DIR")?;
648648

649649
// Heuristic, see https://github.com/rust-lang/cargo/issues/3946
650-
let workspace_root = Path::new(&my_manifest)
650+
let workspace_root = Path::new(&manifest_dir)
651651
.ancestors()
652-
.filter(|it| it.join("Cargo.toml").exists())
653-
.last()
654-
.unwrap()
655-
.to_path_buf();
656-
657-
Ok(workspace_root)
652+
.filter(|it| match fs::read_to_string(it.join("Cargo.toml")) {
653+
Ok(cargo_toml) => cargo_toml.lines().any(|line| line.trim() == "[workspace]"),
654+
Err(_) => false, // no Cargo.toml
655+
})
656+
.next();
657+
658+
// Check if we found a workspace or if we should use
659+
// manifest_dir.
660+
match workspace_root {
661+
Some(workspace_root) => Ok(workspace_root.to_path_buf()),
662+
None => Ok(PathBuf::from(manifest_dir)),
663+
}
658664
})
659665
.unwrap_or_else(|_: env::VarError| {
660666
panic!("No CARGO_MANIFEST_DIR env var and the path is relative: {}", path.display())
@@ -867,4 +873,27 @@ line1
867873
"#\"#\"#",
868874
];
869875
}
876+
877+
#[test]
878+
fn test_nested_workspaces1() -> Result<(), std::io::Error> {
879+
let dir = tempfile::tempdir()?;
880+
881+
let outer = dir.path().join("Cargo.toml");
882+
let nested = dir.path().join("nested");
883+
let inner = nested.join("Cargo.toml");
884+
885+
std::fs::write(outer, r#"[package]\nname = "foo""#)?;
886+
887+
std::fs::create_dir(&nested)?;
888+
std::fs::write(&inner, r#"[package]\nname = "bar"\n[workspace]\n"#)?;
889+
890+
let old_manifest_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
891+
env::set_var("CARGO_MANIFEST_DIR", nested.as_os_str());
892+
let nested_bar = to_abs_ws_path(&Path::new("bar.txt"));
893+
env::set_var("CARGO_MANIFEST_DIR", old_manifest_dir);
894+
895+
assert_eq!(nested_bar, nested.join("bar.txt"));
896+
897+
Ok(())
898+
}
870899
}

0 commit comments

Comments
 (0)