diff --git a/garde/Cargo.toml b/garde/Cargo.toml index 47d50e8..e97c20d 100644 --- a/garde/Cargo.toml +++ b/garde/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "garde" -version = "0.16.2" +version = "0.16.3" edition = "2021" repository = "https://github.com/jprochazk/garde" license = "MIT OR Apache-2.0" diff --git a/garde_derive/Cargo.toml b/garde_derive/Cargo.toml index 34c3fcd..950f0f3 100644 --- a/garde_derive/Cargo.toml +++ b/garde_derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "garde_derive" -version = "0.16.2" +version = "0.16.3" edition = "2021" repository = "https://github.com/jprochazk/garde" license = "MIT OR Apache-2.0" diff --git a/integrations/axum_garde/Cargo.toml b/integrations/axum_garde/Cargo.toml index 2dacc6d..243d4cd 100644 --- a/integrations/axum_garde/Cargo.toml +++ b/integrations/axum_garde/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "axum_garde" -version = "0.16.2" +version = "0.16.3" edition = "2021" repository = "https://github.com/jprochazk/garde" license = "MIT OR Apache-2.0" diff --git a/xtask/src/task.rs b/xtask/src/task.rs index f7d2e27..4c1f938 100644 --- a/xtask/src/task.rs +++ b/xtask/src/task.rs @@ -14,7 +14,7 @@ pub enum Task { Test(test::Test), Check(check::Check), Setup(setup::Setup), - // Version(Version), + Version(version::Version), // Release(Release), } @@ -24,6 +24,7 @@ impl Task { Task::Test(cmd) => cmd.run(), Task::Check(cmd) => cmd.run(), Task::Setup(cmd) => cmd.run(), + Task::Version(cmd) => cmd.run(), } } } diff --git a/xtask/src/task/setup.rs b/xtask/src/task/setup.rs index 4c86580..fdb6940 100644 --- a/xtask/src/task/setup.rs +++ b/xtask/src/task/setup.rs @@ -9,6 +9,8 @@ const TOOLS: &[&str] = &[ "cargo-udeps", "cargo-pants", "cargo-insta", + "cargo-semver-checks", + "cargo-workspaces", "wasm-bindgen-cli", ]; diff --git a/xtask/src/task/test.rs b/xtask/src/task/test.rs index 52c19fa..7d6a457 100644 --- a/xtask/src/task/test.rs +++ b/xtask/src/task/test.rs @@ -52,9 +52,9 @@ impl argp::FromArgValue for Target { ]; options - .iter() - .find(|(name, _)| value.eq_ignore_ascii_case(std::ffi::OsStr::new(*name))) - .map(|(_, target)| *target) + .into_iter() + .find(|(name, _)| value.eq_ignore_ascii_case(std::ffi::OsStr::new(name))) + .map(|(_, target)| target) .ok_or_else(|| "invalid target, expected one of: unit, doc, ui, rules, axum".into()) } } diff --git a/xtask/src/task/version.rs b/xtask/src/task/version.rs index f3764a2..c9315b8 100644 --- a/xtask/src/task/version.rs +++ b/xtask/src/task/version.rs @@ -1,13 +1,60 @@ use argp::FromArgs; +use crate::util::{cargo, CommandExt}; use crate::Result; #[derive(FromArgs)] #[argp(subcommand, name = "version", description = "Bump crate versions")] -pub struct Version {} +pub struct Version { + #[argp(positional, description = "one of: major, minor, patch")] + bump: Bump, +} + +enum Bump { + Patch, + Minor, + Major, +} + +impl Bump { + fn as_str(&self) -> &'static str { + match self { + Bump::Patch => "patch", + Bump::Minor => "minor", + Bump::Major => "major", + } + } +} + +impl argp::FromArgValue for Bump { + fn from_arg_value(value: &std::ffi::OsStr) -> std::result::Result { + let options = [ + ("patch", Bump::Patch), + ("minor", Bump::Minor), + ("major", Bump::Major), + ]; + + options + .into_iter() + .find(|(name, _)| value.eq_ignore_ascii_case(name)) + .map(|(_, bump)| bump) + .ok_or_else(|| "invalid bump kind, expected one of: major, minor, patch".into()) + } +} impl Version { pub fn run(self) -> Result { + // TODO: manually parse workspace and bump versions + cargo("workspaces") + .with_arg("version") + .with_arg(self.bump.as_str()) + .with_args(["--force", "*"]) + .run_async()?; + + cargo("semver-checks") + .with_arg("--all-features") + .run_async()?; + Ok(()) } } diff --git a/xtask/src/util.rs b/xtask/src/util.rs index e137d0e..8979e91 100644 --- a/xtask/src/util.rs +++ b/xtask/src/util.rs @@ -43,6 +43,8 @@ pub trait CommandExt { K: AsRef, V: AsRef; + fn run_async(self) -> Result; + fn run(self) -> Result; fn run_with_output(self) -> Result; @@ -75,6 +77,10 @@ impl CommandExt for Command { self } + fn run_async(mut self) -> Result { + self.spawn()?.wait_async() + } + fn run(mut self) -> Result { self.spawn()?.wait()?.check() } @@ -111,3 +117,19 @@ impl CheckStatus for std::process::Output { self.status.check() } } + +pub trait WaitAsync { + /// Wait with inherited IO + fn wait_async(self) -> Result; +} + +impl WaitAsync for std::process::Child { + fn wait_async(mut self) -> Result { + loop { + if let Some(status) = self.try_wait()? { + status.check()?; + return Ok(()); + } + } + } +}