From 44f650f2606c0cff8d8cce64b309dff4bda6ed99 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Thu, 27 Jan 2022 17:58:06 +0800 Subject: [PATCH] Normalize `--path` to install bin outside current workspace For `Workspace::find_root`, `cargo_util::path::PathAncestors` won't do path normalization while walking back the ancestors. The responsibility lies in the caller. Thus, `cargo install` should normalize its `--path` argument before passing in `SourceId::for_path` and `Workspace::new`. `Config::reload_rooted_at` is not affected because cargo always starts searching and merging configs from where it is invoked. --- src/bin/cargo/commands/install.rs | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/src/bin/cargo/commands/install.rs b/src/bin/cargo/commands/install.rs index 621558d97..f0bbb4d79 100644 --- a/src/bin/cargo/commands/install.rs +++ b/src/bin/cargo/commands/install.rs @@ -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") @@ -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() @@ -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; @@ -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 }; -- 2.39.2