From 6824535fc6ff6b3fc0f84a1b5929d93f997fd43e Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Tue, 12 Sep 2017 16:30:06 +0200 Subject: [PATCH 1/2] Automatically install override toolchain when missing. A typical scenario is: * I work on a repository that uses `rust-toolchain` to pin to a specific Nightly version * I run `git pull`, `rust-toolchain` has been changed to update to a new Rust version * I run `cargo build` Result before this PR (typically): rustup fails with an error like: ``` error: override toolchain 'nightly-2017-08-31' is not installed info: caused by: the toolchain file at '/home/simon/projects/servo/rust-toolchain' specifies an uninstalled toolchain ``` A better result would be to install toolchains as needed. Closes #1218 --- src/rustup/config.rs | 22 +++++++++++++--------- tests/cli-rustup.rs | 14 ++++++-------- tests/cli-v1.rs | 3 +-- tests/cli-v2.rs | 3 +-- 4 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/rustup/config.rs b/src/rustup/config.rs index a05126c5a3..b35bd02766 100644 --- a/src/rustup/config.rs +++ b/src/rustup/config.rs @@ -259,16 +259,20 @@ impl Cfg { } }; - match self.verify_toolchain(&name) { - Ok(t) => { - Ok(Some((t, reason))) + match self.get_toolchain(&name, false) { + Ok(toolchain) => { + if toolchain.exists() { + Ok(Some((toolchain, reason))) + } else if toolchain.is_custom() { + // Strip the confusing NotADirectory error and only mention that the override + // toolchain is not installed. + Err(Error::from(reason_err)) + .chain_err(|| ErrorKind::OverrideToolchainNotInstalled(name.to_string())) + } else { + try!(toolchain.install_from_dist()); + Ok(Some((toolchain, reason))) + } } - Err(Error(ErrorKind::Utils(::rustup_utils::ErrorKind::NotADirectory { .. }), _)) => { - // Strip the confusing NotADirectory error and only mention that the override - // toolchain is not installed. - Err(Error::from(reason_err)) - .chain_err(|| ErrorKind::OverrideToolchainNotInstalled(name.to_string())) - }, Err(e) => { Err(e) .chain_err(|| Error::from(reason_err)) diff --git a/tests/cli-rustup.rs b/tests/cli-rustup.rs index a1044ab321..ad88e4bb38 100644 --- a/tests/cli-rustup.rs +++ b/tests/cli-rustup.rs @@ -4,7 +4,6 @@ extern crate rustup_dist; extern crate rustup_utils; extern crate rustup_mock; extern crate tempdir; -extern crate regex; use std::fs; use std::env::consts::EXE_SUFFIX; @@ -16,7 +15,6 @@ use rustup_mock::clitools::{self, Config, Scenario, expect_err, set_current_dist_date, this_host_triple}; -use regex::Regex; macro_rules! for_host { ($s: expr) => (&format!($s, this_host_triple())) } @@ -621,15 +619,15 @@ fn show_toolchain_override_not_installed() { setup(&|config| { expect_ok(config, &["rustup", "override", "add", "nightly"]); expect_ok(config, &["rustup", "toolchain", "remove", "nightly"]); - // I'm not sure this should really be erroring when the toolchain - // is not installed; just capturing the behavior. let mut cmd = clitools::cmd(config, "rustup", &["show"]); clitools::env(config, &mut cmd); let out = cmd.output().unwrap(); assert!(out.status.success()); let stdout = String::from_utf8(out.stdout).unwrap(); + let stderr = String::from_utf8(out.stderr).unwrap(); assert!(!stdout.contains("not a directory")); - assert!(Regex::new(r"error: override toolchain 'nightly.*' is not installed, the directory override for '.*' specifies an uninstalled toolchain").unwrap().is_match(&stdout)) + assert!(!stdout.contains("is not installed")); + assert!(stderr.contains("info: installing component 'rustc'")); }); } @@ -658,11 +656,11 @@ fn show_toolchain_env_not_installed() { clitools::env(config, &mut cmd); cmd.env("RUSTUP_TOOLCHAIN", "nightly"); let out = cmd.output().unwrap(); - // I'm not sure this should really be erroring when the toolchain - // is not installed; just capturing the behavior. assert!(out.status.success()); let stdout = String::from_utf8(out.stdout).unwrap(); - assert!(stdout.contains("override toolchain 'nightly' is not installed, the RUSTUP_TOOLCHAIN environment variable specifies an uninstalled toolchain")); + let stderr = String::from_utf8(out.stderr).unwrap(); + assert!(!stdout.contains("is not installed")); + assert!(stderr.contains("info: installing component 'rustc'")); }); } diff --git a/tests/cli-v1.rs b/tests/cli-v1.rs index e130d0e143..98a0699ef0 100644 --- a/tests/cli-v1.rs +++ b/tests/cli-v1.rs @@ -139,8 +139,7 @@ fn remove_override_toolchain_err_handling() { expect_ok(config, &["rustup", "default", "nightly"]); expect_ok(config, &["rustup", "override", "add", "beta"]); expect_ok(config, &["rustup", "toolchain", "remove", "beta"]); - expect_err(config, &["rustc"], - for_host!("toolchain 'beta-{0}' is not installed")); + expect_stderr_ok(config, &["rustc", "--version"], "info: installing component"); }); }); } diff --git a/tests/cli-v2.rs b/tests/cli-v2.rs index 10a5f1ddc6..30adb952f1 100644 --- a/tests/cli-v2.rs +++ b/tests/cli-v2.rs @@ -182,8 +182,7 @@ fn remove_override_toolchain_err_handling() { expect_ok(config, &["rustup", "default", "nightly"]); expect_ok(config, &["rustup", "override", "add", "beta"]); expect_ok(config, &["rustup", "toolchain", "remove", "beta"]); - expect_err(config, &["rustc"], - for_host!("toolchain 'beta-{0}' is not installed")); + expect_stderr_ok(config, &["rustc", "--version"], "info: installing component"); }); }); } From eae31319e01f2ab86c6f686ad77dabd69402365d Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Mon, 16 Oct 2017 02:03:24 +0200 Subject: [PATCH 2/2] More tests for override auto-install --- tests/cli-v2.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/tests/cli-v2.rs b/tests/cli-v2.rs index 30adb952f1..29bf18938d 100644 --- a/tests/cli-v2.rs +++ b/tests/cli-v2.rs @@ -187,6 +187,24 @@ fn remove_override_toolchain_err_handling() { }); } +#[test] +fn file_override_toolchain_err_handling() { + setup(&|config| { + let cwd = config.current_dir(); + let toolchain_file = cwd.join("rust-toolchain"); + rustup_utils::raw::write_file(&toolchain_file, "beta").unwrap(); + expect_stderr_ok(config, &["rustc", "--version"], "info: installing component"); + }); +} + +#[test] +fn plus_override_toolchain_err_handling() { + setup(&|config| { + expect_err(config, &["rustc", "+beta"], + for_host!("toolchain 'beta-{0}' is not installed")); + }); +} + #[test] fn bad_sha_on_manifest() { setup(&|config| {