diff --git a/src/cargo/ops/cargo_install.rs b/src/cargo/ops/cargo_install.rs index a183975fb..5f843e8c7 100644 --- a/src/cargo/ops/cargo_install.rs +++ b/src/cargo/ops/cargo_install.rs @@ -193,8 +193,9 @@ impl<'cfg, 'a> InstallablePackage<'cfg, 'a> { // specialized compile options specific to the identified package. // See test `path_install_workspace_root_despite_default_members`. let mut opts = original_opts.clone(); - // Unlike install source tracking (for --git, see above), use the spec url from the - // build workspace (hence unconditional `ws.current()` instead of `pkg` to get `package_id()`). + // For cargo install tracking, we retain the source git url in `pkg`, but for the build spec + // we need to unconditionally use `ws.current()` to correctly address the path where we + // locally cloned that repo. let pkgidspec = PackageIdSpec::from_package_id(ws.current()?.package_id()); opts.spec = Packages::Packages(vec![pkgidspec.to_string()]); diff --git a/tests/testsuite/install.rs b/tests/testsuite/install.rs index 2447f0a79..a0a77c2d6 100644 --- a/tests/testsuite/install.rs +++ b/tests/testsuite/install.rs @@ -1415,6 +1415,46 @@ fn path_install_workspace_root_despite_default_members() { .run(); } +#[cargo_test] +fn git_install_workspace_root_despite_default_members() { + let p = git::repo(&paths::root().join("foo")) + .file( + "Cargo.toml", + r#" + [package] + name = "ws-root" + version = "0.1.0" + authors = [] + + [workspace] + members = ["ws-member"] + default-members = ["ws-member"] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + "ws-member/Cargo.toml", + r#" + [package] + name = "ws-member" + version = "0.1.0" + authors = [] + "#, + ) + .file("ws-member/src/main.rs", "fn main() {}") + .build(); + + cargo_process("install --git") + .arg(p.url().to_string()) + .arg("ws-root") + .with_stderr_contains( + "[INSTALLED] package `ws-root v0.1.0 ([..])` (executable `ws-root[EXE]`)", + ) + // Particularly avoid "Installed package `ws-root v0.1.0 ([..]])` (executable `ws-member`)": + .with_stderr_does_not_contain("ws-member") + .run(); +} + #[cargo_test] fn dev_dependencies_no_check() { Package::new("foo", "1.0.0").publish(); @@ -2323,3 +2363,48 @@ fn self_referential() { .run(); assert_has_installed_exe(cargo_home(), "foo"); } + +#[cargo_test] +fn ambiguous_registry_vs_local_workspace_package() { + // Correctly install 'foo' from a workspace, even if that workspace + // (somewhere) also depends on a registry package named 'foo'. + Package::new("foo", "0.0.1") + .file("src/lib.rs", "fn hello() {}") + .publish(); + + let p = project() + .file("src/main.rs", "fn main() {}") + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + authors = [] + edition = "2021" + + [dependencies] + foo = "0.0.1" + "#, + ) + .build(); + + cargo_process("install --path") + .arg(p.root()) + .with_stderr( + "\ +[INSTALLING] foo v0.1.0 ([..]) +[UPDATING] `[..]` index +[DOWNLOADING] crates ... +[DOWNLOADED] foo v0.0.1 (registry [..]) +[COMPILING] foo v0.0.1 +[COMPILING] foo v0.1.0 ([..]) +[FINISHED] release [optimized] target(s) in [..] +[INSTALLING] [CWD]/home/.cargo/bin/foo[EXE] +[INSTALLED] package `foo v0.1.0 ([..])` (executable `foo[EXE]`) +[WARNING] be sure to add `[..]` to your PATH to be able to run the installed binaries +", + ) + .run(); + assert_has_installed_exe(cargo_home(), "foo"); +}