Humanity

Edit the world by your favorite way

Gitのsubmoduleにまつわるsymlink問題、あとvital.vimのvitalizer

vital.vimとか知らない人は送ったpull reqの説明呼んだ方が分かりやすいです。

事象

  1. emap.vimをData.Listに依存するように書き換えた(未コミット)
  2. Data.ListをvitalizeしないままVimを終了させた(Windowsを再起動した)
  1. emap.vimの実行時にエラーが出るため、素のVimで立ち上がるようになってしまった
    • try catchで「source .vim/init.vim」を囲っているため、エラーが出たら即init.vimの読み込みをスキップするようにしている
    • むしろこれは(中途半端な設定が読み込まれて操作不能になる等といったように)傷を深めずに済んだのでやってて良かった
  2. とりあえずemap.vimを前回のバージョンに戻した
    • なぜかGitHub for Windows付属のmsysgitで「git stash」が使えないので手動バックアップしてから「git reset --hard」した
  3. プラグイン有りのVimを起動
  4. emap.vimリポジトリで「:Vitalize . Mapping Data.List」したら以下のようなエラー。

Could not retrieve current HEAD: vitalizer: 'git --git-dir "C:/Users/takuya/vimfiles/bundle/vital.vim/.git" rev-parse HEAD' failed: fatal: Not a git repository: C:/Users/takuya/vimfiles/bundle/vital.vim/../../../../.git/modules/dotfiles/.vim/bundle/vital.vim

「C:/Users/takuya/vimfiles」はtyru/dotfilesの「dotfiles/.vim」フォルダへのジャンクション。
Gitのsubmoduleの仕様上、submoduleのリポジトリの「.git」はディレクトリではなくファイルであり、中身に相対パス(gitdir: ../../../../.git/modules/dotfiles/.vim/bundle/vital.vim)が書かれていて、.gitディレクトリの実体は親リポジトリの「.git/modules/<トップレベルからの相対パス>」である。*1

しかしこの仕様はジャンクションや、おそらくUnix系においてもsymlinkなどで構成によっては存在しないパスを参照することがあり得る。
(「C:/Users/takuya/vimfiles/bundle/vital.vim/../../../../.git/modules/dotfiles/.vim/bundle/vital.vim」は「C:/Users/.git/modules/dotfiles/.vim/bundle/vital.vim」となるため)
今回はその問題にぶち当たってしまった。

とりあえず手動でvitalizeの処理をしようと思った*2が、うまくいかなかった。*3

vitalizer.vimの「s:vital_dir」の値がジャンクションを含む値となっていることが問題なので、
「s:vital_dir」を直接リテラル値で正しいパスに変更して「so /autoload/vitalizer.vim」して再度:Vitalizeを実行した。

総感

Gitの世界で解決するべきか、
それともGitを扱う以上vitalでもこういった問題をサポートするべきか。
ただこれはGit固有の問題ではなさそうだし、そもそもパスを連結する時に全てのディレクトリのsymlinkを解決してたら遅くなってしまう。
ただ以前のようにsubmoduleの.gitディレクトリがリポジトリの中に直接存在していれば問題は起きなかったはずで、なぜ仕様変更したのか気になるところ。

vital.vim側の対応

とりあえずvital.vim側の対応として、vital.vimに前述した「s:vital_dir」の値を変えられるグローバル変数を追加したpull reqを送った

*1:以前は.gitディレクトリがsubmoduleリポジトリの中に存在していたがいつの間にか仕様変更した

*2:「cp 」。ちなみにmsysgitなのでcpコマンドが使える

*3:だがこれは後にインポートするモジュールをData.ListではなくListと書いていたのが原因と判明。さらにその後Data.List(を使う関数が)いらなかったことが判明