githubとrcmを使ったモダンdotfiles管理

## dotfilesとは

*NIX系OSでよくある、ソフトウェアの個人設定ファイルのことです。
大抵`$HOME`直下に置かれ、先頭がドットで始まる隠しファイルなのでそう呼びます。

## なぜdotfilesをgithubで管理すべきか

個人向けの設定ファイルをいろんな環境で使いまわすためです。
そのために、githubはある意味最適の条件が揃っています:

- インターネットさえあれば、どこからでもアクセスできる
- `git`があれば、どこからでも変更の追跡ができる
- `git`がなくても、ブラウザからzipballやtarballでダウンロードできる
- ブラウザがなくても、パーマリンクを使って`wget`や`curl`でダウンロードできる
- ソースを公開していれば無料で使い放題

## dotfilesを使いまわすときの問題

- インストールが面倒くさい

これに尽きます。なので、大抵の場合インストールスクリプトを自作することになりますが…

- そもそも可搬性の高いシェルスクリプトを書くのが難しい
    -  非標準コマンドへの依存、`bash`依存 etc.
- 複数の環境でのテストが面倒
    -  Windowsは諦めるとしても、*BSD / OSX / Linux etc. 

ということで、厄介ごとが多いです。

## `rcm`で解決

https://github.com/thoughtbot/rcm

> rcm
> This is a management suite for dotfiles. See the tutorial to get started quickly.
>
> It assumes that you have a separate dotfiles directory, or are interested in creating one.
>
> The programs provided are rcup(1), mkrc(1), rcdn(1), and lsrc(1). They are explained in the tutorial and configured using rcrc(5).

名前(rc manager)の通り、dotfilesの管理ツールです。

`rcm`というのはパッケージの名前で、
実際は複数のコマンドと1つの設定ファイルで構成されています。

これを使うと、

- どの*NIX環境でもきちんとインストールできる
- コマンド一発でアップデートできる
- インストール/アップデートをフックしてスクリプトの実行ができる
- `rcm`自体のインストールも、システムのパッケージ管理システムを使って行える
- パッケージ管理システムがなくても、`make`さえあればインストールできる

便利ですね。

## `rcm`を使った管理

[公式ドキュメント](https://robots.thoughtbot.com/rcm-for-rc-files-in-dotfiles-repos)を見れば詳しく書いてあります。かいつまんで説明すると、

### ディレクトリ構成

今からdotfilesを新たに用意したい場合は、[thoughtbot/dotfiles](https://github.com/thoughtbot/dotfiles)をフォークすると、そのまま使えます。

基本的にはディレクトリのトップに、アタマのドットを抜いたファイル群を置きます。

```bash
% find dotfiles
dotfiles/
dotfiles/vimrc
dotfiles/emacs.d/
dotfiles/tmux.conf
dotfiles/rcrc
dotfiles/hooks/
dotfiles/hooks/post-up
```

`hooks/post-up`にあるスクリプトは、`rcup`によるインストール/アップデートをフックして実行されます。

アタマのドットがついたままだと、`rcm`に無視されます。
これによって、`.git`や`.gitignore`などのファイルが自動的に管理から外れます。

アタマにドットがついていないファイルを除外したい場合は、
`rcm`の設定ファイル`rcrc`に、以下を追記します:

```bash
EXCLUDES="README.md LICENSE"
```

中身はシェルスクリプトとして解釈されるので、`=`の間にスペースを入れてはなりません。

### `rcup`

dotfilesレポジトリが用意できたら、ローカルのホームディレクトリにクローンしておきます。

初回は`rcm`をインストールしないといけないので、公式のインストールガイドにしたがってインストールします。
Ubuntuならapt、CentOSならyum、OSXならHomebrewからインストールできるうえ、
`./configure && make all install`でもいけます。

さて、インストールができたら早速、以下を実行します。

```bash
env RCRC=dotfiles/rcrc rcup
```

環境変数`$RCRC`は`rcm`の設定ファイル(`rcrc`)の場所を指します。
上述のディレクトリ構成なら、`$HOME/.rcrc`ができるので、次回からは`rcup`だけでいけます。

`rcup`を実行すると、`dotfiles`以下のファイル群がアタマのドット付きでホームディレクトリに展開されます。
展開直前に、`hooks/pre-up`スクリプトが（もしあれば）実行され、展開直後に、`hooks/post-up`スクリプトが（もしあれば）実行されます。
環境依存の設定は、`hooks/post-up`で書き換えると良いです。

展開処理は、デフォルトでは以下のルールに従います:

- ディレクトリは階層ごとにコピー
- ファイルはシンボリックリンク

なので、新たに`$HOME`直下に（環境依存の）ファイルを作っても、リポジトリの管理下にはなりません。
管理したくなったら、後述の`mkrc`を使います。

### `rcdn`

簡単にいうと`rcup`の逆で、アンインストール専用のコマンドです。
通常これを使うときは`$HOME/.rcrc`が存在するので、`rcdn`するだけでいいです。

### `mkrc`

管理外のdotfilesを`rcm`の管理下に移すコマンドです。
`mkrc .vimrc`のように使います。

### `lsrc`

簡単にいうと、`rcup`のdry-runを行うコマンドです。
管理中のファイルを確認したいときに使います。

## TIPS

`rcm`と直接関係ないんですが、グローバルに使いまわすdotfilesの他に、環境依存の設定も使いたい場合、設定ファイル内でローカル用の設定をインクルードするとよいです。
たとえば、
https://github.com/thoughtbot/dotfiles/blob/master/zshrc

環境によってdotfilesの記述を変化させたい場合、`hooks/post-up`を使ってパッチを当てることができます。
パッチファイルを別のディレクトリに隔離して`.rcrc`内で`$EXCLUDES`しておくと、それ自体の管理も綺麗にできます。
`.rcrc`の`$COPY_ALWAYS`変数に書き換えるファイルを指定しておけば、リポジトリも汚れなくて便利です。