1use crate::Result;
2use crate::command::Command;
3use crate::core::git::{BranchOperations, GitOperations};
4use crate::core::safety::Safety;
5
6pub fn run(dry_run: bool) -> Result<()> {
7 let cmd = CleanBranchesCommand;
8 cmd.execute(dry_run)
9}
10
11pub struct CleanBranchesCommand;
13
14impl Command for CleanBranchesCommand {
15 type Input = bool;
16 type Output = ();
17
18 fn execute(&self, dry_run: bool) -> Result<()> {
19 run_clean_branches(dry_run)
20 }
21
22 fn name(&self) -> &'static str {
23 "clean-branches"
24 }
25
26 fn description(&self) -> &'static str {
27 "Clean up merged branches"
28 }
29
30 fn is_destructive(&self) -> bool {
31 true
32 }
33}
34
35fn run_clean_branches(dry_run: bool) -> Result<()> {
36 if !dry_run {
38 Safety::ensure_clean_working_directory()?;
39 }
40
41 let merged_branches = GitOperations::merged_branches()?;
42 let branches: Vec<String> = merged_branches
43 .into_iter()
44 .filter(|branch| !is_protected_branch(branch))
45 .collect();
46
47 if !dry_run && !branches.is_empty() {
49 let details = format!(
50 "This will delete {} merged branches: {}",
51 branches.len(),
52 branches.join(", ")
53 );
54
55 if !Safety::confirm_destructive_operation("Clean merged branches", &details)? {
56 println!("Operation cancelled by user.");
57 return Ok(());
58 }
59 }
60
61 let mut deleted = Vec::new();
62
63 for branch in branches {
64 if dry_run {
65 deleted.push(branch);
66 } else {
67 match BranchOperations::delete(&branch, false) {
68 Ok(()) => {
69 deleted.push(branch);
70 }
71 Err(_) => {
72 }
74 }
75 }
76 }
77
78 if deleted.is_empty() {
79 println!("No merged branches to delete.");
80 } else {
81 println!("{}", format_deletion_summary(deleted.len(), dry_run));
82 for branch in deleted {
83 if dry_run {
84 let branch1 = &branch;
85 println!("{branch1}");
86 } else {
87 println!(" {branch}");
88 }
89 }
90 }
91
92 Ok(())
93}
94
95fn is_protected_branch(branch: &str) -> bool {
96 ["main", "master", "develop"].contains(&branch)
97}
98
99fn format_deletion_summary(count: usize, dry_run: bool) -> String {
100 if dry_run {
101 format!("🧪 (dry run) {count} branches would be deleted:")
102 } else {
103 format!("🧹 Deleted {count} merged branches:")
104 }
105}