Skip to content

Commit

Permalink
feat: Add CargoCommand with features and target options
Browse files Browse the repository at this point in the history
* Adds CargoCommand struct
* Unlike RustupCommand, not (yet) intended to run standalone, since we use rustup to run certain versions of toolchains
* Currently only used for "cargo check", but could be refactored to also include the likes of "cargo build" and friends (cargo build support could help for adding support for Rust < 1.16).
* Has options to forward features and target to cargo
  • Loading branch information
foresterre committed Nov 17, 2023
1 parent eb2e597 commit 728f5d4
Show file tree
Hide file tree
Showing 21 changed files with 362 additions and 30 deletions.
16 changes: 6 additions & 10 deletions src/check/rustup_toolchain_check.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use crate::check::Check;
use crate::command::cargo_command::CargoCommand;
use crate::command::rustup_command::RustupCommand;
use crate::context::EnvironmentContext;
use crate::download::{DownloadToolchain, ToolchainDownloader};
use crate::error::{IoError, IoErrorSource};
use crate::lockfile::LockfileHandler;
use crate::reporter::event::{CheckMethod, CheckResult, CheckToolchain, Method};
use crate::rustup_command::RustupCommand;
use crate::toolchain::ToolchainSpec;
use crate::{lockfile, CargoMSRVError, Outcome, Reporter, TResult};
use camino::{Utf8Path, Utf8PathBuf};
Expand Down Expand Up @@ -214,15 +215,10 @@ pub struct RunCommand {
}

