mod cli;
use clap::Parser as _;
use jj_cz::{CommitWorkflow, Error, JjLib};
use std::process;
const EXIT_SUCCESS: i32 = 0;
const EXIT_CANCELLED: i32 = 130; const EXIT_ERROR: i32 = 1;
fn error_to_exit_code(error: Error) -> i32 {
match error {
Error::Cancelled => EXIT_CANCELLED,
Error::NotARepository => EXIT_ERROR,
Error::RepositoryLocked => EXIT_ERROR,
Error::JjOperation { .. } => EXIT_ERROR,
Error::InvalidScope(_) => EXIT_ERROR,
Error::InvalidDescription(_) => EXIT_ERROR,
Error::InvalidCommitMessage(_) => EXIT_ERROR,
Error::NonInteractive => EXIT_ERROR,
Error::FailedGettingCurrentDir => EXIT_ERROR,
Error::FailedReadingConfig { .. } => EXIT_ERROR,
Error::RevsetResolutionError { .. } => EXIT_ERROR,
Error::MultipleRevisions { .. } => EXIT_ERROR,
Error::NewFlagWithMultipleRevisions => EXIT_ERROR,
}
}
fn is_interactive_terminal() -> bool {
use std::io::IsTerminal;
std::io::stdin().is_terminal() && std::io::stdout().is_terminal()
}
#[tokio::main]
async fn main() -> Result<(), ()> {
let cli = cli::Cli::parse();
cli.validate().map_err(exit_on_error)?;
if !is_interactive_terminal() {
eprintln!("❌ Error: jj-cz requires an interactive terminal (TTY)");
eprintln!(" This tool cannot be used in non-interactive mode or when piping input.");
eprintln!(" Use --help for usage information.");
process::exit(EXIT_ERROR);
}
let executor = JjLib::new().await.map_err(exit_on_error)?;
let workflow = CommitWorkflow::new(executor);
for revset in cli.revsets() {
let result = workflow.run_for_revset(revset).await;
handle_result(result);
if cli.create_new() {
println!("Creating a new revision after {revset}");
workflow.new_revision(revset).await.map_err(exit_on_error)?;
}
}
fn handle_result(result: Result<(), Error>) {
match result {
Ok(()) => println!("✅ Commit message applied successfully!"),
Err(Error::Cancelled) => {
println!("🟡 Operation cancelled by user.");
process::exit(EXIT_CANCELLED);
}
Err(e) => exit_on_error(e),
}
}
process::exit(EXIT_SUCCESS);
}
fn exit_on_error(e: Error) {
eprintln!("❌ Error: {}", e);
process::exit(error_to_exit_code(e));
}