#[derive(clap::Parser)]
#[command(about, author, version)]
#[command(
color = concolor_clap::color_choice(),
)]
#[command(group = clap::ArgGroup::new("mode").multiple(false))]
#[command(args_conflicts_with_subcommands = true)]
pub struct Args {
#[arg(short, long, group = "mode")]
pub rebase: bool,
#[arg(long)]
pub pull: bool,
#[arg(long)]
pub push: bool,
#[arg(short, long, value_enum)]
pub stack: Option<git_stack::legacy::config::Stack>,
#[arg(long)]
pub base: Option<String>,
#[arg(long)]
pub onto: Option<String>,
#[arg(long, value_enum)]
pub fixup: Option<git_stack::legacy::config::Fixup>,
#[arg(long, overrides_with("no_repair"))]
repair: bool,
#[arg(long, overrides_with("repair"), hide = true)]
no_repair: bool,
#[arg(short = 'n', long)]
pub dry_run: bool,
#[arg(long, value_enum)]
pub format: Option<git_stack::legacy::config::Format>,
#[arg(long, value_enum)]
pub show_commits: Option<git_stack::legacy::config::ShowCommits>,
#[arg(long, group = "mode")]
pub protected: bool,
#[arg(long, group = "mode")]
pub protect: Option<String>,
#[arg(short = 'C', hide = true, value_name = "PATH")]
pub current_dir: Option<Vec<std::path::PathBuf>>,
#[arg(long, group = "mode")]
pub dump_config: Option<std::path::PathBuf>,
#[command(flatten)]
pub(crate) color: concolor_clap::Color,
#[command(flatten)]
pub verbose: clap_verbosity_flag::Verbosity<clap_verbosity_flag::InfoLevel>,
#[command(subcommand)]
command: Option<Command>,
}
#[derive(clap::Subcommand)]
pub enum Command {
#[command(alias = "prev")]
Previous(crate::prev::PrevArgs),
Next(crate::next::NextArgs),
Reword(crate::reword::RewordArgs),
Amend(crate::amend::AmendArgs),
Sync(crate::sync::SyncArgs),
Run(crate::run::RunArgs),
Alias(crate::alias::AliasArgs),
}
impl Args {
pub fn exec(&self, colored_stdout: bool, colored_stderr: bool) -> proc_exit::ExitResult {
match &self.command {
Some(Command::Previous(c)) => c.exec(colored_stdout, colored_stderr),
Some(Command::Next(c)) => c.exec(colored_stdout, colored_stderr),
Some(Command::Reword(c)) => c.exec(colored_stdout, colored_stderr),
Some(Command::Amend(c)) => c.exec(colored_stdout, colored_stderr),
Some(Command::Sync(c)) => c.exec(colored_stdout, colored_stderr),
Some(Command::Run(c)) => c.exec(colored_stdout, colored_stderr),
Some(Command::Alias(c)) => c.exec(colored_stdout, colored_stderr),
None => {
if let Some(output_path) = self.dump_config.as_deref() {
crate::config::dump_config(self, output_path)
} else if let Some(ignore) = self.protect.as_deref() {
crate::config::protect(self, ignore)
} else if self.protected {
crate::config::protected(self)
} else {
crate::stack::stack(self, colored_stdout, colored_stderr)
}
}
}
}
pub fn to_config(&self) -> git_stack::legacy::config::RepoConfig {
git_stack::legacy::config::RepoConfig {
protected_branches: None,
protect_commit_count: None,
protect_commit_age: None,
auto_base_commit_count: None,
stack: self.stack,
push_remote: None,
pull_remote: None,
show_format: self.format,
show_commits: self.show_commits,
show_stacked: None,
auto_fixup: None,
auto_repair: None,
capacity: None,
}
}
pub fn repair(&self) -> Option<bool> {
resolve_bool_arg(self.repair, self.no_repair)
}
}
fn resolve_bool_arg(yes: bool, no: bool) -> Option<bool> {
match (yes, no) {
(true, false) => Some(true),
(false, true) => Some(false),
(false, false) => None,
(_, _) => unreachable!("clap should make this impossible"),
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn verify_app() {
use clap::CommandFactory;
Args::command().debug_assert()
}
}