11use std:: {
22 cell:: { Cell , Ref , RefCell } ,
33 collections:: { BTreeMap , HashMap , VecDeque } ,
4- default,
5- fs,
4+ default, fs,
65 path:: PathBuf ,
76 process:: Command ,
87 rc:: Rc ,
@@ -14,14 +13,8 @@ use serde::{Deserialize, Serialize};
1413
1514use crate :: {
1615 git:: {
17- DEFAULT_REMOTE ,
18- GitTrunk ,
19- after_text,
20- git_branch_exists,
21- git_remote_main,
22- git_sha,
23- git_trunk,
24- is_ancestor,
16+ DEFAULT_REMOTE , GitTrunk , after_text, git_branch_exists, git_remote_main, git_sha,
17+ git_trunk, is_ancestor,
2518 } ,
2619 run_git,
2720} ;
@@ -587,6 +580,78 @@ impl State {
587580 . status ( ) ?;
588581 Ok ( ( ) )
589582 }
583+
584+ /// Try to auto-mount the current branch if it's not in the tree.
585+ /// Returns Ok(true) if the branch was auto-mounted, Ok(false) if it was already in the tree,
586+ /// or Err if auto-mount failed.
587+ pub ( crate ) fn try_auto_mount ( & mut self , repo : & str , branch_name : & str ) -> Result < bool > {
588+ // Check if the branch is already in the tree
589+ if self . branch_exists_in_tree ( repo, branch_name) {
590+ return Ok ( false ) ;
591+ }
592+
593+ // Check if this branch exists in git
594+ if !git_branch_exists ( branch_name) {
595+ bail ! ( "Branch {branch_name} does not exist in git" ) ;
596+ }
597+
598+ // Get the tree for this repo
599+ let Some ( tree) = self . get_tree ( repo) else {
600+ bail ! ( "No tree found for repo {repo}" ) ;
601+ } ;
602+
603+ // Collect all mounted branches
604+ let mut all_branches = Vec :: new ( ) ;
605+ collect_all_branches ( tree, & mut all_branches) ;
606+
607+ // Find all mounted branches that are ancestors of the current branch
608+ let mut ancestor_branches = Vec :: new ( ) ;
609+ for mounted_branch in & all_branches {
610+ if let Ok ( true ) = is_ancestor ( mounted_branch, branch_name) {
611+ ancestor_branches. push ( mounted_branch. clone ( ) ) ;
612+ }
613+ }
614+
615+ // Determine the parent branch
616+ let parent_branch = if ancestor_branches. is_empty ( ) {
617+ // No ancestors found, default to the trunk/main branch
618+ let trunk = git_trunk ( ) ?;
619+ tracing:: info!(
620+ "No mounted ancestor branches found for {}. Defaulting to trunk branch {}." ,
621+ branch_name,
622+ trunk. main_branch
623+ ) ;
624+ trunk. main_branch
625+ } else {
626+ // Find the deepest ancestor branch (highest depth in the tree)
627+ let mut deepest_branch = None ;
628+ let mut max_depth = 0 ;
629+
630+ for ancestor in & ancestor_branches {
631+ if let Some ( depth) = get_branch_depth ( tree, ancestor, 0 )
632+ && depth >= max_depth
633+ {
634+ max_depth = depth;
635+ deepest_branch = Some ( ancestor. clone ( ) ) ;
636+ }
637+ }
638+
639+ deepest_branch
640+ . ok_or_else ( || anyhow ! ( "Failed to determine parent branch for auto-mount" ) ) ?
641+ } ;
642+
643+ tracing:: info!( "Auto-mounting branch {} on {}" , branch_name, parent_branch) ;
644+ println ! (
645+ "Auto-mounting branch {} on {}..." ,
646+ branch_name. yellow( ) ,
647+ parent_branch. yellow( )
648+ ) ;
649+
650+ // Mount the branch
651+ self . mount ( repo, branch_name, Some ( parent_branch) ) ?;
652+
653+ Ok ( true )
654+ }
590655}
591656
592657fn get_path < ' a > ( branch : & ' a Branch , target_branch : & str , path : & mut Vec < & ' a Branch > ) -> bool {
@@ -731,6 +796,27 @@ fn find_stack_with_branch<'a>(
731796 ) )
732797}
733798
799+ /// Collect all branch names from the tree recursively.
800+ fn collect_all_branches ( branch : & Branch , branches : & mut Vec < String > ) {
801+ branches. push ( branch. name . clone ( ) ) ;
802+ for child in & branch. branches {
803+ collect_all_branches ( child, branches) ;
804+ }
805+ }
806+
807+ /// Calculate the depth of a branch in the tree. Returns None if the branch is not found.
808+ fn get_branch_depth ( tree : & Branch , target : & str , current_depth : usize ) -> Option < usize > {
809+ if tree. name == target {
810+ return Some ( current_depth) ;
811+ }
812+ for child in & tree. branches {
813+ if let Some ( depth) = get_branch_depth ( child, target, current_depth + 1 ) {
814+ return Some ( depth) ;
815+ }
816+ }
817+ None
818+ }
819+
734820fn get_xdg_path ( ) -> anyhow:: Result < PathBuf > {
735821 let base_dirs = xdg:: BaseDirectories :: with_prefix ( env ! ( "CARGO_PKG_NAME" ) ) ;
736822 base_dirs
0 commit comments