rbenv/rbenvのコードリーディングの備忘録。バージョンは1.1.0-2-g4f8925a です。

bin/rbenvはrcファイルで明示的にパスを通したメインの実行ファイルです。rcスクリプト内で  eval "$(rbenv init -)" を呼び出すところが起点になります。

まず~/.rbenv/libexecにパスを通します。libexecディレクトリ内に各サブコマンドの実体が入っています。

環境変数など諸々の設定が終わった後、$command_pathが実行されます。initの場合はlibexec/rbenv-initが実行されます。

rbenv init -を実行すると、以下のようなスクリプトが文字列として返されるので、rcスクリプト内でevalします。これによって.rbenv/shimsにパスを通したりcompletionsのスクリプトを実行して補完が効くようにするなどの初期化が行われます。また、bin/rbenvコマンドがラップされたrbenv関数が定義されます。

rbenv init – で実行されるrehashの処理を追っていきます。実体はlibexec/rbenv-rehashです。中身は以下のようになっており、shimsディレクトリ内のshimファイルを作っています。shimファイルとは各バージョン差異を埋めるためのファイルであり、rbenvの場合は、ruby・irb・gemなどのファイル名で作成されるシェルスクリプトになります。これらのシェルスクリプトが各バージョンの実行ファイルを実行するような作りとなっています。

create_prototype_shim関数を見るとわかるとおり、全てのshimファイルは同じスクリプトであり、呼び出された名前によって呼び出す実行ファイルを切り替えています。

このファイルをプロトタイプとして作成し、install_registerd_shimsによってコピーを行い、rubyやgemのファイル名でシェルスクリプトを作成します。

このプロトタイプが呼び出すrbenv execの実体はlibexec/rbenv-execです。バージョンから適切な実行ファイルのパスを取得し、execコマンドで実行しています。

rbenv-version-nameはRBENV_VERSIONの環境変数を取得するか、無ければrbenv-version-file、rbenv-version-file-readによってバージョンを取得します。

rbenv-version-file関数は.ruby-versionファイルを指定のディレクトリから階層を上にたどって検索してパスを返します。なければ~/.rbenv/version(globalで指定したバージョン)を返します。

rbenv-version-file-readはrbenv-version-fileで取得したファイルパスからバージョンを取得します。

rbenv localを使うと.ruby-versionファイルが書き込まれたり、現在のバージョンを表示できます。

ちなみにrbenv自体のバージョンはgit describeの結果(タグ+タグからのコミット数+コミット番号)を表示しています。