impl RunCommand {
pub fn default(target: impl ToString) -> Self {
let command = vec![
"cargo".to_string(),
"check".to_string(),
"--target".to_string(),
target.to_string(),
];

Self { command }
pub fn default(cargo_command: CargoCommand) -> Self {
Self {
command: cargo_command.into_args(),
}
}

pub fn custom(command: Vec<String>) -> Self {
Expand Down
4 changes: 2 additions & 2 deletions src/cli.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::cli::custom_check_opts::CargoCheckOpts;
use crate::cli::custom_check_opts::CheckCommandOpts;
use crate::cli::find_opts::FindOpts;
use crate::cli::rust_releases_opts::RustReleasesOpts;
use crate::cli::shared_opts::SharedOpts;
Expand Down Expand Up @@ -150,7 +150,7 @@ pub struct VerifyOpts {
pub toolchain_opts: ToolchainOpts,

#[command(flatten)]
pub cargo_check_opts: CargoCheckOpts,
pub cargo_check_opts: CheckCommandOpts,

/// The Rust version, to check against for toolchain compatibility
///
Expand Down
14 changes: 13 additions & 1 deletion src/cli/custom_check_opts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,25 @@ use clap::Args;

#[derive(Debug, Args)]
#[command(next_help_heading = "Custom check options")]
pub struct CargoCheckOpts {
pub struct CheckCommandOpts {
/// Forwards the provided features to cargo, when running cargo-msrv with the default compatibility
/// check command.
///
/// If a custom a custom compatibility check command is used, this option is ignored.
#[arg(long)]
pub features: Option<Vec<String>>,

/// Forwards the --all-features flag to cargo, when running cargo-msrv with the default compatibility
/// check command.
///
/// If a custom a custom compatibility check command is used, this option is ignored.
#[arg(long, value_delimiter = ' ')]
pub all_features: bool,

/// Forwards the --no-default-features flag to cargo, when running cargo-msrv with the default compatibility
/// check command.
///
/// If a custom a custom compatibility check command is used, this option is ignored.
#[arg(long)]
pub no_default_features: bool,

Expand Down
4 changes: 2 additions & 2 deletions src/cli/find_opts.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::cli::custom_check_opts::CargoCheckOpts;
use crate::cli::custom_check_opts::CheckCommandOpts;
use crate::cli::rust_releases_opts::RustReleasesOpts;
use crate::cli::toolchain_opts::ToolchainOpts;
use clap::Args;
Expand Down Expand Up @@ -59,5 +59,5 @@ pub struct FindOpts {
pub toolchain_opts: ToolchainOpts,

#[command(flatten)]
pub custom_check_opts: CargoCheckOpts,
pub custom_check_opts: CheckCommandOpts,
}
2 changes: 2 additions & 0 deletions src/command.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub mod cargo_command;
pub mod rustup_command;
166 changes: 166 additions & 0 deletions src/command/cargo_command.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
#[derive(Debug, Default)]
pub struct CargoCommand {
features: Option<Vec<String>>,
all_features: bool,
no_default_features: bool,
target: Option<String>,
}

impl CargoCommand {
/// Set the features to be forwarded as `cargo <cmd> --features`
pub fn features(mut self, features: Option<Vec<String>>) -> Self {
self.features = features;
self
}

/// Set the `all features` flag to be forwarded as `cargo <cmd> --all-features`
pub fn all_features(mut self, value: bool) -> Self {
self.all_features = value;
self
}

/// Set the `no default features` flag to be forwarded as `cargo <cmd> --no-default-features`
pub fn no_default_features(mut self, value: bool) -> Self {
self.no_default_features = value;
self
}

/// Set the target flag to be forwarded as `cargo <cmd> --target
pub fn target(mut self, target: Option<impl ToString>) -> Self {
self.target = target.map(|t| t.to_string());
self
}

/// Intended to be used in conjunction with [`RunCommand`] and/or [`RustupCommand`].
///
/// [`RunCommand`]: crate::check::RunCommand
/// [`RustupCommand`]: crate::command::rustup_command::RustupCommand
// Currently we don't invoke it from here directly, but we might eventually, if
// we want to also provide some nicer structs around parsing. However compared to
// some other cargo subcommand crates, we also (currently) need rustup, so the invocation
// would need to supply everything we supply to rustup.
pub fn into_args(self) -> Vec<String> {
// Eventually we should also add support for CARGO env var
let mut args = Vec::<String>::with_capacity(8);

// Currently only `cargo check` is used by cargo msrv.
// Alternatives can be set when using cargo msrv -- custom cmd
// This value does open the path to use cargo build for Rust < 1.16
args.extend_from_slice(&["cargo".to_string(), "check".to_string()]);

if let Some(features) = self.features {
let features = features.join(",");

args.extend_from_slice(&["--features".to_string(), features]);
}

// probably unnecessary to supply both this and --features, if both have a value, but
// by adding both to the command separately, we can optimally invoke cargo's own behaviour
if self.all_features {
args.push("--all-features".to_string());
}

if self.no_default_features {
args.push("--no-default-features".to_string());
}

if let Some(target) = self.target {
args.push("--target".to_string());
args.push(target);
}

args
}
}

#[cfg(test)]
mod tests {
use crate::command::cargo_command::CargoCommand;

#[test]
fn set_features_none() {
let cargo_command = CargoCommand::default();
let cargo_command = cargo_command.features(None);
assert_eq!(
cargo_command.into_args().join(" "),
"cargo check".to_string()
);
}

#[test]
fn set_features_one() {
let cargo_command = CargoCommand::default();
let cargo_command = cargo_command.features(Some(vec!["pika".to_string()]));
assert_eq!(
cargo_command.into_args().join(" "),
"cargo check --features pika".to_string()
);
}

#[test]
fn set_features_two() {
let cargo_command = CargoCommand::default();
let cargo_command =
cargo_command.features(Some(vec!["chu".to_string(), "chris".to_string()]));
assert_eq!(
cargo_command.into_args().join(" "),
"cargo check --features chu,chris".to_string()
);
}

#[test]
fn set_no_default_features() {
let cargo_command = CargoCommand::default();
let cargo_command = cargo_command.no_default_features(true);
assert_eq!(
cargo_command.into_args().join(" "),
"cargo check --no-default-features".to_string()
);
}

#[test]
fn set_all_features() {
let cargo_command = CargoCommand::default();
let cargo_command = cargo_command.all_features(true);
assert_eq!(
cargo_command.into_args().join(" "),
"cargo check --all-features".to_string()
);
}

#[test]
fn set_target_none() {
let cargo_command = CargoCommand::default();
let cargo_command = cargo_command.target(None::<String>);
assert_eq!(
cargo_command.into_args().join(" "),
"cargo check".to_string()
);
}

#[test]
fn set_target_some() {
let cargo_command = CargoCommand::default();
let cargo_command = cargo_command.target(Some("some"));
assert_eq!(
cargo_command.into_args().join(" "),
"cargo check --target some".to_string()
);
}

#[test]
fn combination_of_everything() {
let cargo_command = CargoCommand::default();
let cargo_command = cargo_command
.features(Some(vec!["pika".to_string(), "chu".to_string()]))
.all_features(true)
.no_default_features(true)
.target(Some("pickme"));

let cmd = cargo_command.into_args().join(" ");
assert!(cmd.contains("--all-features"));
assert!(cmd.contains("--features pika,chu"));
assert!(cmd.contains("--no-default-features"));
assert!(cmd.contains("--target pickme"));
}
}
File renamed without changes.
8 changes: 4 additions & 4 deletions src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ pub mod set;
pub mod show;
pub mod verify;

use crate::cli::custom_check_opts::CargoCheckOpts;
use crate::cli::custom_check_opts::CheckCommandOpts;
use crate::cli::rust_releases_opts::Edition;
use crate::cli::{CargoMsrvOpts, SubCommand};
use crate::default_target::default_target;
Expand Down Expand Up @@ -191,7 +191,7 @@ impl TryFrom<ToolchainOpts> for ToolchainContext {
}

#[derive(Debug)]
pub struct CargoCheckContext {
pub struct CheckCommandContext {
pub cargo_features: Option<Vec<String>>,

pub cargo_all_features: bool,
Expand All @@ -202,8 +202,8 @@ pub struct CargoCheckContext {
pub rustup_command: Option<Vec<String>>,
}

impl From<CargoCheckOpts> for CargoCheckContext {
fn from(opts: CargoCheckOpts) -> Self {
impl From<CheckCommandOpts> for CheckCommandContext {
fn from(opts: CheckCommandOpts) -> Self {
Self {
cargo_features: opts.features,
cargo_all_features: opts.all_features,
Expand Down
13 changes: 10 additions & 3 deletions src/context/find.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use crate::check::RunCommand;
use crate::cli::CargoMsrvOpts;
use crate::command::cargo_command::CargoCommand;
use crate::context::{
CargoCheckContext, EnvironmentContext, RustReleasesContext, SearchMethod, ToolchainContext,
CheckCommandContext, EnvironmentContext, RustReleasesContext, SearchMethod, ToolchainContext,
UserOutputContext,
};
use crate::error::CargoMSRVError;
Expand Down Expand Up @@ -31,7 +32,7 @@ pub struct FindContext {
pub toolchain: ToolchainContext,

/// The context for checks to be used with rustup
pub check_cmd: CargoCheckContext,
pub check_cmd: CheckCommandContext,

/// Resolved environment options
pub environment: EnvironmentContext,
Expand Down Expand Up @@ -77,7 +78,13 @@ impl FindContext {
if let Some(custom) = &self.check_cmd.rustup_command {
RunCommand::custom(custom.clone())
} else {
RunCommand::default(self.toolchain.target.clone())
let cargo_command = CargoCommand::default()
.target(Some(self.toolchain.target.clone()))
.features(self.check_cmd.cargo_features.clone())
.all_features(self.check_cmd.cargo_all_features)
.no_default_features(self.check_cmd.cargo_no_default_features);

RunCommand::default(cargo_command)
}
}
}
14 changes: 11 additions & 3 deletions src/context/verify.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
use crate::cli::{CargoMsrvOpts, SubCommand};
use crate::context::{
CargoCheckContext, EnvironmentContext, RustReleasesContext, ToolchainContext, UserOutputContext,
CheckCommandContext, EnvironmentContext, RustReleasesContext, ToolchainContext,
UserOutputContext,
};

use crate::check::RunCommand;
use crate::command::cargo_command::CargoCommand;
use crate::error::CargoMSRVError;
use crate::sub_command::verify::RustVersion;
use std::convert::{TryFrom, TryInto};
Expand All @@ -26,7 +28,7 @@ pub struct VerifyContext {
pub toolchain: ToolchainContext,

/// The context for custom checks to be used with rustup
pub check_cmd: CargoCheckContext,
pub check_cmd: CheckCommandContext,

/// Resolved environment options
pub environment: EnvironmentContext,
Expand Down Expand Up @@ -76,7 +78,13 @@ impl VerifyContext {
if let Some(custom) = &self.check_cmd.rustup_command {
RunCommand::custom(custom.clone())
} else {
RunCommand::default(self.toolchain.target.clone())
let cargo_command = CargoCommand::default()
.target(Some(self.toolchain.target.clone()))
.features(self.check_cmd.cargo_features.clone())
.all_features(self.check_cmd.cargo_all_features)
.no_default_features(self.check_cmd.cargo_no_default_features);

RunCommand::default(cargo_command)
}
}
}
2 changes: 1 addition & 1 deletion src/default_target.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::command::rustup_command::RustupCommand;
use crate::error::{CargoMSRVError, TResult};
use crate::rustup_command::RustupCommand;

/// Uses the `.rustup/settings.toml` file to determine the default target (aka the
/// `default_host_triple`) if not set by a user.
Expand Down
2 changes: 1 addition & 1 deletion src/download.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::command::rustup_command::RustupCommand;
use crate::error::RustupInstallFailed;
use crate::reporter::event::SetupToolchain;
use crate::rustup_command::RustupCommand;
use crate::toolchain::ToolchainSpec;
use crate::{CargoMSRVError, Reporter, TResult};

Expand Down
4 changes: 3 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,16 @@ use rust_releases::semver;

pub mod check;
pub mod cli;

pub mod error;
pub mod exit_code;
pub mod io;
pub mod reporter;
pub mod toolchain;

pub(crate) mod combinators;

mod command;
mod context;
pub(crate) mod default_target;
pub(crate) mod dependency_graph;
Expand All @@ -52,7 +55,6 @@ pub(crate) mod outcome;
mod release_index;
pub(crate) mod releases_filter;
mod rust_release;
pub(crate) mod rustup_command;
pub(crate) mod search_method;
pub(crate) mod sub_command;
pub(crate) mod typed_bool;
Expand Down
Loading

0 comments on commit 728f5d4

Please sign in to comment.