@@ -398,9 +398,15 @@ impl<'a> SymlinkHandler<'a> {
398398 return ;
399399 } ;
400400
401- let mut removed_groups = HashSet :: new ( ) ;
401+ let mut removed_files = HashSet :: new ( ) ;
402402 let mut added_files = HashSet :: new ( ) ;
403403
404+ // Context: if a directory is a symlink of a group and then another group tries to symlink to that same directory
405+ // we would end up adding a symlink inside another symlink, borking the user's dotfiles.
406+ // So the solution is to detect that the directory should be shared by multiple groups or even multiple dotfiles profiles,
407+ // If that happens we should remove all the groups that will share those directories, create the shared directories
408+ // and then add everything back in
409+
404410 while let Some ( idx) = dotfiles:: get_highest_priority_target_idx ( & groups) {
405411 let group = & groups[ idx] ;
406412 let group = Dotfile :: try_from ( self . dotfiles_dir . join ( "Configs" ) . join ( group) ) . unwrap ( ) ;
@@ -410,8 +416,8 @@ impl<'a> SymlinkHandler<'a> {
410416
411417 // if there's a symlink in this path, we take its group and put it in the "to be removed" bucket
412418 // it will later be readded so that the groups are all contained in the same parent directory
413- if let Some ( group ) = dotfiles:: get_group_from_target_path ( & f_target) {
414- removed_groups . insert ( group ) ;
419+ if let Some ( dotfile ) = dotfiles:: get_dotfile_from_path ( & f_target) {
420+ removed_files . insert ( dotfile ) ;
415421 }
416422 added_files. insert ( f) ;
417423 }
@@ -429,18 +435,18 @@ impl<'a> SymlinkHandler<'a> {
429435
430436 // NOTE/TODO?: this will only work if the dotfiles are in the same profile context
431437 // maybe we should instead move the files into a temporary and then move them back
432- for group in & removed_groups {
433- self . remove ( dry_run, & group . group_name ) ;
438+ for file in & removed_files {
439+ self . remove ( dry_run, & file . group_name ) ;
434440
435- let target_path = group . to_target_path ( ) . unwrap ( ) ;
436- fs:: create_dir_all ( if group . path . is_file ( ) {
441+ let target_path = file . to_target_path ( ) . unwrap ( ) ;
442+ fs:: create_dir_all ( if file . path . is_file ( ) {
437443 target_path. parent ( ) . unwrap ( )
438444 } else {
439445 & target_path
440446 } )
441- . unwrap ( ) ;
447+ . unwrap ( ) ;
442448
443- let group_iter = Dotfile :: try_from ( group . group_path . clone ( ) )
449+ let group_iter = Dotfile :: try_from ( file . group_path . clone ( ) )
444450 . unwrap ( )
445451 . try_iter ( )
446452 . unwrap ( ) ;
@@ -468,9 +474,7 @@ impl<'a> SymlinkHandler<'a> {
468474 symlink_file ( dry_run, file. path ) ;
469475 }
470476
471- // we do this because otherwise the next time this function is called
472- // the dotfile won't be in the symlink status cache
473- // TODO: find a better way??
477+ // we have to update the cache to reflect the new state
474478 self . symlinked
475479 . insert ( group. into ( ) , group_only_added_files. into_iter ( ) . collect ( ) ) ;
476480 self . not_symlinked . remove ( group) ;
0 commit comments