Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions src/cli/rustup_mode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -887,13 +887,13 @@ async fn default_(
cfg.set_default(Some(&toolchain_name.into()))?;
}
MaybeResolvableToolchainName::Some(ResolvableToolchainName::Official(toolchain)) => {
let desc = toolchain.resolve(&cfg.default_host_tuple()?)?;
let desc = toolchain.clone().resolve(&cfg.default_host_tuple()?)?;
let status = cfg
.ensure_installed(&desc, vec![], vec![], None, force_non_host, true)
.await?
.status;

cfg.set_default(Some(&desc.clone().into()))?;
cfg.set_default(Some(&toolchain.into()))?;

writeln!(cfg.process.stdout().lock())?;

Expand Down Expand Up @@ -1091,7 +1091,7 @@ async fn update(
force_non_host,
)?;
}
let desc = name.resolve(&cfg.default_host_tuple()?)?;
let desc = name.clone().resolve(&cfg.default_host_tuple()?)?;

let components = opts.component.iter().map(|s| &**s).collect::<Vec<_>>();
let targets = opts.target.iter().map(|s| &**s).collect::<Vec<_>>();
Expand Down Expand Up @@ -1134,7 +1134,7 @@ async fn update(
if opts.default
|| (cfg.get_default()?.is_none() && matches!(status, UpdateStatus::Installed))
{
cfg.set_default(Some(&desc.into()))?;
cfg.set_default(Some(&name.into()))?;
}
}
exit_code &= self_update_mode.update(should_self_update, &dl_cfg).await?;
Expand Down
28 changes: 10 additions & 18 deletions src/cli/self_update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@ use crate::{
process::Process,
toolchain::{
DistributableToolchain, MaybeOfficialToolchainName, ResolvableToolchainName, Toolchain,
ToolchainName,
},
utils::{self, ExitCode},
};
Expand Down Expand Up @@ -252,7 +251,8 @@ impl InstallOpts<'_> {

