#!/usr/bin/perl -w use strict; use Test::More tests => 54; use SVK::Test; use SVK::Util qw( HAS_SYMLINK is_symlink); our $output; my ($xd, $svk) = build_test(); my ($copath, $corpath) = get_copath ('symlink'); my @symlinks; sub _symlink { my ($from, $to) = @_; push @symlinks, $to; return symlink($from => $to) if HAS_SYMLINK; overwrite_file ($to, "link $from"); } sub _fix_symlinks { $svk->ps('svn:special' => '*', @symlinks) if !HAS_SYMLINK && @symlinks; @symlinks = (); } sub _check_symlinks1 { unless (HAS_SYMLINK) { ok(1); ok(1); return; } # doesn't work on a single target is_output ($svk, 'pg', ['svn:special', @_], [map { "$_ - *" } @_], 'got svn:special'); return 1; } sub _check_symlinks2 { for (@_) { ok (0, "$_ is symlink"), return if HAS_SYMLINK and !is_symlink ($_); } ok (1, 'paths are symlinks'); } sub _check_symlinks { my (@params) = @_; return unless _check_symlinks1(@params); _check_symlinks2(@params); } $svk->checkout ('//', $copath); mkdir ("$copath/A"); overwrite_file ("$copath/A/bar", "foobar\n"); _symlink ("bar", "$copath/A/bar.lnk"); _symlink ('/tmp', "$copath/A/dir.lnk"); is_output ($svk, 'add', ["$copath/A"], [__"A $copath/A", __"A $copath/A/bar", __"A $copath/A/bar.lnk", __"A $copath/A/dir.lnk"], 'add symlinks'); _symlink ('/non-exists', "$copath/A/non.lnk"); is_output ($svk, 'add', ["$copath/A/non.lnk"], [__("A $copath/A/non.lnk")], 'dangling symlink'); is_output ($svk, 'rm', ["$copath/A/non.lnk"], [__("$copath/A/non.lnk is scheduled; use '--force' to go ahead.")]); is_output ($svk, 'rm', ["$copath/A/bar.lnk"], [__("$copath/A/bar.lnk is scheduled; use '--force' to go ahead.")]); is_output ($svk, 'status', ["$copath/A"], [__"A $copath/A", __"A $copath/A/bar", __"A $copath/A/bar.lnk", __"A $copath/A/dir.lnk", __"A $copath/A/non.lnk"], 'status added symlinks'); my @allsymlinks = @symlinks; _fix_symlinks(); _check_symlinks (@allsymlinks); $svk->commit ('-m', 'init', $copath); rmtree [$copath]; is_output ($svk, 'checkout', ['//', $copath], ["Syncing //(/) in $corpath to 1.", __"A $copath/A", __"A $copath/A/dir.lnk", __"A $copath/A/bar", __"A $copath/A/bar.lnk", __"A $copath/A/non.lnk"], 'checkout symlinks'); is_output ($svk, 'status', [$copath], [], 'unmodified status'); _check_symlinks (@allsymlinks); unlink ("$copath/A/dir.lnk"); _symlink ('.', "$copath/A/dir.lnk"); is_output ($svk, 'status', [$copath], [__("M $copath/A/dir.lnk")], 'modified status'); _check_symlinks (@allsymlinks); is_output ($svk, 'diff', [$copath], [__('=== t/checkout/symlink/A/dir.lnk'), '==================================================================', __("--- t/checkout/symlink/A/dir.lnk\t(revision 1)"), __("+++ t/checkout/symlink/A/dir.lnk\t(local)"), '@@ -1 +1 @@', '-link /tmp', '\ No newline at end of file', '+link .', '\ No newline at end of file'], 'modified diff'); $svk->revert ("$copath/A/dir.lnk"); _check_symlinks (@allsymlinks); is_output ($svk, 'status', [$copath], [], 'revert'); $svk->cp ('//A/non.lnk', "$copath/non.lnk.cp"); ok (_l("$copath/non.lnk.cp"), 'copy'); _fix_symlinks(); _check_symlinks (@allsymlinks, "$copath/non.lnk.cp"); is_output ($svk, 'commit', ['-m', 'add copied symlink', $copath], ['Committed revision 2.']); $svk->cp ('-m', 'make branch', '//A', '//B'); # XXX: commit and then update will break checkout optimization, # make a separate test for that $svk->update ($copath); unlink ("$copath/B/dir.lnk"); _symlink ('.', "$copath/B/dir.lnk"); _check_symlinks (map {s{/A}{/B}; $_} @allsymlinks); _fix_symlinks(); $svk->commit ('-m', 'change something', "$copath/B"); is_output ($svk, 'status', [$copath], [], 'committed'); $svk->smerge ('-C', '//B', "$copath/A"); # Symlink correction adds a revision my $baserev = (HAS_SYMLINK ? 1 : 2); is_output ($svk, 'smerge', ['--no-ticket', '//B', "$copath/A"], ["Auto-merging (0, 4) /B to /A (base /A:$baserev).", __("U $copath/A/dir.lnk")], 'merge'); is_output ($svk, 'diff', [$copath], [__('=== t/checkout/symlink/A/dir.lnk'), '==================================================================', __("--- t/checkout/symlink/A/dir.lnk\t(revision 4)"), __("+++ t/checkout/symlink/A/dir.lnk\t(local)"), '@@ -1 +1 @@', '-link /tmp', '\ No newline at end of file', '+link .', '\ No newline at end of file'], 'merge'); _symlink ('non', "$copath/B/new-non.lnk"); $svk->import ('--force', '-m', 'use import', '//', $copath); unlink ("$copath/B/new-non.lnk"); $svk->revert ('-R', "$copath/B"); ok (_l("$copath/B/new-non.lnk"), 'import sets auto prop too'); is_output ($svk, 'status', [$copath], [], 'import'); $svk->rm ("$copath/B/new-non.lnk"); is_output ($svk, 'status', [$copath], [__('D t/checkout/symlink/B/new-non.lnk')], 'delete'); overwrite_file ("$copath/B/new-non.lnk", "foobar\n"); is_output ($svk, 'add', ["$copath/B/new-non.lnk"], [__('R t/checkout/symlink/B/new-non.lnk')], 'replace symlink with normal file'); _fix_symlinks(); is_output ($svk, 'commit', ['-m', 'change to non-link', $copath], ['Committed revision 6.']); $svk->update ('-r5', $copath); ok (_l("$copath/B/new-non.lnk"), 'update from file to symlink'); $svk->update ($copath); ok (-e "$copath/B/new-non.lnk", 'update from symlink to file'); $svk->rm ("$copath/B/new-non.lnk"); _symlink ('non', "$copath/B/new-non.lnk"); is_output ($svk, 'add', ["$copath/B/new-non.lnk"], [__('R t/checkout/symlink/B/new-non.lnk')], 'replace normal file with symlink'); is_output ($svk, 'st', [$copath], [__('R t/checkout/symlink/B/new-non.lnk')]); is_output ($svk, 'commit', ['-m', 'change to non-link', $copath], ['Committed revision 7.']); unlink ("$copath/B/dir.lnk"); _symlink ('/tmp', "$copath/B/dir.lnk"); is_output ($svk, 'commit', ['-m', "change dir.lnk", "$copath/B/dir.lnk"], ['Committed revision 8.']); $svk->rm ("$copath/A/dir.lnk"); overwrite_file ("$copath/A/dir.lnk", "link /tmp"); is_output ($svk, 'add', ["$copath/A/dir.lnk"], [__("R $copath/A/dir.lnk")], 'replace symlink with normal file of same content'); is_output ($svk, 'status', [$copath], [__("R $copath/A/dir.lnk")], 'replace symlink with normal file of same content'); $svk->commit (-m => 'change a symlink to normal file', $copath); @allsymlinks = grep {!m/dir.lnk/} @allsymlinks; is_output ($svk, 'status', [$copath], [], 'committed'); $svk->rm ("$copath/A/dir.lnk"); _symlink ('non', "$copath/A/dir.lnk"); is_output ($svk, 'add', ["$copath/A/dir.lnk"], [__("R $copath/A/dir.lnk")], 'replace with symlink to nonexist'); _fix_symlinks(); is_output ($svk, 'commit', [-m => 'replace to symlink to nonexist', $copath], ['Committed revision 10.']); _symlink ('A', "$copath/entry.lnk"); $svk->add ("$copath/entry.lnk"); is_output ($svk, 'status', [$copath], [__("A $copath/entry.lnk")]); _fix_symlinks(); is_output ($svk, 'revert', ["$copath/entry.lnk"], [__"Reverted $copath/entry.lnk"]); is_output ($svk, 'status', [$copath], [__("? $copath/entry.lnk")]); unlink ("$copath/entry.lnk"); unlink ("$copath/non.lnk.cp"); overwrite_file ("$copath/non.lnk.cp", "hate\n"); SKIP: { skip 'no real symlinks', 8 unless HAS_SYMLINK; is_output ($svk, 'status', [$copath], ["~ $copath/non.lnk.cp"], 'overwrite symlink with normal file'); is_output($svk, 'ci', [-m => 'bzz', '--import', $copath], ['Committed revision 11.']); is_output ($svk, 'status', [$copath], []); unlink ("$copath/non.lnk.cp"); _symlink ('non', "$copath/non.lnk.cp"); _fix_symlinks(); is_output ($svk, 'status', [$copath], ["~ $copath/non.lnk.cp"], 'change file back to symlink'); is_output($svk, 'ci', [-m => 'back to symlink with --import', '--import', $copath], ['Committed revision 12.']); $svk->revert ($copath); is_output ($svk, 'status', [$copath], []); # the first part of _check_symlinks currently passes but the second part fails. # once both parts are passing revert back to a single call like the rest of the file. _check_symlinks1 ("$copath/non.lnk.cp", "$copath/B/dir.lnk"); _check_symlinks2 ("$copath/non.lnk.cp", "$copath/B/dir.lnk"); }