Skip to content

Commit 873c8b2

Browse files
committed
Fix #236, alt link only if necessary
Tests: #65 (test_stale_link_removal) still passes. #236 (test_alt_preserves_user_symlink_until_alt_tracked) lazy touch (test_alt_skips_correct_symlink_without_touching)
1 parent bbb58e6 commit 873c8b2

File tree

2 files changed

+65
-4
lines changed

2 files changed

+65
-4
lines changed

test/test_alt.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

yadm

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -603,12 +603,12 @@ function alt() {
603603
target="$target$suffix"
604604
fi
605605

606-
# Remove target if it's a symlink pointing at source
607-
if [ -L "$target" ] && [ "$target" -ef "$source" ]; then
606+
score_file "$source" "$target" "$conditions"
607+
608+
# Remove target if it's a symlink pointing at source with score 0 (stale)
609+
if [ -L "$target" ] && [ "$target" -ef "$source" ] && [ "$score" -eq 0 ]; then
608610
rm -f "$target"
609611
fi
610-
611-
score_file "$source" "$target" "$conditions"
612612
done
613613

614614
local alt_linked=()
@@ -705,6 +705,12 @@ function alt_linking() {
705705
local source="${alt_sources[$index]}"
706706
local template_processor="${alt_template_processors[$index]}"
707707

708+
if [ -L "$target" ] && [ "$target" -ef "$source" ] && [ "$do_copy" -eq 0 ]; then
709+
$log "Keeping $target; already linked to $source"
710+
exclude+=("${target#"$YADM_WORK"}")
711+
continue
712+
fi
713+
708714
if [ -L "$target" ]; then
709715
rm -f "$target"
710716
elif [ -d "$target" ]; then

0 commit comments

Comments
 (0)