Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/cargo/sources/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -991,6 +991,10 @@ fn read_packages(
source_id: SourceId,
gctx: &GlobalContext,
) -> CargoResult<HashMap<PackageId, Vec<Package>>> {
// Normalize for consistency.
// See https://github.com/rust-lang/cargo/issues/15981
// Otherwise, a `CARGO_HOME` with `..` can collect a package twice and incorrectly warn about a duplicate.
let path = &paths::normalize_path(path);
let mut all_packages = HashMap::default();
let mut visited = HashSet::<PathBuf>::default();
let mut errors = Vec::<anyhow::Error>::new();
Expand Down
70 changes: 70 additions & 0 deletions tests/testsuite/git.rs
Comment thread
hirehamir marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -1250,6 +1250,76 @@ in favor of [ROOT]/home/.cargo/git/checkouts/dep-[HASH]/[..]/duplicate1/Cargo.to
.run();
}

#[cargo_test]
fn no_duplicate_package_warning_with_dotdot_cargo_home() {
// Regression test for https://github.com/rust-lang/cargo/issues/15981.
//
// A `CARGO_HOME` containing a `..` segment can make the git checkout path retain
// the `..`, so a workspace member discovered by walking the checkout (raw path)
// and by following the root's `path` dependency (normalized path) looked
// like two different packages, producing an incorrect duplicate warning.
let git_project = git::new("dep", |project| {
project
.file(
"Cargo.toml",
r#"
[package]
name = "dep"
version = "0.1.0"
edition = "2015"

[dependencies]
member = { path = "member" }
"#,
)
.file("src/lib.rs", "")
.file(
"member/Cargo.toml",
r#"
[package]
name = "member"
version = "0.1.0"
edition = "2015"
"#,
)
.file("member/src/lib.rs", "")
});
let p = project()
.file(
"Cargo.toml",
&format!(
r#"
[package]
name = "foo"
version = "0.1.0"
edition = "2015"

[dependencies]
dep = {{ git = '{}' }}
"#,
git_project.url()
),
)
.file("src/main.rs", "fn main() {}")
.build();

// `paths::home()` is created by the test harness, so the `..` resolves on disk.
let cargo_home = paths::home().join("..").join("cargo-home");

p.cargo("check")
.env("CARGO_HOME", &cargo_home)
.with_stderr_data(str![[r#"
[UPDATING] git repository `[ROOTURL]/dep`
[LOCKING] 2 packages to latest compatible versions
[CHECKING] member v0.1.0 ([ROOTURL]/dep#[..])
[CHECKING] dep v0.1.0 ([ROOTURL]/dep#[..])
[CHECKING] foo v0.1.0 ([ROOT]/foo)
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s

"#]])
.run();
}

#[cargo_test]
fn unused_ambiguous_published_deps() {
let project = project();
Expand Down