diff --git a/src/cli/rustup_mode.rs b/src/cli/rustup_mode.rs index ab04b735cf8..84b269feb2c 100644 --- a/src/cli/rustup_mode.rs +++ b/src/cli/rustup_mode.rs @@ -853,7 +853,7 @@ fn default_(cfg: &Cfg, m: &ArgMatches<'_>) -> Result { let status = if !toolchain.is_custom() { let distributable = DistributableToolchain::new(&toolchain)?; Some(distributable.install_from_dist_if_not_installed()?) - } else if !toolchain.exists() { + } else if !toolchain.exists() && toolchain.name() != "none" { return Err(RustupError::ToolchainNotInstalled(toolchain.name().to_string()).into()); } else { None diff --git a/src/config.rs b/src/config.rs index b91b94d21e3..0134ad4b7b6 100644 --- a/src/config.rs +++ b/src/config.rs @@ -382,7 +382,11 @@ impl Cfg { pub fn set_default(&self, toolchain: &str) -> Result<()> { self.settings_file.with_mut(|s| { - s.default_toolchain = Some(toolchain.to_owned()); + s.default_toolchain = if toolchain == "none" { + None + } else { + Some(toolchain.to_owned()) + }; Ok(()) })?; (self.notify_handler)(Notification::SetDefaultToolchain(toolchain)); diff --git a/src/notifications.rs b/src/notifications.rs index dd83e2b9a54..a1b171898fa 100644 --- a/src/notifications.rs +++ b/src/notifications.rs @@ -96,6 +96,7 @@ impl<'a> Display for Notification<'a> { Install(n) => n.fmt(f), Utils(n) => n.fmt(f), Temp(n) => n.fmt(f), + SetDefaultToolchain("none") => write!(f, "default toolchain unset"), SetDefaultToolchain(name) => write!(f, "default toolchain set to '{}'", name), SetOverrideToolchain(path, name) => write!( f, diff --git a/tests/cli-exact.rs b/tests/cli-exact.rs index 377e72dce2f..a9dad1afc11 100644 --- a/tests/cli-exact.rs +++ b/tests/cli-exact.rs @@ -4,7 +4,7 @@ pub mod mock; use crate::mock::clitools::{ - self, check_update_setup, expect_err_ex, expect_ok, expect_ok_ex, expect_stdout_ok, + self, check_update_setup, expect_err_ex, expect_ok, expect_ok_ex, expect_stdout_ok, expect_stderr_ok, self_update_setup, set_current_dist_date, Config, Scenario, }; use rustup::for_host; @@ -587,6 +587,14 @@ error: target '2016-03-1' not found in channel. Perhaps check https://doc.rust- }); } +#[test] +fn default_none() { + setup(&|config| { + expect_stderr_ok(config, &["rustup", "default", "none"], "info: default toolchain unset"); + expect_err_ex(config, &["rustc", "--version"], "", "error: no override and no default toolchain set\n"); + }) +} + #[test] fn list_targets() { setup(&|config| { diff --git a/tests/mock/clitools.rs b/tests/mock/clitools.rs index 20fed38c34b..dfa3ad62391 100644 --- a/tests/mock/clitools.rs +++ b/tests/mock/clitools.rs @@ -384,7 +384,15 @@ pub fn expect_err_ex(config: &Config, args: &[&str], stdout: &str, stderr: &str) println!("expected.ok: false"); print_indented("expected.stdout", stdout); print_indented("expected.stderr", stderr); - panic!(); + if out.ok { + panic!("expected command to fail"); + } else if out.stdout != stdout { + panic!("expected stdout to match"); + } else if out.stderr != stderr { + panic!("expected stderr to match"); + } else { + unreachable!() + } } } @@ -445,10 +453,16 @@ fn print_command(args: &[&str], out: &SanitizedOutput) { } fn print_indented(heading: &str, text: &str) { + let mut lines = text.lines().count(); + // The standard library treats `a\n` and `a` as both being one line. + // This is confusing when the test fails because of a missing newline. + if !text.is_empty() && !text.ends_with('\n') { + lines -= 1; + } println!( "{} ({} lines):\n {}", heading, - text.lines().count(), + lines, text.replace("\n", "\n ") ); }