Skip to content

Commit 2836a16

Browse files
committed
Fix up FileUtils#ln_sr
1 parent 7a748eb commit 2836a16

File tree

2 files changed

+26
-24
lines changed

2 files changed

+26
-24
lines changed

lib/fileutils.rb

Lines changed: 19 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -731,30 +731,22 @@ def ln_sf(src, dest, noop: nil, verbose: nil)
731731
# Like FileUtils.ln_s, but create links relative to +dest+.
732732
#
733733
def ln_sr(src, dest, target_directory: true, force: nil, noop: nil, verbose: nil)
734-
fu_output_message "ln -sr#{force ? 'f' : ''}#{
735-
target_directory ? '' : 'T'} #{[src,dest].flatten.join ' '}" if verbose
736-
return if noop
734+
cmd = "ln -s#{force ? 'f' : ''}#{target_directory ? '' : 'T'}" if verbose
737735
unless target_directory
738-
destdirs = fu_split_path(File.realdirpath(dest))
736+
destdirs = fu_split_path(dest)
739737
end
740738
fu_each_src_dest0(src, dest, target_directory) do |s,d|
741739
if target_directory
742-
destdirs = fu_split_path(File.realdirpath(File.dirname(d)))
740+
destdirs = fu_split_path(File.dirname(d))
743741
# else d == dest
744742
end
745-
if fu_starting_path?(s)
746-
srcdirs = fu_split_path((File.realdirpath(s) rescue File.expand_path(s)))
747-
base = fu_relative_components_from(srcdirs, destdirs)
748-
s = File.join(*base)
749-
else
750-
srcdirs = fu_clean_components(*fu_split_path(s))
751-
base = fu_relative_components_from(fu_split_path(Dir.pwd), destdirs)
752-
while srcdirs.first&. == ".." and base.last&.!=("..") and !fu_starting_path?(base.last)
753-
srcdirs.shift
754-
base.pop
755-
end
756-
s = File.join(*base, *srcdirs)
757-
end
743+
srcdirs = fu_split_path(s)
744+
i = fu_common_components(srcdirs, destdirs)
745+
n = destdirs.size - i
746+
n -= 1 unless target_directory
747+
s = File.join(fu_clean_components(*Array.new(n, '..'), *srcdirs[i..-1]))
748+
fu_output_message [cmd, s, d].flatten.join(' ') if verbose
749+
next if noop
758750
remove_file d, true if force
759751
File.symlink s, d
760752
end
@@ -2504,22 +2496,26 @@ def fu_split_path(path) #:nodoc:
25042496
path = File.path(path)
25052497
list = []
25062498
until (parent, base = File.split(path); parent == path or parent == ".")
2507-
list << base
2499+
if base != '..' and list.last == '..' and !(fu_have_symlink? && File.symlink?(path))
2500+
list.pop
2501+
else
2502+
list << base
2503+
end
25082504
path = parent
25092505
end
25102506
list << path
25112507
list.reverse!
25122508
end
25132509
private_module_function :fu_split_path
25142510

2515-
def fu_relative_components_from(target, base) #:nodoc:
2511+
def fu_common_components(target, base) #:nodoc:
25162512
i = 0
25172513
while target[i]&.== base[i]
25182514
i += 1
25192515
end
2520-
Array.new(base.size-i, '..').concat(target[i..-1])
2516+
i
25212517
end
2522-
private_module_function :fu_relative_components_from
2518+
private_module_function :fu_common_components
25232519

25242520
def fu_clean_components(*comp) #:nodoc:
25252521
comp.shift while comp.first == "."
@@ -2529,7 +2525,7 @@ def fu_clean_components(*comp) #:nodoc:
25292525
while c = comp.shift
25302526
if c == ".." and clean.last != ".." and !(fu_have_symlink? && File.symlink?(path))
25312527
clean.pop
2532-
path.chomp!(%r((?<=\A|/)[^/]+/\z), "")
2528+
path.sub!(%r((?<=\A|/)[^/]+/\z), "")
25332529
else
25342530
clean << c
25352531
path << c << "/"

test/fileutils/test_fileutils.rb

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1048,11 +1048,17 @@ def test_ln_sr
10481048
end
10491049
end
10501050

1051+
File.symlink 'data', 'link'
1052+
mkdir 'link/d1'
1053+
mkdir 'link/d2'
1054+
ln_sr 'link/d1/z', 'link/d2'
1055+
assert_equal '../d1/z', File.readlink('data/d2/z')
1056+
10511057
mkdir 'data/src'
10521058
File.write('data/src/xxx', 'ok')
10531059
File.symlink '../data/src', 'tmp/src'
10541060
ln_sr 'tmp/src/xxx', 'data'
1055-
assert File.symlink?('data/xxx')
1061+
assert_file.symlink?('data/xxx')
10561062
assert_equal 'ok', File.read('data/xxx')
10571063
end
10581064

0 commit comments

Comments
 (0)