ci

CI for all possible combinations of features in Cargo.toml.
git clone https://git.philomathiclife.com/repos/ci
Log | Files | Refs | README

commit c1b52e436d4256bffd29a1059323c9ac079eede3
parent df7e4b016c9aad07aa08e7abe9573b6d9fc26631
Author: Zack Newman <zack@philomathiclife.com>
Date:   Thu,  8 Aug 2024 15:17:50 -0600

improve run_cmd

Diffstat:
MREADME.md | 4++--
Msrc/args.rs | 46++++++++++++++++++----------------------------
Msrc/main.rs | 17+++++------------
3 files changed, 25 insertions(+), 42 deletions(-)

diff --git a/README.md b/README.md @@ -7,8 +7,8 @@ feature `bar` and `bar` automatically enables feature `fizz`, then no combination of features that contains `foo` and `bar`, `foo` and `fizz`, or `bar` and `fizz` will be tested. -`ci` writes to `stdout` iff an error arises. The error is written as well as the command and features -that caused the error. +`ci` writes to `stderr` iff an error arises. The error is written as well as the command and features +that caused the error. `stdout` is never written to. ## Why is this useful? diff --git a/src/args.rs b/src/args.rs @@ -38,20 +38,14 @@ pub enum Opts { Tests, } impl Opts { - /// Returns the string representation of `self`. - const fn as_str(self) -> &'static str { - match self { - Self::None => "", - Self::Clippy => "clippy", - Self::DocTests => "doc_tests", - Self::Tests => "tests", - } - } /// Runs `cargo` with argument based on `self` and features of `features`. - #[allow(clippy::unreachable)] pub fn run_cmd(self, features: &str) -> Result<(), E> { match self { - Self::None => unreachable!("Opts::run_cmd must not be called on Opts::None"), + Self::None => Self::Clippy.run_cmd(features).and_then(|()| { + Self::DocTests + .run_cmd(features) + .and_then(|()| Self::Tests.run_cmd(features)) + }), Self::Clippy => { let mut args = vec!["clippy", "-q", "--no-default-features"]; if !features.is_empty() { @@ -141,23 +135,19 @@ impl Opts { /// Returns `Opts` based on arguments passed to the application. pub fn from_args() -> Result<Self, ArgsErr> { let mut args = env::args(); - if args.next().is_some() { - let mut opts = Self::None; - for arg in args { - if matches!(opts, Self::None) { - match arg.as_str() { - "clippy" => opts = Self::Clippy, - "doc_tests" => opts = Self::DocTests, - "tests" => opts = Self::Tests, - _ => return Err(ArgsErr::InvalidOption(arg)), - } - } else { - return Err(ArgsErr::InvalidOption(format!("{} {arg}", opts.as_str()))); + args.next().ok_or(ArgsErr::NoArgs).and_then(|_| { + args.next().map_or(Ok(Self::None), |arg| { + match arg.as_str() { + "clippy" => Ok(Self::Clippy), + "doc_tests" => Ok(Self::DocTests), + "tests" => Ok(Self::Tests), + _ => Err(ArgsErr::InvalidOption(arg)), } - } - Ok(opts) - } else { - Err(ArgsErr::NoArgs) - } + .and_then(|opts| { + args.next() + .map_or(Ok(opts), |opt| Err(ArgsErr::InvalidOption(opt))) + }) + }) + }) } } diff --git a/src/main.rs b/src/main.rs @@ -7,8 +7,8 @@ //! feature `bar` and `bar` automatically enables feature `fizz`, then no combination of features that contains //! `foo` and `bar`, `foo` and `fizz`, or `bar` and `fizz` will be tested. //! -//! `ci` writes to `stdout` iff an error arises. The error is written as well as the command and features -//! that caused the error. +//! `ci` writes to `stderr` iff an error arises. The error is written as well as the command and features +//! that caused the error. `stdout` is never written to. //! //! ## Why is this useful? //! @@ -110,17 +110,10 @@ fn main() -> Result<(), E> { fs::read_to_string("Cargo.toml") .map_err(E::Io) .and_then(|toml| manifest::from_toml(toml.as_str()).map_err(E::Toml)) - .and_then(|features| match opt { - Opts::None => features.into_iter().try_fold((), |(), feature| { - Opts::Clippy.run_cmd(feature.as_str()).and_then(|()| { - Opts::DocTests - .run_cmd(feature.as_str()) - .and_then(|()| Opts::Tests.run_cmd(feature.as_str())) - }) - }), - Opts::Clippy | Opts::DocTests | Opts::Tests => features + .and_then(|features| { + features .into_iter() - .try_fold((), |(), feature| opt.run_cmd(feature.as_str())), + .try_fold((), |(), feature| opt.run_cmd(feature.as_str())) }) }) }