Skip to content
use clap::{Parser, Subcommand};
use std::error::Error;

mod commands;

#[derive(Parser)]
#[command(
    name = "ino",
    version,
    about = "Tool to create version names, tags and numbers"
)]
struct Cli {
    #[command(subcommand)]
    command: Option<Commands>,
}

#[derive(Subcommand)]
enum Commands {
    /// Output all determined versions
    New,
    /// Print guidance for creating a Dockerfile
    Skill,
    /// Execute a command with versions injected as environment variables
    Exec {
        /// Command to execute
        #[arg(trailing_var_arg = true, allow_hyphen_values = true)]
        command: Vec<String>,
    },
    /// Automatically bump the version from the latest conventional commit and release
    #[command(alias = "release")]
    Auto,
    /// Bump the patch version and release
    Patch,
    /// Bump the minor version and release
    Minor,
    /// Bump the major version and release
    Major,
}

fn main() {
    if let Err(error) = run() {
        eprintln!("ino: {error}");
        std::process::exit(1);
    }
}

fn run() -> Result<(), Box<dyn Error>> {
    let cli = Cli::parse();

    // Running `ino` with no subcommand is the convenient automatic release mode.
    match cli.command.unwrap_or(Commands::Auto) {
        Commands::New => commands::new::run()?,
        Commands::Skill => commands::skill::run()?,
        Commands::Exec { command } => commands::exec::run(&command)?,
        Commands::Auto => commands::release::run(commands::new::Bump::Auto)?,
        Commands::Patch => commands::release::run(commands::new::Bump::Patch)?,
        Commands::Minor => commands::release::run(commands::new::Bump::Minor)?,
        Commands::Major => commands::release::run(commands::new::Bump::Major)?,
    }

    Ok(())
}