use crate::fleet::error::{Result, SuperGitError};
use crate::fleet::git::{GitOps, SubmoduleOps, SubmoduleTree};
use crate::fleet::output::Formatter;
use crate::prelude::*;
use dialoguer::Confirm;
pub fn execute<P: AsRef<Path>>(
repo_root: P,
branch: &str,
remote: bool,
force: bool,
dry_run: bool,
verbose: bool,
) -> Result<()> {
let tree = SubmoduleTree::discover(&repo_root)?;
Formatter::print_info(&format!(
"Deleting branch '{}' from superproject + {} submodule(s){}",
branch,
tree.len(),
if remote { " (including remote)" } else { "" }
));
if dry_run {
Formatter::print_warning("DRY RUN: No changes will be made");
}
if remote && !dry_run {
let confirmed = Confirm::new()
.with_prompt(format!(
"Are you sure you want to delete '{}' from remote?",
branch
))
.default(false)
.interact()
.unwrap_or(false);
if !confirmed {
return Err(SuperGitError::Cancelled);
}
}
let mut successful = 0;
let mut failed = 0;
let mut skipped = 0;
for node in tree.top_down() {
if verbose {
Formatter::print_submodule_header(node.label());
}
if !node.initialized {
Formatter::print_warning(&format!(
"Submodule '{}' not initialized, skipping",
node.label()
));
skipped += 1;
continue;
}
let repo = match GitOps::open_repo(&node.abs_path) {
Ok(r) => r,
Err(e) => {
Formatter::print_error(&format!("Failed to open '{}': {}", node.label(), e));
failed += 1;
continue;
}
};
let is_detached = match GitOps::is_detached_head(&repo) {
Ok(value) => value,
Err(e) => {
Formatter::print_error(&format!(
"Failed to check HEAD state of '{}': {}",
node.label(),
e
));
failed += 1;
continue;
}
};
if !is_detached {
let current_branch = match GitOps::current_branch(&repo) {
Ok(value) => value,
Err(e) => {
Formatter::print_error(&format!(
"Failed to determine current branch of '{}': {}",
node.label(),
e
));
failed += 1;
continue;
}
};
if current_branch == branch {
Formatter::print_error(&format!(
"Cannot delete '{}' in '{}': currently checked out. Switch to another branch first.",
branch,
node.label()
));
failed += 1;
continue;
}
}
let branch_exists = match GitOps::branch_exists(&repo, branch) {
Ok(exists) => exists,
Err(e) => {
Formatter::print_error(&format!(
"Failed to check branch in '{}': {}",
node.label(),
e
));
failed += 1;
continue;
}
};
if !branch_exists {
Formatter::print_warning(&format!(
"Branch '{}' does not exist in '{}', skipping",
branch,
node.label()
));
skipped += 1;
continue;
}
if dry_run {
Formatter::print_info(&format!("Would delete branch '{}'", branch));
if remote {
Formatter::print_info(&format!("Would delete remote branch '{}'", branch));
}
successful += 1;
continue;
}
match SubmoduleOps::delete_branch(node, branch, force) {
Ok(_) => {
Formatter::print_success(&format!(
"Deleted branch '{}' in '{}'",
branch,
node.label()
));
successful += 1;
if remote {
match SubmoduleOps::delete_remote_branch(node, branch) {
Ok(_) => {
Formatter::print_success(&format!(
"Deleted remote branch '{}' in '{}'",
branch,
node.label()
));
}
Err(e) => {
Formatter::print_error(&format!(
"Failed to delete remote branch '{}' in '{}': {}",
branch,
node.label(),
e
));
failed += 1;
}
}
}
}
Err(e) => {
Formatter::print_error(&format!(
"Failed to delete branch '{}' in '{}': {}",
branch,
node.label(),
e
));
failed += 1;
}
}
}
if !dry_run {
Formatter::print_summary(successful, failed, skipped);
}
if failed > 0 {
return Err(SuperGitError::Other(format!(
"{} submodule(s) failed to delete branch",
failed
)));
}
Ok(())
}