diff --git a/lib/thor/actions/create_link.rb b/lib/thor/actions/create_link.rb index 51d4dab82..3c6014279 100644 --- a/lib/thor/actions/create_link.rb +++ b/lib/thor/actions/create_link.rb @@ -33,7 +33,8 @@ class CreateLink < CreateFile #:nodoc: # Boolean:: true if it is identical, false otherwise. # def identical? - exists? && File.identical?(render, destination) + source = File.expand_path(render, File.dirname(destination)) + exists? && File.identical?(source, destination) end def invoke! diff --git a/spec/actions/create_link_spec.rb b/spec/actions/create_link_spec.rb index 361159b6f..2f79b692f 100644 --- a/spec/actions/create_link_spec.rb +++ b/spec/actions/create_link_spec.rb @@ -4,93 +4,116 @@ describe Thor::Actions::CreateLink, :unless => windows? do before do - @silence = false @hardlink_to = File.join(Dir.tmpdir, "linkdest.rb") ::FileUtils.rm_rf(destination_root) ::FileUtils.rm_rf(@hardlink_to) end - def create_link(destination = nil, config = {}, options = {}) - @base = MyCounter.new([1, 2], options, :destination_root => destination_root) - allow(@base).to receive(:file_name).and_return("rdoc") + let(:config) { {} } + let(:options) { {} } - @tempfile = Tempfile.new("config.rb") + let(:base) do + base = MyCounter.new([1, 2], options, :destination_root => destination_root) + allow(base).to receive(:file_name).and_return("rdoc") + base + end + + let(:tempfile) { Tempfile.new("config.rb") } + + let(:source) { tempfile.path } - @action = Thor::Actions::CreateLink.new(@base, destination, @tempfile.path, - {:verbose => !@silence}.merge(config)) + let(:destination) { "doc/config.rb" } + + let(:action) do + Thor::Actions::CreateLink.new(base, destination, source, config) end def invoke! - capture(:stdout) { @action.invoke! } + capture(:stdout) { action.invoke! } end def revoke! - capture(:stdout) { @action.revoke! } - end - - def silence! - @silence = true + capture(:stdout) { action.revoke! } end describe "#invoke!" do - it "creates a symbolic link for :symbolic => true" do - create_link("doc/config.rb", :symbolic => true) - invoke! - destination_path = File.join(destination_root, "doc/config.rb") - expect(File.exist?(destination_path)).to be true - expect(File.symlink?(destination_path)).to be true + context "specifying :symbolic => true" do + let(:config) { {:symbolic => true} } + + it "creates a symbolic link" do + invoke! + destination_path = File.join(destination_root, "doc/config.rb") + expect(File.exist?(destination_path)).to be true + expect(File.symlink?(destination_path)).to be true + end end - it "creates a hard link for :symbolic => false" do - create_link(@hardlink_to, :symbolic => false) - invoke! - destination_path = @hardlink_to - expect(File.exist?(destination_path)).to be true - expect(File.symlink?(destination_path)).to be false + context "specifying :symbolic => false" do + let(:config) { {:symbolic => false} } + let(:destination) { @hardlink_to } + + it "creates a hard link" do + invoke! + destination_path = @hardlink_to + expect(File.exist?(destination_path)).to be true + expect(File.symlink?(destination_path)).to be false + end end it "creates a symbolic link by default" do - create_link("doc/config.rb") invoke! destination_path = File.join(destination_root, "doc/config.rb") expect(File.exist?(destination_path)).to be true expect(File.symlink?(destination_path)).to be true end - it "does not create a link if pretending" do - create_link("doc/config.rb", {}, :pretend => true) - invoke! - expect(File.exist?(File.join(destination_root, "doc/config.rb"))).to be false + context "specifying :pretend => true" do + let(:options) { {:pretend => true} } + it "does not create a link" do + invoke! + expect(File.exist?(File.join(destination_root, "doc/config.rb"))).to be false + end end it "shows created status to the user" do - create_link("doc/config.rb") expect(invoke!).to eq(" create doc/config.rb\n") end - it "does not show any information if log status is false" do - silence! - create_link("doc/config.rb") - expect(invoke!).to be_empty + context "specifying :verbose => false" do + let(:config) { {:verbose => false} } + it "does not show any information" do + expect(invoke!).to be_empty + end end end describe "#identical?" do it "returns true if the destination link exists and is identical" do - create_link("doc/config.rb") - expect(@action.identical?).to be false + expect(action.identical?).to be false invoke! - expect(@action.identical?).to be true + expect(action.identical?).to be true + end + + context "with source path relative to destination" do + let(:source) do + destination_path = File.dirname(File.join(destination_root, destination)) + Pathname.new(super()).relative_path_from(Pathname.new(destination_path)).to_s + end + + it "returns true if the destination link exists and is identical" do + expect(action.identical?).to be false + invoke! + expect(action.identical?).to be true + end end end describe "#revoke!" do it "removes the symbolic link of non-existent destination" do - create_link("doc/config.rb") invoke! - File.delete(@tempfile.path) + File.delete(tempfile.path) revoke! - expect(File.symlink?(@action.destination)).to be false + expect(File.symlink?(action.destination)).to be false end end end