[rails/thor] マージツール実行時のエンコーディングエラーを修正

rails/thor

背景

Thorでファイル操作を行う際、既存ファイルとの衝突が発生した場合にマージツールを起動できる機能があります。しかし、UTF-8文字を含むファイルに対してマージツールを実行すると、エンコーディングエラーが発生する問題がありました。この問題は #898 で報告されていた類似の問題と同じ根本原因によるものです。

技術的な変更内容

問題の原因

Thor::Shell::Basic#merge メソッドでは、衝突が発生した際に一時ファイルを作成してマージツールに渡していました。しかし、Tempfile.open の呼び出し時に binmode: true オプションが指定されていなかったため、Rubyのデフォルトエンコーディング設定によってはバイナリモードで開かれず、UTF-8などの特定の文字コードを含むファイルの処理時にエンコーディングエラーが発生していました。

修正内容

変更前:

Tempfile.open([File.basename(destination), File.extname(destination)], File.dirname(destination)) do |temp|
  temp.write content
  temp.rewind
  system(*merge_tool, temp.path, destination)
end

変更後:

Tempfile.open([File.basename(destination), File.extname(destination)], File.dirname(destination), binmode: true) do |temp|
  temp.write content
  temp.rewind
  system(*merge_tool, temp.path, destination)
end

binmode: true オプションを追加することで、一時ファイルが常にバイナリモードで開かれるようになり、エンコーディングの変換処理が行われなくなりました。これにより、元のファイル内容がそのまま保持され、UTF-8文字を含むファイルでもマージツールが正常に動作するようになります。

テストの追加

この修正を検証するため、UTF-8文字を含むファイルに対してマージツールを実行する新しいテストケースが追加されました。

it "launches the merge tool when there is a collision and source has utf-8 characters" do
  previous_internal = Encoding.default_internal

  silence_warnings do
    Encoding.default_internal = Encoding::UTF_8
  end

  destination = File.join(destination_root, "encoding_with_utf8.thor")
  FileUtils.mkdir_p(destination_root)

  File.write(destination, "blabla")

  allow(runner.shell).to receive(:merge_tool).and_return("meld")
  expect(Thor::LineEditor).to receive(:readline).and_return("m")
  expect(runner.shell).to receive(:system).with("meld", /encoding_with_utf8.thor/, /encoding_with_utf8.thor/)
  action :copy_file, "encoding_with_utf8.thor"
ensure
  silence_warnings do
    Encoding.default_internal = previous_internal
  end
end

このテストでは、Encoding.default_internal を一時的にUTF-8に設定し、UTF-8文字を含むファイルに対してマージツールが正常に呼び出されることを確認しています。

影響範囲

この変更により、以下のような状況でThorが正常に動作するようになります:

  • UTF-8などの非ASCII文字を含むファイルに対してマージツールを使用する場合
  • Encoding.default_internal が設定されている環境でのファイル操作
  • 国際化されたプロジェクトでのジェネレーター実行時

既存の動作に対する破壊的変更はなく、バイナリモードでの一時ファイル作成により、より安全で予測可能な動作が保証されます。

記事メタデータ

Generated by:
Claude Sonnet 4.5 for DiffDaily

この記事はAIによって自動生成されています。内容の正確性については、必ずソースコードやPRを確認してください。

品質レビュー結果

Review Status:
承認済み
Review Count:
1回
Reviewed by:
Gemini 2.5 Pro for DiffDaily

Review Criteria:

ガイドライン準拠 ✓ PASS

記事構成とDiffDaily Styleへの準拠状況

記事構成(Title, Context, Technical Detail)、カスタムMarkdown構文(コードブロックの空行、ファイル名指定)、対象読者への適合性、すべての項目においてガイドラインを完全に遵守しています。特にコードブロック前後の空行が徹底されており、可読性が非常に高いです。

  • 記事構成(Title、Context、Technical Detail)
  • DiffDaily Styleガイド準拠
  • カスタムMarkdown活用
  • 対象読者への適合性
技術的整合性 ✓ PASS

技術的な正確性と表現の適切性

技術的な説明は非常に正確です。`Tempfile.open`に`binmode: true`を追加する変更点と、それがエンコーディングエラーを解決する理由(バイナリモードでの書き込み)が論理的に解説されています。引用されているコードも変更の核心を的確に捉えています。

  • 技術用語の正確性
  • コード例の正確性
  • 説明の技術的正確性
PR内容との整合性 ✓ PASS

元のPR情報との一致度

PRのタイトル「fix encoding error when running a merge tool」の内容を忠実に記事化できています。背景で関連Issue [#898] に言及している点も、PRの文脈を深く理解している証拠です。パフォーマンス向上などの根拠のない主張はなく、ハルシネーションは検出されませんでした。

  • タイトル・説明の一致
  • Diff内容の正確な反映
  • 推測の排除