From ecaa264a10c01635ef999d7a98c7ebc0920575fe Mon Sep 17 00:00:00 2001 From: Tom Close Date: Wed, 18 May 2022 15:49:36 +0100 Subject: [PATCH 1/3] failing spec for CreateFile#identical? utf-8 bug --- spec/actions/create_file_spec.rb | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/spec/actions/create_file_spec.rb b/spec/actions/create_file_spec.rb index 1e0c934e0..d92762130 100644 --- a/spec/actions/create_file_spec.rb +++ b/spec/actions/create_file_spec.rb @@ -7,11 +7,11 @@ ::FileUtils.rm_rf(destination_root) end - def create_file(destination = nil, config = {}, options = {}) + def create_file(destination = nil, config = {}, options = {}, contents = "CONFIGURATION") @base = MyCounter.new([1, 2], options, :destination_root => destination_root) allow(@base).to receive(:file_name).and_return("rdoc") - @action = Thor::Actions::CreateFile.new(@base, destination, "CONFIGURATION", {:verbose => !@silence}.merge(config)) + @action = Thor::Actions::CreateFile.new(@base, destination, contents, {:verbose => !@silence}.merge(config)) end def invoke! @@ -196,5 +196,12 @@ def silence! invoke! expect(@action.identical?).to be true end + + it "returns true if the destination file exists and is identical and contains multi-byte UTF-8 codepoints" do + create_file("doc/config.rb", {}, {}, "€") + expect(@action.identical?).to be false + invoke! + expect(@action.identical?).to be true + end end end From b792623bfdf9256a385a167590ce127bf797444e Mon Sep 17 00:00:00 2001 From: Tom Close Date: Wed, 18 May 2022 15:51:00 +0100 Subject: [PATCH 2/3] fix CreateFile#identical? utf-8 bug --- lib/thor/actions/create_file.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/thor/actions/create_file.rb b/lib/thor/actions/create_file.rb index fa7b22cbb..2f913b827 100644 --- a/lib/thor/actions/create_file.rb +++ b/lib/thor/actions/create_file.rb @@ -43,7 +43,7 @@ def initialize(base, destination, data, config = {}) # Boolean:: true if it is identical, false otherwise. # def identical? - exists? && File.binread(destination) == render + exists? && File.binread(destination) == String.new(render).force_encoding("ASCII-8BIT") end # Holds the content to be added to the file. From 00b0829dfd8aa17c0d8c4ab9deab6c126cc1cedd Mon Sep 17 00:00:00 2001 From: Tom Close Date: Wed, 18 May 2022 21:19:20 +0100 Subject: [PATCH 3/3] add comment explaining why we need to force ASCII-8BIT encoding when comparing created files --- lib/thor/actions/create_file.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/thor/actions/create_file.rb b/lib/thor/actions/create_file.rb index 2f913b827..56855c2a7 100644 --- a/lib/thor/actions/create_file.rb +++ b/lib/thor/actions/create_file.rb @@ -43,6 +43,7 @@ def initialize(base, destination, data, config = {}) # Boolean:: true if it is identical, false otherwise. # def identical? + # binread uses ASCII-8BIT, so to avoid false negatives, the string must use the same exists? && File.binread(destination) == String.new(render).force_encoding("ASCII-8BIT") end