Skip to content

Commit

Permalink
Auto merge of #10335 - weihanglo:issue-10283, r=alexcrichton
Browse files Browse the repository at this point in the history
Normalize --path when install bin outside current workspace
  • Loading branch information
bors committed Jan 27, 2022
2 parents 0673982 + 76301eb commit 5137905
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 6 deletions.
24 changes: 19 additions & 5 deletions src/bin/cargo/commands/install.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
use crate::command_prelude::*;

use cargo::core::{GitReference, SourceId};
use cargo::core::{GitReference, SourceId, Workspace};
use cargo::ops;
use cargo::util::IntoUrl;

use cargo_util::paths;

pub fn cli() -> App {
subcommand("install")
.about("Install a Rust binary. Default location is $HOME/.cargo/bin")
Expand Down Expand Up @@ -80,13 +82,20 @@ pub fn cli() -> App {
}

pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
if let Some(path) = args.value_of_path("path", config) {
let path = args.value_of_path("path", config);
if let Some(path) = &path {
config.reload_rooted_at(path)?;
} else {
// TODO: Consider calling set_search_stop_path(home).
config.reload_rooted_at(config.home().clone().into_path_unlocked())?;
}

// In general, we try to avoid normalizing paths in Cargo,
// but in these particular cases we need it to fix rust-lang/cargo#10283.
// (Handle `SourceId::for_path` and `Workspace::new`,
// but not `Config::reload_rooted_at` which is always cwd)
let path = path.map(|p| paths::normalize_path(&p));

let krates = args
.values_of("crate")
.unwrap_or_default()
Expand All @@ -106,7 +115,7 @@ pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
GitReference::DefaultBranch
};
SourceId::for_git(&url, gitref)?
} else if let Some(path) = args.value_of_path("path", config) {
} else if let Some(path) = &path {
SourceId::for_path(&path)?
} else if krates.is_empty() {
from_cwd = true;
Expand All @@ -125,9 +134,14 @@ pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
// We only provide workspace information for local crate installation from
// one of the following sources:
// - From current working directory (only work for edition 2015).
// - From a specific local file path.
let workspace = if from_cwd || args.is_present("path") {
// - From a specific local file path (from `--path` arg).
//
// This workspace information is for emitting helpful messages from
// `ArgMatchesExt::compile_options` and won't affect the actual compilation.
let workspace = if from_cwd {
args.workspace(config).ok()
} else if let Some(path) = &path {
Workspace::new(&path.join("Cargo.toml"), config).ok()
} else {
None
};
Expand Down
66 changes: 65 additions & 1 deletion tests/testsuite/install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use cargo_test_support::cross_compile;
use cargo_test_support::git;
use cargo_test_support::registry::{self, registry_path, registry_url, Package};
use cargo_test_support::{
basic_manifest, cargo_process, no_such_file_err_msg, project, symlink_supported, t,
basic_manifest, cargo_process, no_such_file_err_msg, project, project_in, symlink_supported, t,
};

use cargo_test_support::install::{
Expand Down Expand Up @@ -493,6 +493,70 @@ but found cargo.toml please try to rename it to Cargo.toml. --path must point to
.run();
}

#[cargo_test]
fn install_relative_path_outside_current_ws() {
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "bar"
version = "0.1.0"
authors = []
[workspace]
members = ["baz"]
"#,
)
.file("src/main.rs", "fn main() {}")
.file(
"baz/Cargo.toml",
r#"
[package]
name = "baz"
version = "0.1.0"
authors = []
edition = "2021"
[dependencies]
foo = "1"
"#,
)
.file("baz/src/lib.rs", "")
.build();

let _bin_project = project_in("bar")
.file("src/main.rs", "fn main() {}")
.build();

p.cargo("install --path ../bar/foo")
.with_stderr(&format!(
"\
[INSTALLING] foo v0.0.1 ([..]/bar/foo)
[COMPILING] foo v0.0.1 ([..]/bar/foo)
[FINISHED] release [..]
[INSTALLING] {home}/bin/foo[EXE]
[INSTALLED] package `foo v0.0.1 ([..]/bar/foo)` (executable `foo[EXE]`)
[WARNING] be sure to add [..]
",
home = cargo_home().display(),
))
.run();

// Validate the workspace error message to display available targets.
p.cargo("install --path ../bar/foo --bin")
.with_status(101)
.with_stderr(
"\
[ERROR] \"--bin\" takes one argument.
Available binaries:
foo
",
)
.run();
}

#[cargo_test]
fn multiple_crates_error() {
let p = git::repo(&paths::root().join("foo"))
Expand Down

0 comments on commit 5137905

Please sign in to comment.