From 5cb458d68798a3f96275cc7ffa0ede98ba38e8a6 Mon Sep 17 00:00:00 2001 From: Shaun Jackman Date: Fri, 22 Feb 2019 13:18:47 -0800 Subject: [PATCH] install_symlink_p: Fix when dest includes a symlink install_symlink_p does not work as intended when dst includes a symlink in its path. relative_path_from requires that both src and dst be real paths without symlinks. From https://ruby-doc.org/stdlib-2.3.7/libdoc/pathname/rdoc/Pathname.html#method-i-relative_path_from This method doesn't access the filesystem. It assumes no symlinks. --- Library/Homebrew/extend/pathname.rb | 7 ++++--- Library/Homebrew/test/pathname_spec.rb | 8 ++++++++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/Library/Homebrew/extend/pathname.rb b/Library/Homebrew/extend/pathname.rb index 8398726fe9..c27322e232 100644 --- a/Library/Homebrew/extend/pathname.rb +++ b/Library/Homebrew/extend/pathname.rb @@ -135,10 +135,11 @@ class Pathname end def install_symlink_p(src, new_basename) - src = Pathname(src).expand_path(self) - dst = join(new_basename) mkpath - FileUtils.ln_sf(src.relative_path_from(dst.parent), dst) + dstdir = realpath + src = Pathname(src).expand_path(dstdir) + src = src.dirname.realpath/src.basename if src.dirname.exist? + FileUtils.ln_sf(src.relative_path_from(dstdir), dstdir/new_basename) end private :install_symlink_p diff --git a/Library/Homebrew/test/pathname_spec.rb b/Library/Homebrew/test/pathname_spec.rb index e1c6645bf9..1967420212 100644 --- a/Library/Homebrew/test/pathname_spec.rb +++ b/Library/Homebrew/test/pathname_spec.rb @@ -245,6 +245,14 @@ describe Pathname do dst.install_symlink "foo" => "bar" expect((dst/"bar").readlink).to eq(described_class.new("foo")) end + + it "can install relative symlinks in a symlinked directory" do + mkdir_p dst/"1/2" + dst.install_symlink "1/2" => "12" + expect((dst/"12").readlink).to eq(described_class.new("1/2")) + (dst/"12").install_symlink dst/"foo" + expect((dst/"12/foo").readlink).to eq(described_class.new("../../foo")) + end end describe InstallRenamed do