diff --git a/src/cli/rustup_mode.rs b/src/cli/rustup_mode.rs index 67ec21b7cf..c2433105e1 100644 --- a/src/cli/rustup_mode.rs +++ b/src/cli/rustup_mode.rs @@ -378,6 +378,10 @@ struct UpdateOpts { #[arg(long)] no_self_update: bool, + /// Don't try to update the installed toolchain + #[arg(long)] + no_update: bool, + /// Force an update, even if some components are missing #[arg(long)] force: bool, @@ -967,8 +971,12 @@ async fn update( let profile = cfg.get_profile()?; let status = match DistributableToolchain::new(cfg, desc.clone()) { Ok(mut d) => { - d.update_extra(&components, &targets, profile, force, allow_downgrade) - .await? + if !opts.no_update { + d.update_extra(&components, &targets, profile, force, allow_downgrade) + .await? + } else { + UpdateStatus::Unchanged + } } Err(RustupError::ToolchainNotInstalled { .. }) => { DistributableToolchain::install( diff --git a/tests/suite/cli_rustup.rs b/tests/suite/cli_rustup.rs index 7b1b0787dc..6dcd7cc53e 100644 --- a/tests/suite/cli_rustup.rs +++ b/tests/suite/cli_rustup.rs @@ -1737,6 +1737,32 @@ info: it's active because: overridden by '[TOOLCHAIN_FILE]' .is_ok(); } +#[tokio::test] +async fn toolchain_install_no_change_with_no_update() { + let mut cx = CliTestContext::new(Scenario::None).await; + + { + let cx = cx.with_dist_dir(Scenario::ArchivesV2_2015_01_01); + cx.config + .expect(["rustup", "toolchain", "add", "stable"]) + .await + .is_ok(); + } + + let cx = cx.with_dist_dir(Scenario::SimpleV2); + cx.config + .expect(["rustup", "install", "--no-update", "stable"]) + .await + .with_stdout(snapbox::str![[r#" + + stable-[HOST_TRIPLE] unchanged - 1.0.0 (hash-stable-1.0.0) + + +"#]]) + .with_stderr(snapbox::str![[""]]) + .is_ok(); +} + #[tokio::test] async fn toolchain_update_is_like_update() { let cx = CliTestContext::new(Scenario::SimpleV2).await;