ra_project_model: look for Cargo in more places

See #3118
This commit is contained in:
Craig Disselkoen 2020-05-05 11:59:41 -07:00
parent 30eb458b4f
commit ffaef1b7ae
3 changed files with 128 additions and 10 deletions

77
Cargo.lock generated
View file

@ -21,6 +21,12 @@ version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33954243bd79057c2de7338850b85983a44588021f8a5fee574a8888c6de4344" checksum = "33954243bd79057c2de7338850b85983a44588021f8a5fee574a8888c6de4344"
[[package]]
name = "arrayref"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544"
[[package]] [[package]]
name = "arrayvec" name = "arrayvec"
version = "0.5.1" version = "0.5.1"
@ -66,6 +72,12 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "base64"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7"
[[package]] [[package]]
name = "base64" name = "base64"
version = "0.12.0" version = "0.12.0"
@ -78,6 +90,17 @@ version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
[[package]]
name = "blake2b_simd"
version = "0.5.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8fb2d74254a3a0b5cac33ac9f8ed0e44aa50378d9dbb2e5d83bd21ed1dc2c8a"
dependencies = [
"arrayref",
"arrayvec",
"constant_time_eq",
]
[[package]] [[package]]
name = "bstr" name = "bstr"
version = "0.2.12" version = "0.2.12"
@ -212,6 +235,12 @@ dependencies = [
"winapi 0.3.8", "winapi 0.3.8",
] ]
[[package]]
name = "constant_time_eq"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc"
[[package]] [[package]]
name = "crossbeam" name = "crossbeam"
version = "0.7.3" version = "0.7.3"
@ -289,6 +318,28 @@ version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198"
[[package]]
name = "dirs"
version = "2.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13aea89a5c93364a98e9b37b2fa237effbb694d5cfe01c5b70941f7eb087d5e3"
dependencies = [
"cfg-if",
"dirs-sys",
]
[[package]]
name = "dirs-sys"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "afa0b23de8fd801745c471deffa6e12d248f962c9fd4b4c33787b055599bde7b"
dependencies = [
"cfg-if",
"libc",
"redox_users",
"winapi 0.3.8",
]
[[package]] [[package]]
name = "drop_bomb" name = "drop_bomb"
version = "0.1.4" version = "0.1.4"
@ -659,7 +710,7 @@ version = "0.74.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57c0e6a2b8837d27b29deb3f3e6dc1c6d2f57947677f9be1024e482ec5b59525" checksum = "57c0e6a2b8837d27b29deb3f3e6dc1c6d2f57947677f9be1024e482ec5b59525"
dependencies = [ dependencies = [
"base64", "base64 0.12.0",
"bitflags", "bitflags",
"serde", "serde",
"serde_json", "serde_json",
@ -1158,6 +1209,7 @@ version = "0.1.0"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"cargo_metadata", "cargo_metadata",
"dirs",
"log", "log",
"ra_arena", "ra_arena",
"ra_cfg", "ra_cfg",
@ -1298,6 +1350,17 @@ version = "0.1.56"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84"
[[package]]
name = "redox_users"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09b23093265f8d200fa7b4c2c76297f47e681c655f6f1285a8780d6a022f7431"
dependencies = [
"getrandom",
"redox_syscall",
"rust-argon2",
]
[[package]] [[package]]
name = "regex" name = "regex"
version = "1.3.7" version = "1.3.7"
@ -1382,6 +1445,18 @@ dependencies = [
"winapi 0.3.8", "winapi 0.3.8",
] ]
[[package]]
name = "rust-argon2"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2bc8af4bda8e1ff4932523b94d3dd20ee30a87232323eda55903ffd71d2fb017"
dependencies = [
"base64 0.11.0",
"blake2b_simd",
"constant_time_eq",
"crossbeam-utils",
]
[[package]] [[package]]
name = "rustc-ap-rustc_lexer" name = "rustc-ap-rustc_lexer"
version = "656.0.0" version = "656.0.0"

View file

@ -22,3 +22,5 @@ serde = { version = "1.0.106", features = ["derive"] }
serde_json = "1.0.48" serde_json = "1.0.48"
anyhow = "1.0.26" anyhow = "1.0.26"
dirs = "2.0"

View file

@ -8,7 +8,7 @@ use std::{
process::Command, process::Command,
}; };
use anyhow::{Context, Result}; use anyhow::{Context, Error, Result};
use cargo_metadata::{BuildScript, CargoOpt, Message, MetadataCommand, PackageId}; use cargo_metadata::{BuildScript, CargoOpt, Message, MetadataCommand, PackageId};
use ra_arena::{Arena, Idx}; use ra_arena::{Arena, Idx};
use ra_db::Edition; use ra_db::Edition;
@ -145,12 +145,8 @@ impl CargoWorkspace {
cargo_toml: &Path, cargo_toml: &Path,
cargo_features: &CargoConfig, cargo_features: &CargoConfig,
) -> Result<CargoWorkspace> { ) -> Result<CargoWorkspace> {
let _ = Command::new(cargo_binary())
.arg("--version")
.output()
.context("failed to run `cargo --version`, is `cargo` in PATH?")?;
let mut meta = MetadataCommand::new(); let mut meta = MetadataCommand::new();
meta.cargo_path(cargo_binary()?);
meta.manifest_path(cargo_toml); meta.manifest_path(cargo_toml);
if cargo_features.all_features { if cargo_features.all_features {
meta.features(CargoOpt::AllFeatures); meta.features(CargoOpt::AllFeatures);
@ -288,7 +284,7 @@ pub fn load_extern_resources(
cargo_toml: &Path, cargo_toml: &Path,
cargo_features: &CargoConfig, cargo_features: &CargoConfig,
) -> Result<ExternResources> { ) -> Result<ExternResources> {
let mut cmd = Command::new(cargo_binary()); let mut cmd = Command::new(cargo_binary()?);
cmd.args(&["check", "--message-format=json", "--manifest-path"]).arg(cargo_toml); cmd.args(&["check", "--message-format=json", "--manifest-path"]).arg(cargo_toml);
if cargo_features.all_features { if cargo_features.all_features {
cmd.arg("--all-features"); cmd.arg("--all-features");
@ -337,6 +333,51 @@ fn is_dylib(path: &Path) -> bool {
} }
} }
fn cargo_binary() -> String { /// Return a `String` to use for executable `cargo`.
env::var("CARGO").unwrap_or_else(|_| "cargo".to_string()) ///
/// E.g., this may just be `cargo` if that gives a valid Cargo executable; or it
/// may be a full path to a valid Cargo.
fn cargo_binary() -> Result<String> {
// The current implementation checks three places for a `cargo` to use:
// 1) $CARGO environment variable (erroring if this is set but not a usable Cargo)
// 2) `cargo`
// 3) `~/.cargo/bin/cargo`
if let Ok(path) = env::var("CARGO") {
if is_valid_cargo(&path) {
Ok(path)
} else {
Err(Error::msg("`CARGO` environment variable points to something that's not a valid Cargo executable"))
}
} else {
let final_path: Option<String> = if is_valid_cargo("cargo") {
Some("cargo".to_owned())
} else {
if let Some(mut path) = dirs::home_dir() {
path.push(".cargo");
path.push("bin");
path.push("cargo");
if is_valid_cargo(&path) {
Some(path.into_os_string().into_string().expect("Invalid Unicode in path"))
} else {
None
}
} else {
None
}
};
final_path.ok_or(
// This error message may also be caused by $PATH or $CARGO not being set correctly for VSCode,
// even if they are set correctly in a terminal.
// On macOS in particular, launching VSCode from terminal with `code <dirname>` causes VSCode
// to inherit environment variables including $PATH and $CARGO from that terminal; but
// launching VSCode from Dock does not inherit environment variables from a terminal.
// For more discussion, see #3118.
Error::msg("Failed to find `cargo` executable. Make sure `cargo` is in `$PATH`, or set `$CARGO` to point to a valid Cargo executable.")
)
}
}
/// Does the given `Path` point to a usable `Cargo`?
fn is_valid_cargo(p: impl AsRef<Path>) -> bool {
Command::new(p.as_ref()).arg("--version").output().is_ok()
} }