2012年05月20日

GitLabで日本語ファイル名のソース表示

最近git環境の構築を頑張っていますが、ちょうどいいタイミングでmsysGitやTortoiseGITの日本語ファイル名対応が始まったので、Windowsにも本格的にGit環境を構築始めました。

現在の環境はこんな感じです。

プロンプトConsole2 + 日本語入力パッチ適用済みバイナリ
シェルNYAOS
gitmsysGit
サーバ側GitLab + gitolite

正直Windows側もサーバ側も構築は一筋縄ではいかないので、まだまだおすすめできませんが、上記をうまいこと設定できるとUTF-8で統一できている限り、日本語が通るGit環境が構築できます。

ただし、テストしていて気になったのが、GitLabで日本語ファイル名のソースコードが表示されない点。

すでにバグとして報告されていますが、

ソースを追ったところ、利用しているgrit側の問題っぽい気がしています。

というのも、ソースの表示の際にはGrit::Treeの「/」メソッドで表示するオブジェクトを探しているのですが、Gritでファイル名を求めると日本語ファイル名も文字列クラスのエンコーディングがアスキーで戻ってくるため、「/」メソッドの内部でオブジェクトの検索を行う際に全く同じ文字列でもエンコーディングが異なるためマッチングせず、nilが帰ってしまい、GitLabでクラッシュしているようです。

1
2
3
4
5
repo = Grit::Repo.new("リポジトリの場所")
repo.commits[0].tree / "表.txt"                #=> false
repo.commits[0].tree.contents[0].name          #=> "\xE8\xA1\xA8.txt"
repo.commits[0].tree.contents[0].name.encoding #=> #<Encoding:ASCII-8BIT>
"表.txt".encoding                              #=> #<Encoding:UTF-8>
ちなみに、log/production.logに記録されるエラーは下記のような感じ
Started GET "/gitlab/testing/master/tree/%e8%a1%a8.txt" for 192.168.7.130 at 2012-05-20 06:35:02 +0900
Processing by RefsController#tree as JS
  Parameters: {"project_id"=>"testing", "id"=>"master", "path"=>"表.txt"}
  Rendered refs/_tree.html.haml (5.6ms)
  Rendered refs/tree.js.haml (6.3ms)
Completed 500 Internal Server Error in 30ms

ActionView::Template::Error (Tree#contents delegated to tree.contents, but tree is nil: #, @ref="master", @path="表.txt">):
    12:   - if tree.is_blob?
    13:     = render :partial => "refs/tree_file", :locals => { :name => tree.name, :content => tree.data, :file => tree }
    14:   - else
    15:     - contents = tree.contents
    16:     %table#tree-slider.bordered-table.table
    17:       %thead
    18:         %th Name
  app/models/tree.rb:8:in `rescue in contents'
  app/models/tree.rb:5:in `contents'
  app/views/refs/_tree.html.haml:15:in `_app_views_refs__tree_html_haml___1220856377968593484_29251100'
  app/views/refs/tree.js.haml:2:in `_app_views_refs_tree_js_haml___2381425268440379864_23737120'
で、肝心の解決策ですが、必ずUTF-8同士でマッチングさせるために、下記のようにソースを書き換えると手元の環境では日本語ファイル名のソースも表示できるようになりました。

vendor/bundle/ruby/1.9.1/bundler/gems/grit-3fc864f3c637/lib/grit/tree.rb (Ver. 2.4.1) の96行目付近を下記のように書き換え

#self.contents.find {|c| c.name == file }

self.contents.find {|c| c.name.force_encoding(Encoding::UTF_8) == file.force_encoding(Encoding::UTF_8) }
全然テストしてませんし、Gritの最新版の2.5.0での動きも確認していませんが、誰かの役に立つかもしれませんので、メモとして公開しておきます。

Posted by Takuchan at 2012年05月20日 09:38 | トラックバック(0)