diff --git a/Cargo.toml b/Cargo.toml index 50a4f8ff8d8..3f0e81455c2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,6 +46,7 @@ libc = "0.2" log = "0.4.6" libgit2-sys = "0.12.14" memchr = "2.1.3" +normpath = "0.1" num_cpus = "1.0" opener = "0.4" percent-encoding = "2.0" diff --git a/src/cargo/core/workspace.rs b/src/cargo/core/workspace.rs index 3c083d1aeff..870e9efb12c 100644 --- a/src/cargo/core/workspace.rs +++ b/src/cargo/core/workspace.rs @@ -7,6 +7,7 @@ use std::slice; use glob::glob; use log::debug; +use normpath::BasePath; use url::Url; use crate::core::features::Features; @@ -1198,7 +1199,10 @@ impl WorkspaceRootConfig { let mut expanded_list = Vec::new(); for glob in globs { - let pathbuf = self.root_dir.join(glob); + let pathbuf = BasePath::new(&self.root_dir) + .chain_err(|| "failed to read the current directory")? + .join(glob) + .into_path_buf(); let expanded_paths = Self::expand_member_path(&pathbuf)?; // If glob does not find any valid paths, then put the original diff --git a/tests/testsuite/workspaces.rs b/tests/testsuite/workspaces.rs index a20ef11ba70..8514ceba165 100644 --- a/tests/testsuite/workspaces.rs +++ b/tests/testsuite/workspaces.rs @@ -2396,3 +2396,54 @@ fn virtual_primary_package_env_var() { p.cargo("clean").run(); p.cargo("test -p foo").run(); } + +// https://github.com/rust-lang/cargo/pull/8874 +#[cargo_test] +#[cfg(windows)] +fn unc_workspace_subfolder() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + # These paths cannot use globs because the glob crate does not support globs in UNC paths + # for unclear reasons + members = ["foo", "crates/bar"] +"#, + ) + .file("foo/Cargo.toml", &basic_manifest("foo", "0.1.0")) + .file("foo/src/lib.rs", "") + .file("crates/bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("crates/bar/src/lib.rs", ""); + let p = p.build(); + // Check that this project can be built normally + p.cargo("build").run(); + + let canon = p + .root() + .canonicalize() + .expect("Build dir cannot be canonicalised"); + + // `std` has this method, but it's private + // canon.components().prefix_verbatim(), + match &canon.components().next() { + Some(std::path::Component::Prefix(it)) if it.kind().is_verbatim() => (), + // If this is because the std implementation has changed, this test should + // be updated to use a different method of getting a UNC path to the build_dir + _ => panic!("canonicalize unexpectedly didn't create a UNC path on windows."), + }; + p.cargo("build") + .arg("--manifest-path") + .arg(canon.join("Cargo.toml")) + .run(); + p.cargo("clean").run(); + p.cargo("build") + .arg("--manifest-path") + .arg(canon.join("Cargo.toml")) + .run(); + p.cargo("build") + .arg("--manifest-path") + // This path using a backslash *is* required, because canon is a UNC path + .arg(canon.join("foo\\Cargo.toml")) + .run(); +}