use crate::error::{CommandExitCode, Result};
use clap::{Parser, Subcommand};
pub mod owners;
pub mod release;
pub use owners::OwnersSubCommands;
pub use release::{
AnalyzeOpts, BumpOpts, CheckOpts, PlanOpts, PublishOpts, ReleaseSubCommands, ResumeOpts,
SimulateOpts, StatusOpts,
};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum OutputFormat {
Json,
Yaml,
Human,
}
impl OutputFormat {
pub fn from_str(s: &str) -> Option<Self> {
match s.to_lowercase().as_str() {
"json" => Some(Self::Json),
"yaml" => Some(Self::Yaml),
"human" => Some(Self::Human),
_ => None,
}
}
}
#[derive(Parser, Debug)]
#[command(name = "cargo-governor")]
#[command(bin_name = "cargo-governor")]
#[command(about, long_about = None)]
#[command(version)]
#[command(propagate_version = true)]
pub struct Cli {
#[arg(hide = true)]
pub governor: Option<String>,
#[arg(short = 'w', long, global = true)]
pub workspace: Option<String>,
#[arg(short = 'c', long, global = true)]
pub config: Option<String>,
#[arg(short = 'f', long, global = true)]
pub format: Option<String>,
#[arg(short = 'o', long, global = true)]
pub output: Option<String>,
#[arg(short = 'v', long, global = true)]
pub verbose: bool,
#[arg(short = 'q', long, global = true)]
pub quiet: bool,
#[arg(long, global = true)]
pub dry_run: bool,
#[command(subcommand)]
pub command: Commands,
}
#[derive(Subcommand, Debug)]
pub enum Commands {
#[command(name = "owners")]
Owners {
#[command(subcommand)]
subcmd: OwnersSubCommands,
},
#[command(name = "release")]
Release {
#[command(subcommand)]
subcmd: ReleaseSubCommands,
},
}
pub async fn run() -> Result<CommandExitCode> {
use crate::cli::{Cli, Commands, OutputFormat};
let args: Vec<String> = std::env::args().collect();
let cli = if args.len() > 1 && args[1] == "governor" {
let args_without_governor: Vec<String> = std::iter::once(args[0].clone())
.chain(args.into_iter().skip(2))
.collect();
Cli::parse_from(args_without_governor)
} else {
Cli::parse()
};
let format = cli
.format
.and_then(|f| OutputFormat::from_str(&f))
.unwrap_or(OutputFormat::Json);
let workspace_path = cli.workspace.unwrap_or_else(|| ".".to_string());
match cli.command {
Commands::Owners { subcmd } => handle_owners(subcmd, &workspace_path).await,
Commands::Release { subcmd } => handle_release(subcmd, &workspace_path, format).await,
}
}
async fn handle_owners(
subcmd: OwnersSubCommands,
_workspace_path: &str,
) -> Result<CommandExitCode> {
let config = crate::meta::CargoConfig::from_current_workspace()?;
match subcmd {
OwnersSubCommands::Show { .. } => Ok(crate::commands::owners::show_cmd(&config, &subcmd)),
OwnersSubCommands::Check { .. } => {
crate::commands::owners::check_cmd(&config, &subcmd).await
}
OwnersSubCommands::Sync { .. } => crate::commands::owners::sync_cmd(&config, &subcmd).await,
}
}
async fn handle_release(
subcmd: ReleaseSubCommands,
workspace_path: &str,
format: OutputFormat,
) -> Result<CommandExitCode> {
match subcmd {
ReleaseSubCommands::Analyze(opts) => {
crate::commands::release::analyze::execute(workspace_path, opts, format).await
}
ReleaseSubCommands::Plan(opts) => {
crate::commands::release::plan::execute(workspace_path, opts, format).await
}
ReleaseSubCommands::Bump(opts) => {
crate::commands::release::bump::execute(workspace_path, opts, format).await
}
ReleaseSubCommands::Publish(opts) => {
crate::commands::release::publish::execute(workspace_path, opts, format).await
}
ReleaseSubCommands::Simulate(opts) => {
crate::commands::release::simulate::execute(workspace_path, opts, format).await
}
ReleaseSubCommands::Check(opts) => {
crate::commands::release::check::execute(workspace_path, opts, format)
}
ReleaseSubCommands::Status(opts) => {
crate::commands::release::status::execute(workspace_path, opts, format).await
}
ReleaseSubCommands::Resume(opts) => {
crate::commands::release::resume::execute(workspace_path, opts, format).await
}
}
}