use anyhow::Result;
use clap::{Parser, Subcommand};
use crate::cargo_toml::CargoToml;
use crate::git::Git;
use crate::version::Version;
const ABOUT: &str = r#"Cargo plugin to bump crate's versions and Git tag them
for release.
"cargo tag" helps to automate the process of bumping versions
similar to how "npm version" does.
When bumping versions with "cargo tag", the
Cargo.toml and Cargo.lock files are updated with the new version, then a Git
commit and a Git tag are both created."#;
#[derive(Parser)]
#[command(bin_name = "cargo")]
#[command(next_line_help = true)]
#[command(name = "cargo", author, version, about, long_about = Some(ABOUT))]
pub enum Cli {
Tag(TagArgs),
}
#[derive(clap::Args, Debug)]
pub struct TagArgs {
#[command(subcommand)]
pub command: Command,
#[arg(short, long)]
pub prefix: Option<String>,
#[arg(long)]
pub no_commit: bool,
#[arg(long)]
pub no_tag: bool,
#[arg(long)]
pub env: bool,
#[arg(long)]
pub dry_run: bool,
}
#[derive(Clone, Subcommand, Debug)]
pub enum Command {
Current,
Minor,
Major,
Patch,
#[clap(name = "prerelease")]
PreRelease { prerelease: String },
}
impl Command {
pub fn exec(&self, args: &TagArgs) -> Result<()> {
let cargo_toml = CargoToml::open()?;
let mut version = Version::from(&cargo_toml.manifest.package().version);
match *self {
Command::Current => {
println!("{}", cargo_toml.manifest.package().version);
return Ok(());
}
Command::Major | Command::Minor | Command::Patch => {
match self {
Command::Major => version.bump_major(),
Command::Minor => version.bump_minor(),
Command::Patch => version.bump_patch(),
_ => unreachable!(),
};
if !args.dry_run {
cargo_toml.write_version(&version)?;
cargo_toml.run_cargo_fetch()?;
}
}
Command::PreRelease { ref prerelease } => {
version.set_prerelease(prerelease)?;
if !args.dry_run {
cargo_toml.write_version(&version)?;
cargo_toml.run_cargo_fetch()?;
}
}
}
let prefix = args.prefix.clone().unwrap_or_default();
let version_str = prefix + &version.to_string();
if !args.dry_run {
let repository = if args.env {
Git::from_env("main")?
} else {
Git::from_git_config("main")?
};
if !args.no_commit {
repository.commit(&format!("chore: bump version to {}", version_str))?;
}
if !args.no_tag {
repository.tag(
&version_str,
&format!("chore: bump version to {}", version_str),
)?;
}
}
println!("{version_str}");
Ok(())
}
}