Open m-tmatma opened 5 years ago
`gsub': invalid byte sequence in Windows-31J (ArgumentError)
このエラーメッセージ、Windows-31Jのマルチバイトシーケンスとして読もうとしたらおかしなバイトシーケンスを見付けました!(キラーン と言ってるように見えます。
Rubyのオプション(=環境変数?)でデフォルトのテキストエンコーディングをShift_JISにしてた、とかいうオチなんではないかと思います。
UTF-8は7bit以上のコードを表現するのに、一定のパターンで各byteの最上位ビットを立てます。 Shift_JISは9bit以上のコードを表現するのに、一定の値を持つLeadByteをくっ付けてBigEndianのマルチバイトシーケンス(2bytes)を作ります。
Shift_JISに存在しないパターンのバイト並びをデコーダに与えたとき、invalid byte sequence
というエラーを吐かせるのはよくある実装だと思います。対象ファイルの文字コードはUTF-8っぽいので、文字コード指定なしで読みに行ってI/Oデフォルトの文字コードがWindows-31Jだったらこんな感じのエラーが出て不思議はないと思います。
どこに Windows-31J として扱われる文字列があるか、というのが肝です。
「Rubyが2.0になってから、このマジックコメントを指定しない場合のデフォルトのファイルエンコーディングがUS-ASCIIからUTF-8に変更されました」
「REM 日本語を扱えるように内部エンコーディングを UTF-8 にする」
あとは、ファイルシステムエンコーディングに由来するのかなあ、よくわからんなあ、という感じです。
引用先の記述はコードに関するものです。
言語仕様として、文字列のエンコードを想定しない、になっているにしても、I/OライブラリはC言語で書かれる環境依存のものです。windows向けの移植ではほぼvcrtが使われますがvcrtはバイトシーケンスをロケール依存のマルチバイトシーケンスと解釈します。
I/OのデフォルトはUTF-8にしてそうだったので原因は謎ですが、何らかの理由でシステムデフォルトが使われている可能性はあると思います。
引用先の記述はコードに関するものです。
1番目はそうです。文字列リテラルや正規表現リテラルがスクリプトエンコーディングの影響を受けるので、外部由来の文字列変数を埋め込んだり連結したりする際にエンコーディングのミスマッチが起きがちです。
2番目の引用が入出力で想定するデフォルトの文字コードについてです。「I/OのデフォルトはUTF-8にしてそうだった」の根拠に当たる部分ですよね。このオプションが実は機能していませんでした(テヘッ なんてのは知ったこっちゃないので、とりあえず別に原因を求めた結果が先のコメントです。
I/OのデフォルトがUTF-8にしてそうというのは、このコミット https://github.com/sakura-editor/changelog-sakura/commit/db9d666365c03d984052337000d1f1722d0437ec を見て思ったことです。
ruby.exeの起動オプションになんか指定してる ので「常に効果をもたらすと思っていたが、実は制約のある指定方法だった」という顛末を想定しています。
特定の関数を使う場合に効果があるとか、特定のパッケージを使う場合には効果がないとか、ありがちだと思います。おそらくバグというよりはオプションの特性に起因する挙動の違いなんじゃないかな、と。
解決策を導き出すために、検証のネタになりそうな仮定を書いてます。
Ruby 1.9 ですが……
SET RUBYOPT=-EUTF-8:UTF-8
してから irb (対話型プロンプト) で確認した Encoding.default_external と Encoding.default_internal はともに UTF-8 を表すエンコーディングオブジェクトでした。
SET RUBYOPT=
してからだと、Encoding.default_external が Windows-31J で、Encoding.default_internal が nil でした。
berryzplus さんの想定はかなりありえることですが、デバッグ環境がなくてはどうにも。実は https://github.com/takke/changelog-sakura/blob/334126dcd8f0df46ea9a2138e6e843841060439d/makeChangeLog.bat を見てもどこで ruby.exe を起動しているのか、実行スクリプトの内容は、などさっぱりわかっていません。
45行目の github_changelog_generator
が ruby スクリプトだと思ってました。
中身は見てないのでアレですが、先頭に #!/usr/bin/ruby
とか書いてあるのかな?と(ざっくり。
45行目の github_changelog_generator が ruby スクリプトだと思ってました。
そうだろうとは思います。その中身と思しきものは、別のリポジトリで確認した気がします。しかしあまりにも不確かです。
gem(=rubyのパッケージシステム)だった...orz
じゃ、どうやってRUBYOPT
を渡してるんだろう?
https://github.com/sakura-editor/changelog-sakura/pull/13#discussion_r241907256 の以下のエラーが出る (ruby 2.4.5 および 2.6.1 で確認) d176c0fd87a2524bdc98b2ad1136009fa8cafb64 を使用。
github_changelog_generator.bat --help のみで発生。 日本語の .github_changelog_generator をうまく扱えない。 .github_changelog_generator から日本語を取り除くとエラーは発生しない。