use xshell::Shell;
use crate::environment::ProgressGuard;
use crate::toolchain::Toolchain;
const COMPONENTS: &str = "rust-src,clippy,rustfmt";
const TARGET: &str = "thumbv7m-none-eabi";
const NOT_CONFIGURED: &str = "(not configured)";
#[allow(clippy::fn_params_excessive_bools)]
pub fn run(
sh: &Shell,
update_nightly: bool,
update_stable: bool,
msrv: bool,
nightly: bool,
stable: bool,
) -> Result<(), Box<dyn std::error::Error>> {
let _progress = ProgressGuard::new();
if msrv {
if let Some(msrv) = Toolchain::Msrv.try_read_version(sh) {
println!("{}", msrv);
}
return Ok(());
}
if nightly {
if let Some(nightly_version) = Toolchain::Nightly.try_read_version(sh) {
println!("{}", nightly_version);
}
return Ok(());
}
if stable {
if let Some(stable_version) = Toolchain::Stable.try_read_version(sh) {
println!("{}", stable_version);
}
return Ok(());
}
if update_nightly {
install_toolchain(sh, "nightly")?;
let version = resolve_nightly_version(sh)?;
Toolchain::Nightly.write_version(sh, &version)?;
rbmt_eprintln!("Updated nightly-version: {}", version);
}
if update_stable {
install_toolchain(sh, "stable")?;
let version = resolve_stable_version(sh)?;
Toolchain::Stable.write_version(sh, &version)?;
rbmt_eprintln!("Updated stable-version: {}", version);
}
let nightly_status = if let Some(version) = Toolchain::Nightly.try_read_version(sh) {
install_toolchain(sh, &version)?;
version
} else {
rbmt_eprintln!("No pinned nightly toolchain found in [workspace.metadata.rbmt.toolchains] or [package.metadata.rbmt.toolchains]");
NOT_CONFIGURED.to_string()
};
let stable_status = if let Some(version) = Toolchain::Stable.try_read_version(sh) {
install_toolchain(sh, &version)?;
version
} else {
rbmt_eprintln!("No pinned stable toolchain found in [workspace.metadata.rbmt.toolchains] or [package.metadata.rbmt.toolchains]");
NOT_CONFIGURED.to_string()
};
let msrv_status = if let Some(version) = Toolchain::Msrv.try_read_version(sh) {
install_toolchain(sh, &version)?;
version
} else {
rbmt_eprintln!("No MSRV (rust-version) found in any Cargo.toml in the workspace");
NOT_CONFIGURED.to_string()
};
rbmt_eprintln!(
"Toolchain installation complete: nightly={}, stable={}, msrv={}",
nightly_status,
stable_status,
msrv_status
);
Ok(())
}
fn resolve_nightly_version(sh: &Shell) -> Result<String, Box<dyn std::error::Error>> {
let output = rbmt_cmd!(sh, "rustc +nightly --verbose --version").read()?;
let date = output
.lines()
.find_map(|line| line.strip_prefix("commit-date: "))
.ok_or("Could not find commit-date in `rustc +nightly --verbose --version` output")?;
Ok(format!("nightly-{}", date))
}
fn resolve_stable_version(sh: &Shell) -> Result<String, Box<dyn std::error::Error>> {
let output = rbmt_cmd!(sh, "rustc +stable --version").read()?;
let version = output
.strip_prefix("rustc ")
.and_then(|s| s.split_whitespace().next())
.ok_or("Could not parse version from `rustc +stable --version` output")?;
Ok(version.to_string())
}
fn install_toolchain(sh: &Shell, toolchain: &str) -> Result<(), Box<dyn std::error::Error>> {
rbmt_eprintln!("Installing toolchain {}", toolchain);
rbmt_cmd!(
sh,
"rustup toolchain install {toolchain} --component {COMPONENTS} --target {TARGET} --no-self-update"
)
.env("RUSTUP_PERMIT_COPY_RENAME", "true")
.ignore_stdout()
.run()?;
Ok(())
}