sakura-editor / changelog-sakura

changelog for sakura
MIT License
1 stars 3 forks source link

`gsub': invalid byte sequence in Windows-31J #21

Open m-tmatma opened 5 years ago

m-tmatma commented 5 years ago

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 から日本語を取り除くとエラーは発生しない。

C:/Ruby24-x64/lib/ruby/gems/2.4.0/gems/github_changelog_generator-1.15.0.pre.rc/lib/github_changelog_generator/parser_file.rb:54:in `gsub': invalid byte sequence in Windows-31J (ArgumentError)
        from C:/Ruby24-x64/lib/ruby/gems/2.4.0/gems/github_changelog_generator-1.15.0.pre.rc/lib/github_changelog_generator/parser_file.rb:54:in `rescue in parse_line!'
        from C:/Ruby24-x64/lib/ruby/gems/2.4.0/gems/github_changelog_generator-1.15.0.pre.rc/lib/github_changelog_generator/parser_file.rb:48:in `parse_line!'
        from C:/Ruby24-x64/lib/ruby/gems/2.4.0/gems/github_changelog_generator-1.15.0.pre.rc/lib/github_changelog_generator/parser_file.rb:35:in `block in parse!'
        from C:/Ruby24-x64/lib/ruby/gems/2.4.0/gems/github_changelog_generator-1.15.0.pre.rc/lib/github_changelog_generator/parser_file.rb:35:in `each'
        from C:/Ruby24-x64/lib/ruby/gems/2.4.0/gems/github_changelog_generator-1.15.0.pre.rc/lib/github_changelog_generator/parser_file.rb:35:in `each_with_index'
        from C:/Ruby24-x64/lib/ruby/gems/2.4.0/gems/github_changelog_generator-1.15.0.pre.rc/lib/github_changelog_generator/parser_file.rb:35:in `parse!'
        from C:/Ruby24-x64/lib/ruby/gems/2.4.0/gems/github_changelog_generator-1.15.0.pre.rc/lib/github_changelog_generator/parser.rb:14:in `parse_options'
        from C:/Ruby24-x64/lib/ruby/gems/2.4.0/gems/github_changelog_generator-1.15.0.pre.rc/lib/github_changelog_generator.rb:28:in `initialize'
        from C:/Ruby24-x64/lib/ruby/gems/2.4.0/gems/github_changelog_generator-1.15.0.pre.rc/bin/github_changelog_generator:5:in `new'
        from C:/Ruby24-x64/lib/ruby/gems/2.4.0/gems/github_changelog_generator-1.15.0.pre.rc/bin/github_changelog_generator:5:in `<top (required)>'
        from C:/Ruby24-x64/bin/github_changelog_generator:23:in `load'
        from C:/Ruby24-x64/bin/github_changelog_generator:23:in `<main>'
berryzplus commented 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だったらこんな感じのエラーが出て不思議はないと思います。

ds14050 commented 5 years ago

どこに Windows-31J として扱われる文字列があるか、というのが肝です。

Rubyが2.0になってから、このマジックコメントを指定しない場合のデフォルトのファイルエンコーディングがUS-ASCIIからUTF-8に変更されました

REM 日本語を扱えるように内部エンコーディングを UTF-8 にする

あとは、ファイルシステムエンコーディングに由来するのかなあ、よくわからんなあ、という感じです。

berryzplus commented 5 years ago

引用先の記述はコードに関するものです。

言語仕様として、文字列のエンコードを想定しない、になっているにしても、I/OライブラリはC言語で書かれる環境依存のものです。windows向けの移植ではほぼvcrtが使われますがvcrtはバイトシーケンスをロケール依存のマルチバイトシーケンスと解釈します。

I/OのデフォルトはUTF-8にしてそうだったので原因は謎ですが、何らかの理由でシステムデフォルトが使われている可能性はあると思います。

ds14050 commented 5 years ago

引用先の記述はコードに関するものです。

1番目はそうです。文字列リテラルや正規表現リテラルがスクリプトエンコーディングの影響を受けるので、外部由来の文字列変数を埋め込んだり連結したりする際にエンコーディングのミスマッチが起きがちです。

2番目の引用が入出力で想定するデフォルトの文字コードについてです。「I/OのデフォルトはUTF-8にしてそうだった」の根拠に当たる部分ですよね。このオプションが実は機能していませんでした(テヘッ なんてのは知ったこっちゃないので、とりあえず別に原因を求めた結果が先のコメントです。

Ruby 2.6.0 リファレンスマニュアル > 多言語化

berryzplus commented 5 years ago

I/OのデフォルトがUTF-8にしてそうというのは、このコミット https://github.com/sakura-editor/changelog-sakura/commit/db9d666365c03d984052337000d1f1722d0437ec を見て思ったことです。

ruby.exeの起動オプションになんか指定してる ので「常に効果をもたらすと思っていたが、実は制約のある指定方法だった」という顛末を想定しています。

特定の関数を使う場合に効果があるとか、特定のパッケージを使う場合には効果がないとか、ありがちだと思います。おそらくバグというよりはオプションの特性に起因する挙動の違いなんじゃないかな、と。

解決策を導き出すために、検証のネタになりそうな仮定を書いてます。

ds14050 commented 5 years ago

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 を起動しているのか、実行スクリプトの内容は、などさっぱりわかっていません。

berryzplus commented 5 years ago

45行目の github_changelog_generator が ruby スクリプトだと思ってました。 中身は見てないのでアレですが、先頭に #!/usr/bin/ruby とか書いてあるのかな?と(ざっくり。

ds14050 commented 5 years ago

45行目の github_changelog_generator が ruby スクリプトだと思ってました。

そうだろうとは思います。その中身と思しきものは、別のリポジトリで確認した気がします。しかしあまりにも不確かです。

berryzplus commented 5 years ago

gem(=rubyのパッケージシステム)だった...orz

じゃ、どうやってRUBYOPTを渡してるんだろう?