やりたかったこと
ComposerでPackagist以外からインストールした場合にサブモジュール扱いとなってしまうのを回避したかった。
背景
Composerを利用していると、インストールされたライブラリー群も同リポジトリに含めるかどうかの選択に迫られると思います。
僕は含めました。
含めなかった理由として一番大きいのはデプロイ時にPackagistやその他のリポジトリを参照するのが嫌だった。
Satisを使えば回避出来るっぽいけど、その管理が増えるのはあまりメリットに感じませんでした。
というわけで僕の目の前にはcomposer.lockファイルだけじゃなく、vendorディレクトリも丸々入ったプロジェクトがあるんですが、ひとつ困ったことがありました。
Packagist以外から(たとえばGitHub)リポジトリを直接指定して入れるようにしたライブラリーがサブモジュールとして管理されてしまったのです。
理由は**.gitディレクトリが含まれているからでした。**
どうやらPackagistからインストールされる場合は.gitのようなファイルを削除してくれるようで、このような事態にはなりません。
ググったところSatisを利用するとSatis様が削除してくれるそうです。
しかしSatisを使うのはプライドが許さなくて他の手段を探したところ、ComposerにはCommand Eventsというのがあってinstallやupdadteをフックしてコマンドを実行する機能がありました。
Command Events
イベント | タイミング |
---|---|
pre-install-cmd | composer install コマンドの実行前 |
post-install-cmd | composer install コマンドの実行後 |
pre-update-cmd | composer update コマンドの実行前 |
post-update-cmd | composer update コマンドの実行後 |
その他イベントは試してないのでドキュメントを参照ください。結構いっぱいあります。
https://getcomposer.org/doc/articles/scripts.md#command-events
composer.jsonでコマンドを予約する
composer.jsonのrequireやrequire-devの並びにscriptsという情報を加えます。
こんな感じ
<<省略>>
"require": {
"laravel/framework": "5.0.*",
"illuminate/html": "~5.0"
},
"require-dev": {
"phpunit/phpunit": "~4.0",
"phpspec/phpspec": "~2.1"
},
"scripts": {
"post-install-cmd": [
"find ./vendor -name .git | xargs rm -rf"
],
"post-update-cmd": [
"find ./vendor -name .git | xargs rm -rf"
],
},
<<省略>>
上の例ではinstall後とupdate後それぞれ1つしか予約していませんが、配列で指定するようになっていて
複数のコマンドを予約する事もできます。
.gitディレクトリを削除するコマンド
find ./vendor -name .git | xargs rm -rf
xargsを使わないでfind ./vendor -name .git | rm -rf
だとディレクトリがうまく削除出来ないので注意です。
どうやら-rfがfindのオプションとみなされるっぽい。。
まとめ
正直バッドノウハウなんじゃないかという疑念は捨てきれないのですが、この方法でサブモジュール化されてしまう事を防ぐことが出来ました。