From 08889ee8ef0b797e53aec27ba07a816f622df61e Mon Sep 17 00:00:00 2001 From: Ted Kaminski Date: Fri, 9 Sep 2022 19:57:45 +0000 Subject: [PATCH] Ignore `workspace.default-members` when running `cargo install` on root package of a non-virtual workspace --- src/cargo/core/workspace.rs | 17 +++++++++++++++ src/cargo/ops/cargo_install.rs | 5 +++++ tests/testsuite/install.rs | 40 ++++++++++++++++++++++++++++++++++ 3 files changed, 62 insertions(+) diff --git a/src/cargo/core/workspace.rs b/src/cargo/core/workspace.rs index 0d07dafa3479..572a8e57918c 100644 --- a/src/cargo/core/workspace.rs +++ b/src/cargo/core/workspace.rs @@ -552,6 +552,23 @@ impl<'cfg> Workspace<'cfg> { }) } + /// Reset "default build" behavior for non-virtual workspaces, so that a build in + /// the workspace root would build the root package, not the packages specified + /// in `workspace.default-members`. + pub fn ignore_default_members(&mut self) -> &mut Workspace<'cfg> { + // If we're building a virtual workspace, then there is no root package to build + if self.is_virtual() { + return self; + } + // If we're not building the root package, then the default members do not matter + if self.current_manifest != self.root_manifest() { + return self; + } + + self.default_members = vec![self.current_manifest.clone()]; + self + } + /// Returns true if the package is a member of the workspace. pub fn is_member(&self, pkg: &Package) -> bool { self.member_ids.contains(&pkg.package_id()) diff --git a/src/cargo/ops/cargo_install.rs b/src/cargo/ops/cargo_install.rs index dd22cc8efb67..507d6dc9b311 100644 --- a/src/cargo/ops/cargo_install.rs +++ b/src/cargo/ops/cargo_install.rs @@ -734,6 +734,11 @@ fn make_ws_rustc_target<'cfg>( ws.set_ignore_lock(config.lock_update_allowed()); ws.set_require_optional_deps(false); + // `cargo install` effectively does `cargo build` in `pkg`. But when this is the root + // of a non-virtual workspace, that would accidentally build `workspace.default-members` + // instead of `pkg` (possibly not even including `pkg` at all!) + ws.ignore_default_members(); + let rustc = config.load_global_rustc(Some(&ws))?; let target = match &opts.build_config.single_requested_kind()? { CompileKind::Host => rustc.host.as_str().to_owned(), diff --git a/tests/testsuite/install.rs b/tests/testsuite/install.rs index 4bd679c0c80b..58e3f6691e96 100644 --- a/tests/testsuite/install.rs +++ b/tests/testsuite/install.rs @@ -1294,6 +1294,46 @@ fn use_path_workspace() { assert_eq!(lock, lock2, "different lockfiles"); } +#[cargo_test] +fn path_install_workspace_root_despite_default_members() { + let p = project() + .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(); + + p.cargo("install --path") + .arg(p.root()) + .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();