let (components, targets) = (self.components, self.targets);
let toolchain = self.select_toolchain(cfg)?;
if let Some(desc) = toolchain {
if let Some(partial_desc) = toolchain {
let desc = partial_desc.clone().resolve(&cfg.default_host_tuple()?)?;
let options =
DistOptions::new(components, targets, &desc, cfg.get_profile()?, true, cfg)?;
let status = if Toolchain::exists(cfg, &desc.clone().into())? {
Expand All @@ -272,7 +272,7 @@ impl InstallOpts<'_> {

check_proxy_sanity(cfg.process, components, &desc)?;

cfg.set_default(Some(&desc.clone().into()))?;
cfg.set_default(Some(&partial_desc.into()))?;
Comment thread
rami3l marked this conversation as resolved.
writeln!(cfg.process.stdout().lock())?;
common::show_channel_update(cfg, PackageUpdate::Toolchain(desc), Ok(status))?;
}
Expand All @@ -284,7 +284,7 @@ impl InstallOpts<'_> {
/// This function first initializes the default profile and default host tuple in the
/// configuration, then returns the toolchain that should be installed, or `None` if none is
/// specified by the user.
fn select_toolchain(self, cfg: &mut Cfg<'_>) -> Result<Option<ToolchainDesc>> {
fn select_toolchain(self, cfg: &mut Cfg<'_>) -> Result<Option<PartialToolchainDesc>> {
let Self {
default_host_tuple,
default_toolchain,
Expand Down Expand Up @@ -342,18 +342,14 @@ impl InstallOpts<'_> {
MaybeOfficialToolchainName::None => unreachable!(),
MaybeOfficialToolchainName::Some(n) => n,
};
Some(toolchain_name.resolve(&cfg.default_host_tuple()?)?)
Some(toolchain_name)
}
None => match cfg.get_default()? {
None => match cfg.get_default_resolvable()? {
Comment thread
rami3l marked this conversation as resolved.
// Default is installable
Some(ToolchainName::Official(t)) => Some(t),
Some(ResolvableToolchainName::Official(t)) => Some(t),
// Default is custom, presumably from a prior install. Do nothing.
Some(ToolchainName::Custom(_)) => None,
None => Some(
"stable"
.parse::<PartialToolchainDesc>()?
.resolve(&cfg.default_host_tuple()?)?,
),
Some(ResolvableToolchainName::Custom(_)) => None,
None => Some(PartialToolchainDesc::from_str("stable")?),
Comment thread
rami3l marked this conversation as resolved.
},
})
} else {
Expand Down Expand Up @@ -1378,11 +1374,7 @@ mod tests {
};

assert_eq!(
"stable"
.parse::<PartialToolchainDesc>()
.unwrap()
.resolve(&cfg.default_host_tuple().unwrap())
.unwrap(),
"stable".parse::<PartialToolchainDesc>().unwrap(),
opts.select_toolchain(&mut cfg)
.unwrap() // result
.unwrap() // option
Expand Down
31 changes: 22 additions & 9 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,7 @@ impl<'a> Cfg<'a> {
Ok(cfg)
}

pub(crate) fn set_default(&self, toolchain: Option<&ToolchainName>) -> Result<()> {
pub(crate) fn set_default(&self, toolchain: Option<&ResolvableToolchainName>) -> Result<()> {
self.settings_file.with_mut(|s| {
s.default_toolchain = toolchain.map(|t| t.to_string());
Ok(())
Expand Down Expand Up @@ -900,10 +900,24 @@ impl<'a> Cfg<'a> {
})
}

/// Get the configured default toolchain.
/// If none is configured, returns None
/// If a bad toolchain name is configured, errors.
/// Gets the configured default toolchain name in its resolved form, if any.
///
/// This is essentially [`Cfg::get_default_resolvable()`] with an extra resolution step.
pub(crate) fn get_default(&self) -> Result<Option<ToolchainName>> {
let Some(toolchain) = self.get_default_resolvable()? else {
return Ok(None);
};
Ok(Some(toolchain.resolve(&self.default_host_tuple()?)?))
}

/// Gets the configured default toolchain name in its unresolved form, if any.
///
/// # Errors
///
/// This function returns an error if:
/// - The configuration file is invalid.
/// - The configuration file contains an illegal default toolchain name.
pub(crate) fn get_default_resolvable(&self) -> Result<Option<ResolvableToolchainName>> {
let user_opt = self.settings_file.with(|s| Ok(s.default_toolchain.clone()));
let toolchain_maybe_str = if let Some(fallback_settings) = &self.fallback_settings {
match user_opt {
Expand All @@ -913,11 +927,10 @@ impl<'a> Cfg<'a> {
} else {
user_opt
}?;
toolchain_maybe_str
.map(|s| ResolvableToolchainName::from_str(&s))
.transpose()?
.map(|t| t.resolve(&self.default_host_tuple()?))
.transpose()
let Some(toolchain) = &toolchain_maybe_str else {
return Ok(None);
};
Ok(Some(ResolvableToolchainName::from_str(toolchain)?))
}

/// List all the installed toolchains: that is paths in the toolchain dir
Expand Down
12 changes: 12 additions & 0 deletions src/toolchain/names.rs
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,18 @@ impl ResolvableLocalToolchainName {
}
}

impl From<PartialToolchainDesc> for ResolvableToolchainName {
fn from(value: PartialToolchainDesc) -> Self {
Self::Official(value)
}
}

impl From<CustomToolchainName> for ResolvableToolchainName {
fn from(value: CustomToolchainName) -> Self {
Self::Custom(value)
}
}

impl FromStr for ResolvableLocalToolchainName {
type Err = InvalidName;

Expand Down
4 changes: 2 additions & 2 deletions tests/suite/cli_exact.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ async fn update_once() {
info: syncing channel updates for nightly-[HOST_TUPLE]
info: latest update on 2015-01-02 for version 1.3.0 (hash-nightly-2)
info: downloading 4 components
info: default toolchain set to nightly-[HOST_TUPLE]
info: default toolchain set to nightly

"#]]);
cx.config
Expand Down Expand Up @@ -322,7 +322,7 @@ async fn default() {
info: syncing channel updates for nightly-[HOST_TUPLE]
info: latest update on 2015-01-02 for version 1.3.0 (hash-nightly-2)
info: downloading 4 components
info: default toolchain set to nightly-[HOST_TUPLE]
info: default toolchain set to nightly

"#]]);
cx.config
Expand Down
69 changes: 68 additions & 1 deletion tests/suite/cli_inst_interactive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ use std::env::consts::EXE_SUFFIX;
use std::io::Write;
use std::process::Stdio;

use rustup::test::{Assert, CliTestContext, Config, SanitizedOutput, Scenario, this_host_tuple};
use rustup::test::{
Assert, CROSS_ARCH1, CliTestContext, Config, SanitizedOutput, Scenario, this_host_tuple,
};
#[cfg(windows)]
use rustup::test::{RegistryGuard, USER_PATH};
use rustup::utils::raw;
Expand Down Expand Up @@ -685,3 +687,68 @@ warn: many Rust crates require a system C toolchain to build
...
"#]]);
}

// https://github.com/rust-lang/rustup/issues/3651#issuecomment-5058868560
#[tokio::test]
async fn install_defaults_to_default_host() {
let cx = CliTestContext::new(Scenario::SimpleV2).await;
let redactions = [("[RUSTUP_DIR]", &cx.config.rustupdir.to_string())];

cx.config
.expect([
"rustup-init",
"-y",
"--no-modify-path",
"--default-toolchain=beta",
])
.await
.is_ok();

cx.config
.expect(["rustup", "show"])
.await
.extend_redactions(redactions)
.is_ok()
.with_stdout(snapbox::str![[r#"
Default host: [HOST_TUPLE]
rustup home: [RUSTUP_DIR]

installed toolchains
--------------------
beta-[HOST_TUPLE] (active, default)

active toolchain
----------------
name: beta-[HOST_TUPLE]
active because: it's the default toolchain
installed targets:
[HOST_TUPLE]

"#]]);

cx.config
.expect(["rustup", "set", "default-host", CROSS_ARCH1])
.await
.is_ok()
.with_stdout(snapbox::str![[r#""#]]);

cx.config
.expect_with_env(["rustup", "show"], [("RUSTUP_AUTO_INSTALL", "0")])
.await
.extend_redactions(redactions)
.is_ok()
.with_stdout(snapbox::str![[r#"
Default host: [CROSS_ARCH_I]
rustup home: [RUSTUP_DIR]

installed toolchains
--------------------
beta-[HOST_TUPLE]

active toolchain
----------------
name: beta-[CROSS_ARCH_I]
active because: it's the default toolchain

"#]]);
}
66 changes: 63 additions & 3 deletions tests/suite/cli_rustup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ async fn default() {
info: syncing channel updates for nightly-[HOST_TUPLE]
info: latest update on 2015-01-02 for version 1.3.0 (hash-nightly-2)
info: downloading 4 components
info: default toolchain set to nightly-[HOST_TUPLE]
info: default toolchain set to nightly

"#]])
.is_ok();
Expand Down Expand Up @@ -327,7 +327,7 @@ async fn default_override() {
.await
.with_stderr(snapbox::str![[r#"
info: using existing install for stable-[HOST_TUPLE]
info: default toolchain set to stable-[HOST_TUPLE]
info: default toolchain set to stable
info: note that the toolchain 'nightly-[HOST_TUPLE]' is currently in use (directory override for '[..]')

"#]])
Expand Down Expand Up @@ -4032,7 +4032,7 @@ async fn custom_toolchain_with_components_toolchains_profile_does_not_err() {
info: syncing channel updates for nightly-[HOST_TUPLE]
info: latest update on 2015-01-02 for version 1.3.0 (hash-nightly-2)
info: downloading 2 components
info: default toolchain set to nightly-[HOST_TUPLE]
info: default toolchain set to nightly

"#]])
.is_ok();
Expand Down Expand Up @@ -4264,3 +4264,63 @@ fn nightly_manifest_path(cx: &CliTestContext) -> PathBuf {
.join("rustlib")
.join("multirust-channel-manifest.toml")
}

// https://github.com/rust-lang/rustup/issues/3651#issuecomment-5058814392
#[tokio::test]
async fn default_stores_unqualified_toolchains() {
let cx = CliTestContext::new(Scenario::SimpleV2).await;
let redactions = [("[RUSTUP_DIR]", &cx.config.rustupdir.to_string())];

cx.config
.expect(["rustup", "default", "beta"])
.await
.is_ok();

cx.config
.expect(["rustup", "show"])
.await
.extend_redactions(redactions)
.is_ok()
.with_stdout(snapbox::str![[r#"
Default host: [HOST_TUPLE]
rustup home: [RUSTUP_DIR]

installed toolchains
--------------------
beta-[HOST_TUPLE] (active, default)

active toolchain
----------------
name: beta-[HOST_TUPLE]
active because: it's the default toolchain
installed targets:
[HOST_TUPLE]

"#]]);

cx.config
.expect(["rustup", "set", "default-host", CROSS_ARCH1])
.await
.is_ok()
.with_stdout(snapbox::str![[r#""#]]);

cx.config
.expect_with_env(["rustup", "show"], [("RUSTUP_AUTO_INSTALL", "0")])
.await
.extend_redactions(redactions)
.is_ok()
.with_stdout(snapbox::str![[r#"
Default host: [CROSS_ARCH_I]
rustup home: [RUSTUP_DIR]

installed toolchains
--------------------
beta-[HOST_TUPLE]

active toolchain
----------------
name: beta-[CROSS_ARCH_I]
active because: it's the default toolchain

"#]]);
}
2 changes: 1 addition & 1 deletion tests/suite/cli_rustup_ui/rustup_default.stderr.term.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading