@@ -5,7 +5,7 @@ use dialoguer::{Confirm, MultiSelect};
55use crate :: adapters:: git:: GitWorktreeManager ;
66use crate :: adapters:: hooks:: { self , HookContext } ;
77use crate :: constants:: { section_header, DEFAULT_MENU_SELECTION , HOOK_PRE_REMOVE } ;
8- use crate :: domain:: worktree:: WorktreeInfo ;
8+ use crate :: domain:: worktree:: { BasicWorktreeInfo , WorktreeInfo } ;
99use crate :: ui:: { DialoguerUI , UserInterface } ;
1010use crate :: utils:: { self , get_theme, press_any_key_to_continue} ;
1111
@@ -71,6 +71,20 @@ pub fn prepare_batch_delete_items(worktrees: &[WorktreeInfo]) -> Vec<String> {
7171 . collect ( )
7272}
7373
74+ /// Pure business logic for filtering deletable worktrees for batch operations.
75+ pub fn get_deletable_worktrees_basic ( worktrees : & [ BasicWorktreeInfo ] ) -> Vec < & BasicWorktreeInfo > {
76+ worktrees. iter ( ) . filter ( |w| !w. is_current ) . collect ( )
77+ }
78+
79+ /// Pure business logic for preparing batch delete labels from lightweight worktrees.
80+ pub fn prepare_batch_delete_items_basic ( worktrees : & [ BasicWorktreeInfo ] ) -> Vec < String > {
81+ worktrees
82+ . iter ( )
83+ . filter ( |w| !w. is_current )
84+ . map ( |w| format ! ( "{} ({})" , w. name, w. branch) )
85+ . collect ( )
86+ }
87+
7488/// Pure business logic for analyzing deletion requirements
7589pub fn analyze_deletion (
7690 worktree : & WorktreeInfo ,
@@ -238,7 +252,7 @@ pub fn batch_delete_worktrees() -> Result<()> {
238252}
239253
240254fn batch_delete_worktrees_internal ( manager : & GitWorktreeManager ) -> Result < ( ) > {
241- let worktrees = manager. list_worktrees ( ) ?;
255+ let worktrees = manager. list_worktrees_basic ( ) ?;
242256
243257 if worktrees. is_empty ( ) {
244258 println ! ( ) ;
@@ -249,8 +263,7 @@ fn batch_delete_worktrees_internal(manager: &GitWorktreeManager) -> Result<()> {
249263 return Ok ( ( ) ) ;
250264 }
251265
252- let deletable_worktrees: Vec < & WorktreeInfo > =
253- worktrees. iter ( ) . filter ( |w| !w. is_current ) . collect ( ) ;
266+ let deletable_worktrees = get_deletable_worktrees_basic ( & worktrees) ;
254267
255268 if deletable_worktrees. is_empty ( ) {
256269 println ! ( ) ;
@@ -270,7 +283,7 @@ fn batch_delete_worktrees_internal(manager: &GitWorktreeManager) -> Result<()> {
270283 println ! ( "{header}" ) ;
271284 println ! ( ) ;
272285
273- let items = prepare_batch_delete_items ( & worktrees) ;
286+ let items = prepare_batch_delete_items_basic ( & worktrees) ;
274287
275288 let selections = MultiSelect :: with_theme ( & get_theme ( ) )
276289 . with_prompt (
@@ -284,7 +297,7 @@ fn batch_delete_worktrees_internal(manager: &GitWorktreeManager) -> Result<()> {
284297 _ => return Ok ( ( ) ) ,
285298 } ;
286299
287- let selected_worktrees: Vec < & WorktreeInfo > =
300+ let selected_worktrees: Vec < & BasicWorktreeInfo > =
288301 selections. iter ( ) . map ( |& i| deletable_worktrees[ i] ) . collect ( ) ;
289302
290303 let mut branches_to_delete = Vec :: new ( ) ;
@@ -573,4 +586,66 @@ mod tests {
573586 assert ! ( items[ 0 ] . contains( "feature/test" ) ) ;
574587 assert ! ( !items[ 0 ] . contains( "main" ) ) ;
575588 }
589+
590+ #[ test]
591+ fn test_prepare_batch_delete_items_basic_preserves_order_and_filters_current ( ) {
592+ let worktrees = vec ! [
593+ BasicWorktreeInfo {
594+ name: "z-current" . to_string( ) ,
595+ git_name: "z-current" . to_string( ) ,
596+ path: std:: path:: PathBuf :: from( "/test/z-current" ) ,
597+ branch: "main" . to_string( ) ,
598+ is_current: true ,
599+ is_locked: false ,
600+ } ,
601+ BasicWorktreeInfo {
602+ name: "alpha" . to_string( ) ,
603+ git_name: "alpha" . to_string( ) ,
604+ path: std:: path:: PathBuf :: from( "/test/alpha" ) ,
605+ branch: "alpha" . to_string( ) ,
606+ is_current: false ,
607+ is_locked: false ,
608+ } ,
609+ BasicWorktreeInfo {
610+ name: "beta-renamed" . to_string( ) ,
611+ git_name: "beta-original" . to_string( ) ,
612+ path: std:: path:: PathBuf :: from( "/test/beta-renamed" ) ,
613+ branch: "beta-branch" . to_string( ) ,
614+ is_current: false ,
615+ is_locked: false ,
616+ } ,
617+ ] ;
618+
619+ let items = prepare_batch_delete_items_basic ( & worktrees) ;
620+
621+ assert_eq ! ( items, vec![ "alpha (alpha)" , "beta-renamed (beta-branch)" ] ) ;
622+ }
623+
624+ #[ test]
625+ fn test_get_deletable_worktrees_basic_preserves_identity_mapping ( ) {
626+ let worktrees = vec ! [
627+ BasicWorktreeInfo {
628+ name: "main" . to_string( ) ,
629+ git_name: "main" . to_string( ) ,
630+ path: std:: path:: PathBuf :: from( "/test/main" ) ,
631+ branch: "main" . to_string( ) ,
632+ is_current: true ,
633+ is_locked: false ,
634+ } ,
635+ BasicWorktreeInfo {
636+ name: "renamed-feature" . to_string( ) ,
637+ git_name: "feature-original" . to_string( ) ,
638+ path: std:: path:: PathBuf :: from( "/test/renamed-feature" ) ,
639+ branch: "feature-branch" . to_string( ) ,
640+ is_current: false ,
641+ is_locked: false ,
642+ } ,
643+ ] ;
644+
645+ let deletable = get_deletable_worktrees_basic ( & worktrees) ;
646+
647+ assert_eq ! ( deletable. len( ) , 1 ) ;
648+ assert_eq ! ( deletable[ 0 ] . name, "renamed-feature" ) ;
649+ assert_eq ! ( deletable[ 0 ] . git_name, "feature-original" ) ;
650+ }
576651}
0 commit comments