use crate::executable::Executable;
use std::fmt;
#[derive(Debug, PartialEq, Eq, clap::Parser)]
pub enum Phase {
Check,
Format,
Build,
Test,
Doc,
Clippy,
Audit(AuditOptions),
}
#[derive(Debug, PartialEq, Eq, clap::Parser)]
pub struct AuditOptions {
#[clap(short, long, help = "Force an audit check.")]
force: bool,
}
impl Phase {
pub fn execute_everything() -> anyhow::Result<()> {
use crate::runner::Runner;
let everything: Vec<Phase> = Phase::list().collect();
crate::cdcrate::change_directory_to_crate_root()?;
let mut runner = Runner::new()?;
println!(
"\nrunning {} {} validations",
everything.len(),
env!("CARGO_PKG_NAME")
);
for phase in everything {
runner.run_phase(&phase)?;
}
runner.exit()
}
pub fn list() -> impl Iterator<Item = Phase> {
use Phase::*;
[
Check,
Format,
Clippy,
Build,
Test,
Doc,
Audit(AuditOptions { force: false }),
]
.into_iter()
}
pub fn max_phase_name_length() -> usize {
Phase::list()
.map(|p| p.to_string().chars().count())
.max()
.unwrap()
}
}
impl Executable for Option<Phase> {
fn execute(&self) -> anyhow::Result<()> {
if let Some(phase) = self {
phase.execute()
} else {
Phase::execute_everything()
}
}
}
impl Executable for Phase {
fn execute(&self) -> anyhow::Result<()> {
use crate::subcommands::{audit, cargo_builtin};
use Phase::*;
crate::cdcrate::change_directory_to_crate_root()?;
match self {
Audit(opts) => audit(opts.force),
Build => cargo_builtin(["build"], []),
Check => cargo_builtin(["check"], []),
Doc => cargo_builtin(["doc"], [("RUSTDOCFLAGS", "-D warnings")]),
Clippy => cargo_builtin(["clippy"], []),
Format => cargo_builtin(["fmt", "--", "--check"], []),
Test => cargo_builtin(["test"], []),
}
}
}
impl fmt::Display for Phase {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"{}",
match self {
Phase::Audit(opts) => format!("audit{}", if opts.force { " (force)" } else { "" }),
_ => format!("{:?}", self).to_lowercase(),
}
)
}
}