@@ -731,30 +731,34 @@ 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
737- unless target_directory
738- destdirs = fu_split_path ( File . realdirpath ( dest ) )
739- end
734+ cmd = "ln -s#{ force ? 'f' : '' } #{ target_directory ? '' : 'T' } " if verbose
740735 fu_each_src_dest0 ( src , dest , target_directory ) do |s , d |
741736 if target_directory
742- destdirs = fu_split_path ( File . realdirpath ( File . dirname ( d ) ) )
743- # else d == dest
737+ parent = File . dirname ( d )
738+ destdirs = fu_split_path ( parent )
739+ real_ddirs = fu_split_path ( File . realpath ( parent ) )
740+ else
741+ destdirs ||= fu_split_path ( dest )
742+ real_ddirs ||= fu_split_path ( File . realpath ( dest ) )
744743 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 )
744+ srcdirs = fu_split_path ( s )
745+ i = fu_common_components ( srcdirs , destdirs )
746+ n = destdirs . size - i
747+ n -= 1 unless target_directory
748+ link1 = fu_clean_components ( *Array . new ( [ n , 0 ] . max , '..' ) , *srcdirs [ i ..-1 ] )
749+ begin
750+ real_sdirs = fu_split_path ( File . realdirpath ( s ) ) rescue nil
751+ rescue
749752 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 )
753+ i = fu_common_components ( real_sdirs , real_ddirs )
754+ n = real_ddirs . size - i
755+ n -= 1 unless target_directory
756+ link2 = fu_clean_components ( *Array . new ( [ n , 0 ] . max , '..' ) , *real_sdirs [ i ..-1 ] )
757+ link1 = link2 if link1 . size > link2 . size
757758 end
759+ s = File . join ( link1 )
760+ fu_output_message [ cmd , s , d ] . flatten . join ( ' ' ) if verbose
761+ next if noop
758762 remove_file d , true if force
759763 File . symlink s , d
760764 end
@@ -2504,22 +2508,26 @@ def fu_split_path(path) #:nodoc:
25042508 path = File . path ( path )
25052509 list = [ ]
25062510 until ( parent , base = File . split ( path ) ; parent == path or parent == "." )
2507- list << base
2511+ if base != '..' and list . last == '..' and !( fu_have_symlink? && File . symlink? ( path ) )
2512+ list . pop
2513+ else
2514+ list << base
2515+ end
25082516 path = parent
25092517 end
25102518 list << path
25112519 list . reverse!
25122520 end
25132521 private_module_function :fu_split_path
25142522
2515- def fu_relative_components_from ( target , base ) #:nodoc:
2523+ def fu_common_components ( target , base ) #:nodoc:
25162524 i = 0
25172525 while target [ i ] &.== base [ i ]
25182526 i += 1
25192527 end
2520- Array . new ( base . size - i , '..' ) . concat ( target [ i ..- 1 ] )
2528+ i
25212529 end
2522- private_module_function :fu_relative_components_from
2530+ private_module_function :fu_common_components
25232531
25242532 def fu_clean_components ( *comp ) #:nodoc:
25252533 comp . shift while comp . first == "."
@@ -2529,7 +2537,7 @@ def fu_clean_components(*comp) #:nodoc:
25292537 while c = comp . shift
25302538 if c == ".." and clean . last != ".." and !( fu_have_symlink? && File . symlink? ( path ) )
25312539 clean . pop
2532- path . chomp !( %r((?<=\A |/)[^/]+/\z ) , "" )
2540+ path . sub !( %r((?<=\A |/)[^/]+/\z ) , "" )
25332541 else
25342542 clean << c
25352543 path << c << "/"
0 commit comments