diff --git a/src/cargo/core/workspace.rs b/src/cargo/core/workspace.rs index d05b802cf79..05af79a2201 100644 --- a/src/cargo/core/workspace.rs +++ b/src/cargo/core/workspace.rs @@ -283,6 +283,10 @@ impl<'gctx> Workspace<'gctx> { ws.member_ids.insert(id); ws.default_members.push(ws.current_manifest.clone()); ws.set_resolve_behavior(); + // The find_root function is used here to traverse the directory tree and locate the root of the workspace. + // Despite being ephemeral, we still need to validate all the manifests in the workspace, + // which is what `find_root` helps us achieve here. + ws.find_root(ws.current_manifest.clone().as_path())?; Ok(ws) } diff --git a/src/cargo/ops/cargo_install.rs b/src/cargo/ops/cargo_install.rs index 4e51ef30ea4..3cdbebcabcf 100644 --- a/src/cargo/ops/cargo_install.rs +++ b/src/cargo/ops/cargo_install.rs @@ -816,7 +816,7 @@ fn make_ws_rustc_target<'gctx>( source_id: &SourceId, pkg: Package, ) -> CargoResult<(Workspace<'gctx>, Rustc, String)> { - let mut ws = if source_id.is_git() || source_id.is_path() { + let mut ws = if source_id.is_path() { Workspace::new(pkg.manifest_path(), gctx)? } else { Workspace::ephemeral(pkg, gctx, None, false)? diff --git a/tests/testsuite/install.rs b/tests/testsuite/install.rs index ec7bfe7bd9a..85fe4418b64 100644 --- a/tests/testsuite/install.rs +++ b/tests/testsuite/install.rs @@ -2064,6 +2064,76 @@ fn git_install_reads_workspace_manifest() { .run(); } +#[cargo_test] +fn git_install_the_same_bin_twice_with_different_rev() { + let project = git::new("foo", |project| { + project + .file( + "Cargo.toml", + r#" + [workspace] + members = ["bin1"] + "#, + ) + .file("bin1/Cargo.toml", &basic_manifest("bin1", "0.1.0")) + .file( + "bin1/src/main.rs", + r#"fn main() { println!("Hello, world!"); }"#, + ) + }); + let repository = git2::Repository::open(&project.root()).unwrap(); + let first_rev = repository.revparse_single("HEAD").unwrap().id().to_string(); + + // Change the main.rs. + fs::write( + project.root().join("bin1/src/main.rs"), + r#"fn main() { println!("Hello, world! 2"); }"#, + ) + .expect("failed to write file"); + git::commit(&repository); + let second_rev = repository.revparse_single("HEAD").unwrap().id().to_string(); + + // Set up a temp target directory. + let temp_dir = paths::root().join("temp-target"); + cargo_process(&format!( + "install --git {} --rev {} bin1 --target-dir {}", + project.url().to_string(), + second_rev, + temp_dir.display() + )) + .with_stderr( + "\ +[UPDATING] git repository [..] +[INSTALLING] bin1 v0.1.0 [..] +[COMPILING] bin1 v0.1.0 [..] +[FINISHED] [..] +[INSTALLING] [..]home/.cargo/bin/bin1[..] +[INSTALLED] package `bin1 [..] +[WARNING] be sure to add [..] +", + ) + .run(); + + cargo_process(&format!( + "install --git {} --rev {} bin1 --target-dir {}", + project.url().to_string(), + first_rev, + temp_dir.display() + )) + .with_stderr( + "\ +[UPDATING] git repository [..] +[INSTALLING] bin1 v0.1.0 [..] +[COMPILING] bin1 v0.1.0 [..] +[FINISHED] [..] +[REPLACING] [..]home/.cargo/bin/bin1[..] +[REPLACED] package `bin1 [..] +[WARNING] be sure to add [..] +", + ) + .run(); +} + #[cargo_test] fn install_git_with_symlink_home() { // Ensure that `cargo install` with a git repo is OK when CARGO_HOME is a