summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/fileutils.rb24
-rw-r--r--test/fileutils/test_fileutils.rb4
2 files changed, 21 insertions, 7 deletions
diff --git a/lib/fileutils.rb b/lib/fileutils.rb
index 4caa792c9d..81461bc5e8 100644
--- a/lib/fileutils.rb
+++ b/lib/fileutils.rb
@@ -732,19 +732,31 @@ module FileUtils
#
def ln_sr(src, dest, target_directory: true, force: nil, noop: nil, verbose: nil)
cmd = "ln -s#{force ? 'f' : ''}#{target_directory ? '' : 'T'}" if verbose
- unless target_directory
- destdirs = fu_split_path(dest)
- end
fu_each_src_dest0(src, dest, target_directory) do |s,d|
if target_directory
- destdirs = fu_split_path(File.dirname(d))
- # else d == dest
+ parent = File.dirname(d)
+ destdirs = fu_split_path(parent)
+ real_ddirs = fu_split_path(File.realpath(parent))
+ else
+ destdirs ||= fu_split_path(dest)
+ real_ddirs ||= fu_split_path(File.realpath(dest))
end
srcdirs = fu_split_path(s)
i = fu_common_components(srcdirs, destdirs)
n = destdirs.size - i
n -= 1 unless target_directory
- s = File.join(fu_clean_components(*Array.new(n, '..'), *srcdirs[i..-1]))
+ link1 = fu_clean_components(*Array.new([n, 0].max, '..'), *srcdirs[i..-1])
+ begin
+ real_sdirs = fu_split_path(File.realdirpath(s)) rescue nil
+ rescue
+ else
+ i = fu_common_components(real_sdirs, real_ddirs)
+ n = real_ddirs.size - i
+ n -= 1 unless target_directory
+ link2 = fu_clean_components(*Array.new([n, 0].max, '..'), *real_sdirs[i..-1])
+ link1 = link2 if link1.size > link2.size
+ end
+ s = File.join(link1)
fu_output_message [cmd, s, d].flatten.join(' ') if verbose
next if noop
remove_file d, true if force
diff --git a/test/fileutils/test_fileutils.rb b/test/fileutils/test_fileutils.rb
index e4a64bb40d..500c47b56c 100644
--- a/test/fileutils/test_fileutils.rb
+++ b/test/fileutils/test_fileutils.rb
@@ -1031,7 +1031,8 @@ class TestFileUtils < Test::Unit::TestCase
assert_all_assertions_foreach(nil, *TARGETS) do |fname|
lnfname = 'tmp/lnsdest'
ln_sr fname, lnfname
- assert FileTest.symlink?(lnfname), 'not symlink'
+ assert_file.symlink?(lnfname)
+ assert_file.identical?(lnfname, fname)
assert_equal "../#{fname}", File.readlink(lnfname)
ensure
rm_f lnfname
@@ -1060,6 +1061,7 @@ class TestFileUtils < Test::Unit::TestCase
ln_sr 'tmp/src/xxx', 'data'
assert_file.symlink?('data/xxx')
assert_equal 'ok', File.read('data/xxx')
+ assert_equal 'src/xxx', File.readlink('data/xxx')
end
def test_ln_sr_not_target_directory