use crate::config::CommandOpts;
use clap::{Parser, Subcommand};
use commands::merge::MergeArgs;
use commands::new::NewArgs;
use miette::{Context, Diagnostic, IntoDiagnostic};
use std::path::PathBuf;
use thiserror::Error;
mod commands;
mod config;
mod naming;
mod tinychange;
#[cfg(test)]
mod test;
#[derive(Debug, Parser)]
#[command(
version,
propagate_version = true,
about = "A tool for creating tiny changelogs on a fly!"
)]
pub struct TinyChangeArgs {
#[arg(short = 'I', long)]
non_interactive: bool,
#[arg(short, long)]
config: Option<PathBuf>,
#[command(subcommand)]
command: Option<TinyChangeSubcommand>,
}
#[derive(Debug, Clone, Subcommand)]
enum TinyChangeSubcommand {
New(NewArgs),
Merge(MergeArgs),
Init,
}
#[derive(Debug, Error, Diagnostic)]
#[error("Error: {error}")]
struct ErrorHelp {
#[diagnostic]
error: miette::Error,
#[help]
help: String,
}
pub fn run(args: TinyChangeArgs, command_name: &str) -> miette::Result<()> {
let command = args
.command
.unwrap_or_else(|| TinyChangeSubcommand::New(Default::default()));
let config_path = args
.config
.unwrap_or_else(|| PathBuf::from("tinychange.toml"));
if matches!(command, TinyChangeSubcommand::Init) {
return commands::init::run(config_path, command_name);
}
let config = fs_err::read_to_string(&config_path)
.into_diagnostic()
.map_err(|e| ErrorHelp {
error: e,
help: format!(
"Run `{} init` to initialize tinychange in your project",
command_name
),
})?;
let config = toml::from_str(&config)
.into_diagnostic()
.context("Failed to read configuration file")?;
let workdir = std::env::current_dir().into_diagnostic()?;
let config_folder = config_path
.parent()
.map(|p| p.to_owned())
.unwrap_or_else(|| workdir.clone());
let opts = CommandOpts::new(
args.non_interactive,
!args.non_interactive,
config_folder,
workdir,
command_name.to_owned(),
config,
)?;
match command {
TinyChangeSubcommand::New(cmd) => cmd.run(opts),
TinyChangeSubcommand::Merge(cmd) => cmd.run(opts),
TinyChangeSubcommand::Init => unreachable!("Handled above"),
}
}