#![cfg(feature = "native")]
use crate::ansi_colors::Colorize;
use crate::stack;
use std::path::PathBuf;
#[path = "stack_check.rs"]
mod check;
#[path = "stack_drift.rs"]
mod drift;
#[path = "stack_status.rs"]
mod status;
#[path = "stack_versions.rs"]
mod versions;
use check::{cmd_stack_check, cmd_stack_release};
use drift::{cmd_stack_comply, cmd_stack_drift, extract_minor_version};
use status::{cmd_stack_gate, cmd_stack_quality, cmd_stack_status, cmd_stack_sync, cmd_stack_tree};
use versions::{cmd_stack_publish_status, cmd_stack_versions, format_downloads};
#[derive(Debug, Clone, Copy, Default, clap::ValueEnum)]
pub enum StackOutputFormat {
#[default]
Text,
Json,
Markdown,
}
#[derive(Debug, Clone, Copy, clap::ValueEnum)]
pub enum BumpType {
Patch,
Minor,
Major,
}
#[derive(Debug, Clone, clap::Subcommand)]
pub enum StackCommand {
Check {
#[arg(long)]
project: Option<String>,
#[arg(long, value_enum, default_value = "text")]
format: StackOutputFormat,
#[arg(long)]
strict: bool,
#[arg(long)]
verify_published: bool,
#[arg(long)]
offline: bool,
#[arg(long)]
workspace: Option<PathBuf>,
},
Release {
crate_name: Option<String>,
#[arg(long)]
all: bool,
#[arg(long)]
dry_run: bool,
#[arg(long, value_enum)]
bump: Option<BumpType>,
#[arg(long)]
no_verify: bool,
#[arg(long, short)]
yes: bool,
#[arg(long)]
publish: bool,
},
Status {
#[arg(long)]
simple: bool,
#[arg(long, value_enum, default_value = "text")]
format: StackOutputFormat,
#[arg(long)]
tree: bool,
},
Sync {
crate_name: Option<String>,
#[arg(long)]
all: bool,
#[arg(long)]
dry_run: bool,
#[arg(long)]
align: Option<String>,
},
Tree {
#[arg(long, default_value = "ascii")]
format: String,
#[arg(long)]
health: bool,
#[arg(long)]
filter: Option<String>,
},
Quality {
#[arg(long)]
component: Option<String>,
#[arg(long)]
strict: bool,
#[arg(long, value_enum, default_value = "text")]
format: StackOutputFormat,
#[arg(long)]
verify_hero: bool,
#[arg(long, short)]
verbose: bool,
#[arg(long)]
workspace: Option<PathBuf>,
},
Gate {
#[arg(long)]
workspace: Option<PathBuf>,
#[arg(long, short)]
quiet: bool,
},
Versions {
#[arg(long)]
outdated: bool,
#[arg(long, value_enum, default_value = "text")]
format: StackOutputFormat,
#[arg(long)]
offline: bool,
#[arg(long)]
include_prerelease: bool,
},
PublishStatus {
#[arg(long, value_enum, default_value = "text")]
format: StackOutputFormat,
#[arg(long)]
workspace: Option<PathBuf>,
#[arg(long)]
clear_cache: bool,
},
Drift {
#[arg(long, value_enum, default_value = "text")]
format: StackOutputFormat,
#[arg(long)]
fix: bool,
#[arg(long)]
workspace: Option<PathBuf>,
},
Comply {
#[arg(long)]
rule: Option<String>,
#[arg(long)]
fix: bool,
#[arg(long)]
dry_run: bool,
#[arg(long, value_enum, default_value = "text")]
format: ComplyOutputFormat,
#[arg(long)]
workspace: Option<PathBuf>,
#[arg(long)]
list_rules: bool,
},
}
#[derive(Debug, Clone, Copy, Default, clap::ValueEnum)]
pub enum ComplyOutputFormat {
#[default]
Text,
Json,
Markdown,
Html,
}
fn dispatch_stack_info(command: StackCommand) -> anyhow::Result<()> {
match command {
StackCommand::Check { project, format, strict, verify_published, offline, workspace } => {
cmd_stack_check(project, format, strict, verify_published, offline, workspace)
}
StackCommand::Status { simple, format, tree } => cmd_stack_status(simple, format, tree),
StackCommand::Tree { format, health, filter } => {
cmd_stack_tree(&format, health, filter.as_deref())
}
StackCommand::Versions { outdated, format, offline, include_prerelease } => {
cmd_stack_versions(outdated, format, offline, include_prerelease)
}
_ => unreachable!(),
}
}
fn dispatch_stack_action(command: StackCommand) -> anyhow::Result<()> {
match command {
StackCommand::Release { crate_name, all, dry_run, bump, no_verify, yes, publish } => {
cmd_stack_release(crate_name, all, dry_run, bump, no_verify, yes, publish)
}
StackCommand::Sync { crate_name, all, dry_run, align } => {
cmd_stack_sync(crate_name, all, dry_run, align)
}
StackCommand::Quality { component, strict, format, workspace, .. } => {
cmd_stack_quality(component, strict, format, workspace)
}
StackCommand::Gate { workspace, quiet } => cmd_stack_gate(workspace, quiet),
StackCommand::PublishStatus { format, workspace, clear_cache } => {
cmd_stack_publish_status(format, workspace, clear_cache)
}
StackCommand::Drift { format, fix, workspace } => cmd_stack_drift(format, fix, workspace),
StackCommand::Comply { rule, fix, dry_run, format, workspace, list_rules } => {
cmd_stack_comply(rule, fix, dry_run, format, workspace, list_rules)
}
StackCommand::Check { .. }
| StackCommand::Status { .. }
| StackCommand::Tree { .. }
| StackCommand::Versions { .. } => unreachable!(),
}
}
pub fn cmd_stack(command: StackCommand) -> anyhow::Result<()> {
match &command {
StackCommand::Check { .. }
| StackCommand::Status { .. }
| StackCommand::Tree { .. }
| StackCommand::Versions { .. } => dispatch_stack_info(command),
_ => dispatch_stack_action(command),
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_extract_minor_version_simple() {
assert_eq!(extract_minor_version("0.10.1"), "0.10");
assert_eq!(extract_minor_version("1.2.3"), "1.2");
}
#[test]
fn test_extract_minor_version_with_prefix() {
assert_eq!(extract_minor_version("^0.10"), "0.10");
assert_eq!(extract_minor_version("~1.2"), "1.2");
assert_eq!(extract_minor_version("=2.0.0"), "2.0");
}
#[test]
fn test_format_downloads() {
assert_eq!(format_downloads(500), "500");
assert_eq!(format_downloads(1500), "1.5K");
assert_eq!(format_downloads(1_500_000), "1.5M");
}
}