Files
jj-cz/src/cli/mod.rs
T
phundrak e45130d31b feat: implement --new flag
The new `--new` or `-n` flag allows to create a new revision after the
single revision being described. Running `jj-cz --new` is the
equivalent of running `jj-cz @ && jj new`. Running `jj-cz --new xs` is
the equivalent of running `jj-cz xs && jj new xs`.

Passing several revisions to `jj-cz` with the `--new` flag will result
in an error.

Refs: #6
2026-06-14 16:56:07 +02:00

128 lines
3.5 KiB
Rust

use clap::Parser;
/// Interactive conventional commit tool for Jujutsu
///
/// Guides you through creating a properly formatted conventional commit message
/// and applies it to the current change in your Jujutsu repository.
#[derive(Debug, Parser)]
#[command(
name = "jj-cz",
version = concat!(env!("CARGO_PKG_VERSION"), " (jj-lib ", env!("JJ_LIB_VERSION") ,")"),
about = "Interactive conventional commit tool for Jujutsu",
long_about = "Guides you through creating a properly formatted conventional \
commit message and applies it to the current change in your \
Jujutsu repository.\n\n\
This tool requires an interactive terminal (TTY)."
)]
pub struct Cli {
/// The revision(s) whose description to edit (default: @)
#[arg(value_name = "REVSETS")]
revsets: Vec<String>,
/// Create a new child revision after editing the description
#[arg(short, long)]
new: bool,
}
impl Cli {
/// Returns the revsets to operate on, defaulting to `["@"]` if none provided
pub fn revsets(&self) -> Vec<&str> {
if self.revsets.is_empty() {
vec!["@"]
} else {
self.revsets.iter().map(|s| s.as_str()).collect()
}
}
pub fn create_new(&self) -> bool {
self.new
}
pub fn validate(&self) -> Result<(), jj_cz::Error> {
if self.new && self.revsets().len() > 1 {
Err(jj_cz::Error::NewFlagWithMultipleRevisions)
} else {
Ok(())
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use clap::Parser;
#[test]
fn revsets_defaults_to_at() {
let cli = Cli::parse_from(["jj-cz"]);
assert_eq!(cli.revsets(), vec!["@"]);
}
#[test]
fn revsets_returns_provided_values() {
let cli = Cli::parse_from(["jj-cz", "abc", "def"]);
let revsets = cli.revsets();
assert_eq!(revsets, vec!["abc", "def"]);
}
#[test]
fn revsets_single_revset() {
let cli = Cli::parse_from(["jj-cz", "xyz"]);
assert_eq!(cli.revsets(), vec!["xyz"]);
}
#[test]
fn create_new_returns_false_by_default() {
let cli = Cli::parse_from(["jj-cz"]);
assert!(!cli.create_new());
}
#[test]
fn create_new_returns_true_with_flag() {
let cli = Cli::parse_from(["jj-cz", "--new"]);
assert!(cli.create_new());
}
#[test]
fn create_new_returns_true_with_short_flag() {
let cli = Cli::parse_from(["jj-cz", "-n"]);
assert!(cli.create_new());
}
#[test]
fn validate_ok_with_no_args() {
let cli = Cli::parse_from(["jj-cz"]);
assert!(cli.validate().is_ok());
}
#[test]
fn validate_ok_with_new_and_single_revset() {
let cli = Cli::parse_from(["jj-cz", "--new", "@"]);
assert!(cli.validate().is_ok());
}
#[test]
fn validate_ok_with_multiple_revsets_no_new() {
let cli = Cli::parse_from(["jj-cz", "abc", "def"]);
assert!(cli.validate().is_ok());
}
#[test]
fn validate_err_with_new_and_multiple_revsets() {
let cli = Cli::parse_from(["jj-cz", "--new", "abc", "def"]);
let result = cli.validate();
assert!(result.is_err());
assert!(matches!(
result.unwrap_err(),
jj_cz::Error::NewFlagWithMultipleRevisions
));
}
#[test]
fn cli_derives_debug() {
let cli = Cli::parse_from(["jj-cz", "--new", "@"]);
let debug = format!("{:?}", cli);
assert!(debug.contains("Cli"));
}
}