mod add;
mod init;
mod manage;
mod release;
mod status;
mod verify;
use std::path::Path;
use changeset_core::{BumpType, ChangeCategory};
use changeset_manifest::{ChangelogLocation, ComparisonLinks, TagFormat, ZeroVersionBehavior};
use clap::{Args, Subcommand, ValueEnum};
use crate::error::Result;
#[derive(Subcommand)]
pub(crate) enum Commands {
Add(AddArgs),
Verify(VerifyArgs),
Status,
#[command(
verbatim_doc_comment,
after_long_help = "\
Pre-release workflow:
1. cargo changeset release --prerelease alpha → All packages get alpha tag
2. cargo changeset release --prerelease foo:alpha → Only foo gets alpha tag
3. cargo changeset release → Graduates prereleases to stable
Graduation (0.x to 1.0.0):
- cargo changeset release --graduate foo --graduate bar
- Or configure in .changeset/graduation.toml
Per-package configuration can also be set via:
- .changeset/pre-release.toml
- .changeset/graduation.toml
Use 'cargo changeset manage' to configure these files."
)]
Release(ReleaseArgs),
Init(InitArgs),
Manage(ManageArgs),
}
#[derive(Args)]
pub(crate) struct InitArgs {
#[arg(long)]
pub defaults: bool,
#[arg(long)]
pub no_interactive: bool,
#[arg(long)]
pub commit: Option<bool>,
#[arg(long)]
pub tags: Option<bool>,
#[arg(long)]
pub keep_changesets: Option<bool>,
#[arg(long, value_name = "FORMAT")]
pub tag_format: Option<TagFormatArg>,
#[arg(long, value_name = "LOCATION")]
pub changelog: Option<ChangelogLocationArg>,
#[arg(long, value_name = "MODE")]
pub comparison_links: Option<ComparisonLinksArg>,
#[arg(long, value_name = "BEHAVIOR")]
pub zero_version_behavior: Option<ZeroVersionBehaviorArg>,
}
#[derive(Clone, Copy, ValueEnum)]
pub(crate) enum TagFormatArg {
VersionOnly,
CratePrefixed,
}
impl From<TagFormatArg> for TagFormat {
fn from(arg: TagFormatArg) -> Self {
match arg {
TagFormatArg::VersionOnly => Self::VersionOnly,
TagFormatArg::CratePrefixed => Self::CratePrefixed,
}
}
}
#[derive(Clone, Copy, ValueEnum)]
pub(crate) enum ChangelogLocationArg {
Root,
PerPackage,
}
impl From<ChangelogLocationArg> for ChangelogLocation {
fn from(arg: ChangelogLocationArg) -> Self {
match arg {
ChangelogLocationArg::Root => Self::Root,
ChangelogLocationArg::PerPackage => Self::PerPackage,
}
}
}
#[derive(Clone, Copy, ValueEnum)]
pub(crate) enum ComparisonLinksArg {
Auto,
Enabled,
Disabled,
}
impl From<ComparisonLinksArg> for ComparisonLinks {
fn from(arg: ComparisonLinksArg) -> Self {
match arg {
ComparisonLinksArg::Auto => Self::Auto,
ComparisonLinksArg::Enabled => Self::Enabled,
ComparisonLinksArg::Disabled => Self::Disabled,
}
}
}
#[derive(Clone, Copy, ValueEnum)]
pub(crate) enum ZeroVersionBehaviorArg {
EffectiveMinor,
AutoPromoteOnMajor,
}
impl From<ZeroVersionBehaviorArg> for ZeroVersionBehavior {
fn from(arg: ZeroVersionBehaviorArg) -> Self {
match arg {
ZeroVersionBehaviorArg::EffectiveMinor => Self::EffectiveMinor,
ZeroVersionBehaviorArg::AutoPromoteOnMajor => Self::AutoPromoteOnMajor,
}
}
}
#[derive(Args)]
pub(crate) struct AddArgs {
#[arg(long = "package", short = 'p', value_name = "NAME")]
pub packages: Vec<String>,
#[arg(long, short = 'b', value_enum)]
pub bump: Option<BumpType>,
#[arg(long = "package-bump", value_name = "NAME:TYPE")]
pub package_bumps: Vec<String>,
#[arg(long, short = 'c', value_enum, default_value = "changed")]
pub category: ChangeCategory,
#[arg(long, short = 'm')]
pub message: Option<String>,
#[arg(long)]
pub editor: bool,
}
#[derive(Args)]
pub(crate) struct VerifyArgs {
#[arg(long, default_value = "main")]
pub base: String,
#[arg(long)]
pub head: Option<String>,
#[arg(long, short = 'q')]
pub quiet: bool,
#[arg(long, short = 'd')]
pub allow_deleted_changesets: bool,
}
#[derive(Args)]
pub(crate) struct ReleaseArgs {
#[arg(long)]
pub dry_run: bool,
#[arg(long)]
pub convert: bool,
#[arg(long)]
pub no_commit: bool,
#[arg(long)]
pub no_tags: bool,
#[arg(long)]
pub keep_changesets: bool,
#[arg(long, value_name = "CRATE:TAG", num_args = 0..=1, default_missing_value = "")]
pub prerelease: Vec<String>,
#[arg(long, short = 'f')]
pub force: bool,
#[arg(long, value_name = "CRATE", num_args = 0..=1, default_missing_value = "")]
pub graduate: Vec<String>,
}
#[derive(Args)]
pub(crate) struct ManageArgs {
#[command(subcommand)]
pub command: ManageCommand,
}
#[derive(Subcommand)]
pub(crate) enum ManageCommand {
#[command(name = "pre-release")]
Prerelease(ManagePrereleaseArgs),
Graduation(ManageGraduationArgs),
}
#[derive(Args)]
pub(crate) struct ManagePrereleaseArgs {
#[arg(long, value_name = "CRATE:TAG")]
pub add: Vec<String>,
#[arg(long, value_name = "CRATE")]
pub remove: Vec<String>,
#[arg(long, value_name = "CRATE")]
pub graduate: Vec<String>,
#[arg(long, short)]
pub list: bool,
}
#[derive(Args)]
pub(crate) struct ManageGraduationArgs {
#[arg(long, value_name = "CRATE")]
pub add: Vec<String>,
#[arg(long, value_name = "CRATE")]
pub remove: Vec<String>,
#[arg(long, short)]
pub list: bool,
}
pub(crate) struct ExecuteResult {
pub quiet: bool,
}
impl Commands {
pub(crate) fn execute(self, start_path: &Path) -> (Result<()>, ExecuteResult) {
match self {
Self::Add(args) => (add::run(args, start_path), ExecuteResult { quiet: false }),
Self::Verify(args) => {
let quiet = args.quiet;
(verify::run(args, start_path), ExecuteResult { quiet })
}
Self::Status => (status::run(start_path), ExecuteResult { quiet: false }),
Self::Release(args) => (
release::run(args, start_path),
ExecuteResult { quiet: false },
),
Self::Init(args) => (init::run(args, start_path), ExecuteResult { quiet: false }),
Self::Manage(args) => (
manage::run(args, start_path),
ExecuteResult { quiet: false },
),
}
}
}