Skip to content

Commit 6b24420

Browse files
committed
Fix encoding error when trying to show a diff:
- ### Problem Copying or creating a file with UTF-8 charatacters would raise an encoding error when: 1) There is a collision and the user wants to see a diff. 2) The application has set its `Encoding.default_internal` to a non-nil value. ### Context In Rails applications, the `Encoding.default_internal` is set to UTF-8. The `Encoding.default_external` will be used to transcode a string because the `default_internal` is not nil. So doing this would raise a `Encoding::UndefinedConversionError` ```ruby content = "\xE2\x80\x99".force_encoding(Encoding::ASCII_8_BIT) File.write("my_file.rb", content) ```
1 parent 44c4cac commit 6b24420

File tree

2 files changed

+24
-1
lines changed

2 files changed

+24
-1
lines changed

Diff for: lib/thor/shell/basic.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,7 @@ def show_diff(destination, content) #:nodoc:
314314
diff_cmd = ENV["THOR_DIFF"] || ENV["RAILS_DIFF"] || "diff -u"
315315

316316
require "tempfile"
317-
Tempfile.open(File.basename(destination), File.dirname(destination)) do |temp|
317+
Tempfile.open(File.basename(destination), File.dirname(destination), binmode: true) do |temp|
318318
temp.write content
319319
temp.rewind
320320
system %(#{diff_cmd} "#{destination}" "#{temp.path}")

Diff for: spec/actions/file_manipulation_spec.rb

+23
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,29 @@ def file
8181
expect(File.stat(original).mode).to eq(File.stat(copy).mode)
8282
end
8383

84+
it "shows the diff when there is a collision and source has utf-8 characters" do
85+
previous_internal = Encoding.default_internal
86+
87+
silence_warnings do
88+
Encoding.default_internal = Encoding::UTF_8
89+
end
90+
91+
destination = File.join(destination_root, "encoding_with_utf8.thor")
92+
FileUtils.mkdir_p(destination_root)
93+
94+
File.write(destination, "blabla")
95+
96+
expect(Thor::LineEditor).to receive(:readline).and_return("d", "y")
97+
expect(runner.shell).to receive(:system).with(/diff -u/)
98+
action :copy_file, "encoding_with_utf8.thor"
99+
100+
exists_and_identical?("encoding_with_utf8.thor", "encoding_with_utf8.thor")
101+
ensure
102+
silence_warnings do
103+
Encoding.default_internal = previous_internal
104+
end
105+
end
106+
84107
it "logs status" do
85108
expect(action(:copy_file, "command.thor")).to eq(" create command.thor\n")
86109
end

0 commit comments

Comments
 (0)