Brew-fileの Issue で指摘してもらって気づいたのですが、 Homebrewでetcディレクトリを含むパッケージをインストールすると、 アップデートがきちんと行われない事態に陥る事になる事があったのでそれの解決法について。
etc.installの仕様
HomebrewでGitHubにあるレポジトリを取ってきて そのまま中にあるbinやetcディレクトリの中のファイルをインストールするような場合、 通常、
bin.install "bin/brew-file"
等と書いておくと、取ってきて展開したりしたディレクトリのbin/brew-fileを /usr/local/Cellar/brew-file/3.9.3/bin/ 1 などへコピーし、 さらに/usr/bin/にそこへのシンボリックリンクを作ります。
lib等のディレクトリも同様。
但し、etcディレクトリに限っては、
etc.install "etc/brew-wrap"
の様にしておくと、Cellarにはコピーされず、 /usr/etc/に直接ファイルがコピーされます。
homebrew/formula.rb at master · Homebrew/homebrew: https://github.com/Homebrew/homebrew/blob/master/Library/Homebrew/formula.rb#L644
さらに、既にファイルが存在している場合、新しいファイルで上書き等はしないので、
一度インストールすると、brew upgrade
等をしても新しい物に置き換わりません。
ファイルが存在している場合には代わりにbrew-wrap.defaultというファイルが作成されます。
また、brew uninstall
でパッケージを消した際にも消えません。
etcに意図的に同名のファイルを事前にインストールした場合に
Homebrew側では全てそのままにしておく、と言う処置ですが、
Homebrew-fileでも/usr/local/etc/brew-fileというbrew
コマンドを
ラップするためのファイルを置いているのでこれがアップデートされないと困ります。
etcをbin等と同様に扱う
etcを他のbin等と同様にCellarにインストールしてシンボリックリンクを作る、 という扱いにするためには
(prefix/"etc").install "etc/brew-wrap"
のように(prefix/”etc”).installを使います。
ここで、prefix
はパッケージの実態がインストールされるCellarの位置になるので、
Cellarの中のetcへetc/brew-wrapをコピーすることになります。
さらに、この様にCellarにインストールすると
自動的に/usr/local/etcにシンボリックリンクが貼られます。
homebrew/Formula-Cookbook.md at master · Homebrew/homebrew: https://github.com/Homebrew/homebrew/blob/master/share/doc/homebrew/Formula-Cookbook.md
これで、bin以下にあるものなどと同様のインストールが出来、
さらにuninstall
時にもきちんと消えてくれます。
勿論、アップデートすると新しいCellarへのリンクになるのでファイルの内容もアップデートされます。
注意として、これまでetc.installを使ってきて(prefix/”etc”).installに変更すると、
brew upgrade
や再インストールする際、
==> Installing brew-file from rcmdnk/file
==> Downloading https://github.com/rcmdnk/homebrew-file/archive/v3.9.3.tar.gz
Already downloaded: /Library/Caches/Homebrew/brew-file-3.9.3.tar.gz
Error: The `brew link` step did not complete successfully
The formula built, but is not symlinked into /usr/local
Could not symlink etc/brew-wrap
Target /usr/local/etc/brew-wrap
already exists. You may want to remove it:
rm '/usr/local/etc/brew-wrap'
To force the link and overwrite all conflicting files:
brew link --overwrite brew-file
To list all files that would be deleted:
brew link --overwrite --dry-run brew-file
Possible conflicting files are:
/usr/local/etc/brew-wrap
みたいなエラーが出ます。古いファイルがシンボリックリンクではないので どう扱ってよいか戸惑ってしまう訳です。
取り敢えず他にconflictしてる物が無さそうなら
$ brew link --overwrite brew-file
を実行すればOK。他にもconflictがあってそちらは治したくない場合は
$ rm '/usr/local/etc/brew-wrap'
をして、
$ brew reinstall brew-file
等とパッケージを再インストールしてください。
Formula側で強制的に上書きしたい場合は
rm_f etc/"brew-wrap.default"
rm_f etc/"brew-wrap"
(prefix/"etc").install "etc/brew-wrap"
の様にrm_f
を使ってファイルを消してやればOK。
これまでetc.installを使っていたのであれば
defaultファイルも余計に出来てるはずなのでそれも削除するように。
これで快適にetcを含むパッケージを使えます。
Brew-fileでは上の設定を入れてあるのでbrew update && brew upgrade
してもらえば/usr/local/etc/brew-wrapはシンボリックリンクに
変更されて、今後きちんとアップデートされるようになります。
install_symlinkについて
蛇足ですが、installの他にinstall_symlinkという関数もあり、 これを
etc.install_symlink "#{prefix}/etc/brew-wrap"
とすることとかを最初考えてたんですが、これだと /usr/local/etc/brew-fileというシンボリックリンクが出来て、 ../Cellar/brew-file/3.9.3/etc/brew-fileを指す正しいリンクなんですが、 肝心の../Cellar/brew-file/3.9.3/etc/brew-fileへ ファイルがコピーされないのでシンボリックリンクを開くと空ファイルになってしまいます。
install_symlinkは/usr/local下へのインストールに使う、というよりも、 Cellar内でリンクを貼る作業に使う物な感じでした。
つまり、
(prefix/"etc").install "etc/brew-wrap"
(prefix/"etc/more").install_symlink prefix/"etc/brew-wrap"
みたいにしておくと、Cellar内にetc/more/brew-wrapという、 etc/brew-wrapへのシンボリックリンクが出来、 さらに/usr/local/etc/more/brew-wrapにそのファイルに対するシンボリックリンクが出来ます。
ここでは/usr/localをHomebrewのインストール場所としていますが、 以下の/usr/localは全て
brew --prefix
で出てくるHomebrewをインストールした場所です。 ↩