diff --git a/CHANGELOG.md b/CHANGELOG.md index dc1e34c1..b98d17f6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,7 +20,7 @@ the [discussions section](https://github.com/foresterre/cargo-msrv/discussions). * Added a 'minimal' output option intended for machine-readable use when full json output is undesirable. * Added `--features` option, `--all-features` flag and `--no-default-features` flag, which are forwarded to the default compatibility check command -* Added `--add-component` option, which can be used to add a Rust component to a toolchain. +* Added `--component` option, which can be used to add one or more Rust components to a toolchain. * `cargo msrv verify` now supports Cargo [workspace inheritance](https://doc.rust-lang.org/cargo/reference/workspaces.html#the-package-table), and will now correctly inherit the MSRV (i.e. `package.rust-version`) defined by a workspace @@ -55,9 +55,10 @@ the [discussions section](https://github.com/foresterre/cargo-msrv/discussions). * Use compilation target instead of build machine target for MSRV checks. * Fix issue where `--manifest-path Cargo.toml` would yield an empty manifest path. * Supply provided components to `verify` subcommand. -* The CLI arguments `--target` and `--add-component` were previously inadvertently ignored when provided +* The CLI arguments `--target` and `--component` were previously inadvertently ignored when provided to `cargo msrv verify`. -* Fixed issue where some errors were not being reported (e.g. `cargo msrv verify` did not print an error if it wasn't possible to resolve the MSRV to check against). +* Fixed issue where some errors were not being reported (e.g. `cargo msrv verify` did not print an error if it wasn't + possible to resolve the MSRV to check against). ### Removed @@ -71,13 +72,14 @@ the [discussions section](https://github.com/foresterre/cargo-msrv/discussions). arguments `--features`, `--all-features`, `--no-default-features`, `--min`, `--max`, `--include-all-patch-releases` and `--release-source` are ignored when provided to the `verify` subcommand. Workaround: supply these arguments directly to the top-level command, e.g. `cargo msrv --all-features verify`. -* The CLI arguments `--target` and `--add-component` can be provided to both the top-level `cargo msrv` command, and +* The CLI arguments `--target` and `--component` can be provided to both the top-level `cargo msrv` command, and the `cargo msrv verify` subcommand, however if they're provided to both, then only the arguments of the subcommand are considered. - Example: `cargo msrv --target x --add-component a --add-component b verify --target y --add-component c --add-component d` - does not reject or collect the `--target x --add-component a --add-component b` portion; the program will only be - aware of the `--target y --add-component c --add-component d` arguments. -* The CLI arguments `--target` and `--add-component` are shown to be available globally (i.e. both at the top + Example: + `cargo msrv --target x --component a --component b verify --target y --component c --component d` + does not reject or collect the `--target x --component a --component b` portion; the program will only be + aware of the `--target y --component c --component d` arguments. +* The CLI arguments `--target` and `--component` are shown to be available globally (i.e. both at the top level `cargo msrv` command and at the subcommand level, e.g. `cargo msrv verify`), even for subcommands which do not consume these arguments like `cargo msrv list`. diff --git a/src/check/rustup_toolchain_check.rs b/src/check/rustup_toolchain_check.rs index 3617f262..2cf0d0ea 100644 --- a/src/check/rustup_toolchain_check.rs +++ b/src/check/rustup_toolchain_check.rs @@ -1,11 +1,11 @@ use crate::check::Check; use crate::context::EnvironmentContext; -use crate::download::{DownloadToolchain, ToolchainDownloader}; use crate::error::{IoError, IoErrorSource}; use crate::external_command::cargo_command::CargoCommand; use crate::external_command::rustup_command::RustupCommand; use crate::lockfile::LockfileHandler; use crate::reporter::event::{CheckMethod, CheckResult, CheckToolchain, Method}; +use crate::setup_toolchain::{SetupRustupToolchain, SetupToolchain}; use crate::toolchain::ToolchainSpec; use crate::{lockfile, CargoMSRVError, Outcome, Reporter, TResult}; use camino::{Utf8Path, Utf8PathBuf}; @@ -87,7 +87,7 @@ impl fmt::Debug for RustupToolchainCheck<'_, '_, R> { } fn setup_toolchain(reporter: &impl Reporter, toolchain: &ToolchainSpec) -> TResult<()> { - let downloader = ToolchainDownloader::new(reporter); + let downloader = SetupRustupToolchain::new(reporter); downloader.download(toolchain)?; Ok(()) diff --git a/src/cli/toolchain_opts.rs b/src/cli/toolchain_opts.rs index 64c8d3dc..ac1717d1 100644 --- a/src/cli/toolchain_opts.rs +++ b/src/cli/toolchain_opts.rs @@ -13,6 +13,8 @@ pub struct ToolchainOpts { /// Components be added to the toolchain /// /// Can be supplied multiple times to add multiple components. + /// + /// For example: --component rustc --component cargo #[arg(long, value_name = "COMPONENT", global = true)] - pub add_component: Vec, + pub component: Vec, } diff --git a/src/context.rs b/src/context.rs index 800ebe45..2f2827cb 100644 --- a/src/context.rs +++ b/src/context.rs @@ -197,7 +197,7 @@ impl TryFrom for ToolchainContext { let target: &'static str = String::leak(target); let components: &'static [&'static str] = Vec::leak( - opts.add_component + opts.component .into_iter() .map(|s| { let s: &'static str = String::leak(s); diff --git a/src/error.rs b/src/error.rs index 592fbfac..d9da8b75 100644 --- a/src/error.rs +++ b/src/error.rs @@ -92,7 +92,7 @@ pub enum CargoMSRVError { RustReleasesEmptyReleaseSet, #[error(transparent)] - RustupInstallFailed(#[from] RustupInstallFailed), + RustupError(#[from] RustupError), #[error("Check toolchain (with `rustup run `) failed.")] RustupRunWithCommandFailed, @@ -250,24 +250,49 @@ impl From> for CargoMSRVError { } } +#[derive(Debug, thiserror::Error)] +#[error(transparent)] +pub enum RustupError { + Install(#[from] RustupInstallError), + AddComponent(#[from] RustupAddComponentError), + AddTarget(#[from] RustupAddTargetError), +} + #[derive(Debug, thiserror::Error)] #[error( "Unable to install toolchain '{}', rustup reported:\n {}", toolchain_spec, stderr.trim_end().lines().collect::>().join("\n ").dimmed() )] -pub struct RustupInstallFailed { - pub(crate) toolchain_spec: String, - pub(crate) stderr: String, +pub struct RustupInstallError { + pub toolchain_spec: String, + pub stderr: String, } -impl RustupInstallFailed { - pub fn new(toolchain_spec: impl Into, stderr: impl Into) -> Self { - Self { - toolchain_spec: toolchain_spec.into(), - stderr: stderr.into(), - } - } +#[derive(Debug, thiserror::Error)] +#[error( + "Unable to add components '{}' to toolchain '{}', rustup reported:\n {}", + components, + toolchain_spec, + stderr.trim_end().lines().collect::>().join("\n ").dimmed() +)] +pub struct RustupAddComponentError { + pub components: String, + pub toolchain_spec: String, + pub stderr: String, +} + +#[derive(Debug, thiserror::Error)] +#[error( + "Unable to add target '{}' to toolchain '{}', rustup reported:\n {}", + targets, + toolchain_spec, + stderr.trim_end().lines().collect::>().join("\n ").dimmed() +)] +pub struct RustupAddTargetError { + pub targets: String, + pub toolchain_spec: String, + pub stderr: String, } #[derive(Debug, thiserror::Error)] diff --git a/src/lib.rs b/src/lib.rs index 41aafc63..94aa5117 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -43,7 +43,6 @@ pub mod toolchain; mod context; pub(crate) mod default_target; pub(crate) mod dependency_graph; -pub(crate) mod download; mod external_command; pub(crate) mod formatting; pub(crate) mod lockfile; @@ -55,6 +54,7 @@ mod release_index; pub(crate) mod releases_filter; mod rust_release; pub(crate) mod search_method; +pub(crate) mod setup_toolchain; pub(crate) mod sub_command; pub(crate) mod typed_bool; pub(crate) mod writer; diff --git a/src/download.rs b/src/setup_toolchain.rs similarity index 70% rename from src/download.rs rename to src/setup_toolchain.rs index a9762927..dc4335f1 100644 --- a/src/download.rs +++ b/src/setup_toolchain.rs @@ -1,29 +1,31 @@ -use crate::error::RustupInstallFailed; +use crate::error::{ + RustupAddComponentError, RustupAddTargetError, RustupError, RustupInstallError, +}; use crate::external_command::rustup_command::RustupCommand; -use crate::reporter::event::SetupToolchain; +use crate::reporter::event::SetupToolchain as SetupToolchainEvent; use crate::toolchain::ToolchainSpec; use crate::{CargoMSRVError, Reporter, TResult}; -pub trait DownloadToolchain { +pub trait SetupToolchain { fn download(&self, toolchain: &ToolchainSpec) -> TResult<()>; } #[derive(Debug)] -pub struct ToolchainDownloader<'reporter, R: Reporter> { +pub struct SetupRustupToolchain<'reporter, R: Reporter> { reporter: &'reporter R, } -impl<'reporter, R: Reporter> ToolchainDownloader<'reporter, R> { +impl<'reporter, R: Reporter> SetupRustupToolchain<'reporter, R> { pub fn new(reporter: &'reporter R) -> Self { Self { reporter } } } -impl<'reporter, R: Reporter> DownloadToolchain for ToolchainDownloader<'reporter, R> { +impl<'reporter, R: Reporter> SetupToolchain for SetupRustupToolchain<'reporter, R> { #[instrument(skip(self, toolchain))] fn download(&self, toolchain: &ToolchainSpec) -> TResult<()> { self.reporter - .run_scoped_event(SetupToolchain::new(toolchain.to_owned()), || { + .run_scoped_event(SetupToolchainEvent::new(toolchain.to_owned()), || { install_toolchain(toolchain) .and_then(|_| add_target(toolchain)) .and_then(|_| { @@ -57,9 +59,12 @@ fn install_toolchain(toolchain: &ToolchainSpec) -> TResult<()> { "rustup failed to install toolchain" ); - return Err(CargoMSRVError::RustupInstallFailed( - RustupInstallFailed::new(toolchain.spec(), rustup.stderr()), - )); + return Err(CargoMSRVError::RustupError(RustupError::Install( + RustupInstallError { + toolchain_spec: toolchain.spec().to_string(), + stderr: rustup.stderr().to_string(), + }, + ))); } Ok(()) @@ -94,9 +99,13 @@ fn add_target(toolchain: &ToolchainSpec) -> TResult<()> { "rustup failed to add target to toolchain" ); - return Err(CargoMSRVError::RustupInstallFailed( - RustupInstallFailed::new(toolchain.spec(), rustup.stderr()), - )); + return Err(CargoMSRVError::RustupError(RustupError::AddTarget( + RustupAddTargetError { + targets: toolchain.target().to_string(), + toolchain_spec: toolchain.spec().to_string(), + stderr: rustup.stderr().to_string(), + }, + ))); } Ok(()) @@ -135,9 +144,13 @@ fn add_components(toolchain: &ToolchainSpec) -> TResult<()> { "rustup failed to add component(s) to toolchain" ); - return Err(CargoMSRVError::RustupInstallFailed( - RustupInstallFailed::new(toolchain.spec(), rustup.stderr()), - )); + return Err(CargoMSRVError::RustupError(RustupError::AddComponent( + RustupAddComponentError { + components: toolchain.components().join(", "), + toolchain_spec: toolchain.spec().to_string(), + stderr: rustup.stderr().to_string(), + }, + ))); } Ok(())