Atom を WSL の GIT_EDITOR として使う


WSL のターミナルから Git を使っている場合にコミットメッセージを Windows の Atom で入力できるようにする方法のメモです。Atom のターミナルから WSL の Git を使う方法については情報がたくさんありますが,逆(?)の場合は見当たらなかったのでまとめました。

やっていることはパスを変換するラッパースクリプトを書いているだけです。

WSL から Atom を使う場合の制限

Atom は 1.18 で WSL からの起動をサポートしました。また,WSL と Windows の相互運用性により,作業ディレクトリも可能な限り WSL のものが維持されるようになっています。これらのおかげで,Windows ファイルシステム(DrvFs)上のファイルやディレクトリならば,ほぼ問題なく Atom で開けます。

ただし,WSL から Atom でファイルやディレクトリを開くためには相対パスで指定する必要があるようです。絶対パスだとうまくいきません。たとえば,/mnt/c/path/to/sample.txt を開こうとすると C:\mnt\c\path\to\sample.txt のように解釈されてしまいます。Windows ではスラッシュもパスの区切りとして利用できるためなのか,中途半端に受け入れられてしまってエラーにならず,作業ディレクトリのドライブが頭につきます。

GIT_EDITOR として使う場合の問題

普通にエディタとして使う場合は常に相対パスで指定するようにすれば問題ありませんが,Git のエディタとして設定する場合には困ることがあります。

コミットを実行するとコミットメッセージを入力するために COMMIT_EDITMSG というファイルが指定したエディタで開かれますが,このファイルのパスは絶対パスで渡されるようなのです。Atom を WSL の $GIT_EDITOR に設定している場合,/mnt/c/path/to/repos/.git/COMMIT_EDITMSG を開こうとして C:\mnt\c\path\to\repos\.git\COMMIT_EDITMSG を開いてしまいます。当然,この状態でコミットメッセージを書いて保存しても,無関係の場所にファイルができるだけで正しくコミットされません。

$ git commit

Aborting commit due to empty commit message.

パスを変換するラッパースクリプト

この問題への対処としては,簡単なラッパーを書くことが考えられます。以下のようなシェルスクリプトを書いて ~/bin/atom として $PATH に入れておけば解決です。

~/bin/atom
#!/usr/bin/env bash

set -eu

argv=("$@")

for ((i=0; i < $#; i++))
do
    v=${argv[$i]}
    if [[ $v != -* ]]; then
        argv[$i]=$(wslpath -m $(realpath "$v"))
    fi
done

cmd.exe /C atom.cmd "${argv[@]}"

オプション以外の引数をファイル・ディレクトリと見なして wslpath コマンドでパスを変換しています。set -e しているので,WSL のファイルシステム(VolFs)上にあるファイルを開こうとすると,wslpath がパスの変換に失敗してエラーとなり,その時点で強制終了します。誤って WSL のファイルを編集してしまう事態を避けることができます。

realpath でパスを正規化しているのは,通常のエディタとしてターミナルから起動する場合も想定してのことです。wslpath は(引数に相対パスが与えられると?)シンボリックリンクを展開しません。ホームディレクトリに Windows ファイルシステム上のディレクトリへのシンボリックリンクを作っている場合,そのディレクトリをホームディレクトリからの相対パスで開こうとするとエラーになります。あらかじめ realpath でシンボリックリンクを展開して絶対パスに直してやることで,この問題を回避することができます。

参考