use clap::{Args, Subcommand, ValueEnum};
use serde::Serialize;
use homeboy::version::{
bump_version, bump_version_cwd, read_version, read_version_cwd, set_version, VersionTargetInfo,
};
use super::CmdResult;
#[derive(Args)]
pub struct VersionArgs {
#[command(subcommand)]
command: VersionCommand,
}
#[derive(Subcommand)]
enum VersionCommand {
Show {
#[arg(long)]
cwd: bool,
component_id: Option<String>,
},
Bump {
#[arg(long)]
cwd: bool,
component_id: Option<String>,
bump_type: BumpType,
},
#[command(visible_aliases = ["edit", "merge"])]
Set {
component_id: Option<String>,
new_version: String,
},
}
#[derive(Clone, ValueEnum)]
enum BumpType {
Patch,
Minor,
Major,
}
impl BumpType {
fn as_str(&self) -> &'static str {
match self {
BumpType::Patch => "patch",
BumpType::Minor => "minor",
BumpType::Major => "major",
}
}
}
#[derive(Serialize)]
pub struct VersionShowOutput {
command: String,
component_id: String,
pub version: String,
targets: Vec<VersionTargetInfo>,
}
#[derive(Serialize)]
pub struct VersionBumpOutput {
command: String,
component_id: String,
old_version: String,
new_version: String,
targets: Vec<VersionTargetInfo>,
changelog_path: String,
changelog_finalized: bool,
changelog_changed: bool,
}
#[derive(Serialize)]
pub struct VersionSetOutput {
command: String,
component_id: String,
old_version: String,
new_version: String,
targets: Vec<VersionTargetInfo>,
}
pub fn run(
args: VersionArgs,
_global: &crate::commands::GlobalArgs,
) -> CmdResult<serde_json::Value> {
match args.command {
VersionCommand::Show { cwd, component_id } => {
let (info, component_id_str) = if cwd {
(read_version_cwd()?, "cwd".to_string())
} else {
let info = read_version(component_id.as_deref())?;
let id = component_id.unwrap_or_else(|| "cwd".to_string());
(info, id)
};
let out = VersionShowOutput {
command: "version.show".to_string(),
component_id: component_id_str,
version: info.version,
targets: info.targets,
};
let json = serde_json::to_value(out)
.map_err(|e| homeboy::Error::internal_json(e.to_string(), None))?;
Ok((json, 0))
}
VersionCommand::Bump {
cwd,
component_id,
bump_type,
} => {
let (result, component_id_str) = if cwd {
(bump_version_cwd(bump_type.as_str())?, "cwd".to_string())
} else {
let result = bump_version(component_id.as_deref(), bump_type.as_str())?;
let id = component_id.unwrap_or_else(|| "cwd".to_string());
(result, id)
};
let out = VersionBumpOutput {
command: "version.bump".to_string(),
component_id: component_id_str,
old_version: result.old_version,
new_version: result.new_version,
targets: result.targets,
changelog_path: result.changelog_path,
changelog_finalized: result.changelog_finalized,
changelog_changed: result.changelog_changed,
};
let json = serde_json::to_value(out)
.map_err(|e| homeboy::Error::internal_json(e.to_string(), None))?;
Ok((json, 0))
}
VersionCommand::Set {
component_id,
new_version,
} => {
let result = set_version(component_id.as_deref(), &new_version)?;
let component_id_str = component_id.unwrap_or_else(|| "unknown".to_string());
let out = VersionSetOutput {
command: "version.set".to_string(),
component_id: component_id_str,
old_version: result.old_version,
new_version: result.new_version,
targets: result.targets,
};
let json = serde_json::to_value(out)
.map_err(|e| homeboy::Error::internal_json(e.to_string(), None))?;
Ok((json, 0))
}
}
}
pub fn show_version_output(component_id: &str) -> homeboy::Result<(VersionShowOutput, i32)> {
let info = read_version(Some(component_id))?;
Ok((
VersionShowOutput {
command: "version.show".to_string(),
component_id: component_id.to_string(),
version: info.version,
targets: info.targets,
},
0,
))
}