@@ -442,3 +442,58 @@ def setup_standard_yadm_dir(paths):
442442 std_yadm_data .join ("repo.git" ).mksymlinkto (paths .repo , absolute = 1 )
443443 std_yadm_dir .join ("encrypt" ).mksymlinkto (paths .encrypt , absolute = 1 )
444444 return std_yadm_dir , std_yadm_data
445+
446+
447+ @pytest .mark .usefixtures ("ds1_copy" )
448+ def test_alt_preserves_user_symlink_until_alt_tracked (runner , paths ):
449+ """yadm alt should preserve user-created symlinks when no alternate is tracked,
450+ but replaces them once the alternate is added to the repository."""
451+ yadm_dir , yadm_data = setup_standard_yadm_dir (paths )
452+ # Create a user symlink (not managed by yadm)
453+ user_target = paths .work .join ("user_target" )
454+ user_target .write ("user-data" )
455+ link_file = paths .work .join (utils .ALT_FILE1 )
456+ link_file .mksymlinkto (user_target )
457+ assert link_file .islink ()
458+ # Create a yadm alt file, but do not add it yet
459+ alt_file = yadm_dir .join ("alt" ).join (f"{ utils .ALT_FILE1 } ##default" )
460+ alt_file .write ("alt-data" , ensure = True )
461+ # Run yadm alt (should not replace user symlink)
462+ run = runner ([paths .pgm , "-Y" , yadm_dir , "--yadm-data" , yadm_data , "alt" ])
463+ assert run .success
464+ # The symlink should still point to user_target
465+ assert link_file .islink ()
466+ assert os .path .realpath (str (link_file )) == str (user_target )
467+ # Now add the alt file and run yadm alt again
468+ run = runner ([paths .pgm , "-Y" , yadm_dir , "--yadm-data" , yadm_data , "add" , alt_file ])
469+ assert run .success
470+ run = runner ([paths .pgm , "-Y" , yadm_dir , "--yadm-data" , yadm_data , "alt" ])
471+ assert run .success
472+ # Now the symlink should be replaced and point to the alt file
473+ assert link_file .islink ()
474+ assert os .path .realpath (str (link_file )) == str (alt_file )
475+
476+
477+ @pytest .mark .usefixtures ("ds1_copy" )
478+ def test_alt_skips_correct_symlink_without_touching (runner , paths ):
479+ """yadm alt should skip already-correct symlinks without any filesystem operations (no remove/recreate)."""
480+ yadm_dir , yadm_data = setup_standard_yadm_dir (paths )
481+ # Create and add a yadm alt file
482+ alt_file = yadm_dir .join ("alt" ).join (f"{ utils .ALT_FILE1 } ##default" )
483+ alt_file .write ("alt-data" , ensure = True )
484+ run = runner ([paths .pgm , "-Y" , yadm_dir , "--yadm-data" , yadm_data , "add" , alt_file ])
485+ assert run .success
486+ # Run yadm alt to create the symlink
487+ run = runner ([paths .pgm , "-Y" , yadm_dir , "--yadm-data" , yadm_data , "alt" ])
488+ assert run .success
489+ link_file = paths .work .join (utils .ALT_FILE1 )
490+ assert link_file .islink ()
491+ assert os .path .realpath (str (link_file )) == str (alt_file )
492+ # Get the symlink's mtime
493+ mtime_before = link_file .lstat ().mtime
494+ # Run yadm alt again (should not touch the symlink)
495+ run = runner ([paths .pgm , "-Y" , yadm_dir , "--yadm-data" , yadm_data , "alt" ])
496+ assert run .success
497+ mtime_after = link_file .lstat ().mtime
498+ # The mtime should not change
499+ assert mtime_before == mtime_after
0 commit comments