pub mod changelog; pub mod commit; pub mod config; pub mod credential; pub mod ginit; pub mod init; pub mod profile; pub mod tag; use anyhow::{Result, bail}; use dialoguer::{Confirm, MultiSelect}; use crate::git::GitRepo; use crate::i18n::Messages; use crate::utils::{print_progress, print_success, print_warning}; /// Shared push flow for commit and tag: resolve the push target, honor the /// `--yes` > `--select-remote` > `--push` priority chain, then push to the /// chosen target(s). `progress_msg`/`success_msg` render the per-remote /// status lines; `refspec` is "HEAD" for commit, the tag ref for tag. pub(crate) fn run_push_flow( repo: &GitRepo, requested_remote: &str, select_remote: bool, push: bool, yes: bool, messages: &Messages, confirm_prompt: &str, refspec: &str, progress_msg: impl Fn(&str) -> String, success_msg: impl Fn(&str) -> String, ) -> Result<()> { let Some((target, fell_back)) = repo.resolve_push_target(requested_remote)? else { print_warning(&messages.push_skipped_no_remote()); return Ok(()); }; if fell_back && (push || !yes) { print_warning(&messages.push_target_fallback(requested_remote, &target)); } let remotes = if select_remote && !yes { Some(repo.list_remotes()?) } else { None }; let use_multi_select = remotes.as_ref().is_some_and(|r| r.len() > 1); let targets: Vec = if use_multi_select { let remotes = remotes.unwrap(); let items: Vec<(&String, bool)> = remotes.iter().map(|r| (r, *r == target)).collect(); let selected = MultiSelect::new() .with_prompt(messages.select_push_remotes()) .items_checked(&items) .interact()?; if selected.is_empty() { print_warning(&messages.no_remotes_selected()); return Ok(()); } selected.iter().map(|&i| remotes[i].clone()).collect() } else if push { vec![target] } else if !yes { if Confirm::new() .with_prompt(confirm_prompt) .default(false) .interact()? { vec![target] } else { Vec::new() } } else { Vec::new() }; if targets.len() == 1 { print_progress(&progress_msg(&targets[0])); repo.push(&targets[0], refspec)?; print_success(&success_msg(&targets[0])); } else if targets.len() > 1 { let fmt_list = |items: &[String]| { if items.is_empty() { "-".to_string() } else { items.join(", ") } }; for (i, remote_name) in targets.iter().enumerate() { print_progress(&progress_msg(remote_name)); if let Err(e) = repo.push(remote_name, refspec) { bail!( "{}\n{}", messages.push_multi_failed( remote_name, &fmt_list(&targets[..i]), &fmt_list(&targets[i + 1..]) ), e ); } print_success(&success_msg(remote_name)); } } Ok(()) }