diff --git a/justfile b/justfile index 5e3b1ce..ca97264 100644 --- a/justfile +++ b/justfile @@ -16,7 +16,7 @@ delete-release tag: git push --delete origin v{{tag}} release tag: - cargo bump {{tag}} + cargo xtask bump {{tag}} git add Cargo.toml git diff --quiet Cargo.toml && git diff --staged --quiet || git commit -m "Bump version to {{tag}}" git pull origin main diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml index 98d5708..a5d80e0 100644 --- a/xtask/Cargo.toml +++ b/xtask/Cargo.toml @@ -7,4 +7,7 @@ edition = "2021" [dependencies] anyhow = "1.0.69" -xtaskops = "0.4.1" +cargo_metadata = "0.15.3" +clap = "4.1.6" +semver = "1.0.16" +toml_edit = "0.19.3" diff --git a/xtask/src/bump.rs b/xtask/src/bump.rs new file mode 100644 index 0000000..467bfe9 --- /dev/null +++ b/xtask/src/bump.rs @@ -0,0 +1,84 @@ +use anyhow::Result; +use cargo_metadata::MetadataCommand; +use clap::{arg, ArgMatches, Command}; +use toml_edit::{value, Document}; + +pub fn cli() -> Command { + Command::new("bump") + .about("Bump the version of the current crate") + .arg(arg!( "The version to bump to")) +} + +#[derive(Debug, Clone)] +pub enum Modifier { + Major, + Minor, + Patch, + Custom(semver::Version), +} + +impl Modifier { + pub fn parse(s: impl AsRef) -> Result { + let s = s.as_ref().trim(); + if s == "major" { + Ok(Self::Major) + } else if s == "minor" { + Ok(Self::Minor) + } else if s == "patch" { + Ok(Self::Patch) + } else { + Ok(Self::Custom(semver::Version::parse(s)?)) + } + } +} + +pub trait VersionModifier { + fn bump(&self, version: Modifier) -> semver::Version; +} + +impl VersionModifier for semver::Version { + fn bump(&self, version: Modifier) -> semver::Version { + match version { + Modifier::Major => { + let mut v = self.clone(); + v.major += 1; + v.minor = 0; + v.patch = 0; + v + } + Modifier::Minor => { + let mut v = self.clone(); + v.minor += 1; + v.patch = 0; + v + } + Modifier::Patch => { + let mut v = self.clone(); + v.patch += 1; + v + } + Modifier::Custom(v) => v, + } + } +} + +pub fn exec(matches: &ArgMatches) -> Result<()> { + let metadata_cmd = MetadataCommand::new(); + let metadata = metadata_cmd.exec()?; + let root_package = metadata.root_package().unwrap(); + let manifest = root_package.manifest_path.to_owned(); + let source = std::fs::read_to_string(manifest.to_owned())?; + let mut doc = source.parse::()?; + let modifier_str = matches + .get_one::("VERSION") + .expect("VERSION is required"); + let modifier = Modifier::parse(modifier_str)?; + + if let Some(version_str) = doc["package"]["version"].as_str() { + let version = semver::Version::parse(version_str)?; + let new_version = version.bump(modifier.clone()); + doc["package"]["version"] = value(new_version.to_string()); + std::fs::write(manifest, doc.to_string())?; + } + Ok(()) +} diff --git a/xtask/src/main.rs b/xtask/src/main.rs index f8985b5..c263e45 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -1,3 +1,16 @@ +use clap::Command; + +mod bump; + fn main() -> Result<(), anyhow::Error> { - xtaskops::tasks::main() + let app = Command::new("xtask") + .about("A task runner for the xtask crate") + .subcommand(bump::cli()) + .arg_required_else_help(true); + let matches = app.get_matches(); + + match matches.subcommand() { + Some(("bump", submatches)) => bump::exec(submatches), + _ => Ok(()), + } }