MacでHomebrewを使ってパッケージを管理していると インストールした覚えの無いパッケージも大量に入っている事がありますが、 それはインストールしようとしたパッケージが必要とするモジュールなどを含むパッケージを自動でインストールしてくれているからです。
パッケージのリストを管理したい時にこういった依存先のパッケージも全て記録していくと 後々元のパッケージが要らなくなっても残ってしまったりします。
Homebrewでは最近パッケージのインストール時に直接インストールされたのか、 依存関係によってインストールされたのか確認出来る様なフラッグが導入されました。
installed_on_request/installed_as_dependency
Homebrewでインストールされたパッケージを確認するには通常
brew list
としますが、これだと全てのインストールされたパッケージが表示されます。
直接インストールされたのか、依存関係によってインストールされたのか を確認するには
$ brew info --json=v1 <package>
を使います。
$ brew info --json=v1 brew-file|jq .
[
{
"name": "brew-file",
"full_name": "rcmdnk/file/brew-file",
"desc": "Brewfile manager for Homebrew.",
"homepage": "https://github.com/rcmdnk/homebrew-file/",
"oldname": null,
"aliases": [],
"versions": {
"stable": "4.2.0",
"bottle": false,
"devel": null,
"head": "HEAD"
},
"revision": 0,
"version_scheme": 0,
"installed": [
{
"version": "4.2.0",
"used_options": [],
"built_as_bottle": false,
"poured_from_bottle": false,
"runtime_dependencies": [],
"installed_as_dependency": false,
"installed_on_request": true
}
],
"linked_keg": "4.2.0",
"pinned": false,
"outdated": false,
"keg_only": false,
"dependencies": [],
"recommended_dependencies": [],
"optional_dependencies": [],
"build_dependencies": [],
"conflicts_with": [],
"caveats": null,
"requirements": [],
"options": [
{
"option": "--without-completions",
"description": "Disable bash/zsh completions"
}
],
"bottle": {}
}
]
こんな感じでJSON形式でパッケージの情報がとってこれます1。
この中のinstalled
の項目にある
installed_as_dependency
/installed_on_request
というのが
最近導入された値です。
installed_as_dependency
がtrue
なら他のパッケージが依存するものとしてインストールされたものになります。
installed_on_request
がtrue
なら直接brew install <package>
でインストールされたものになります。
通常はこれらはどちらかがtrue
でどちらかがfalse
と反対になっているはずですが、
一部、両方true
だったりするものもあってちょっと良く分かりません。
(ただのバグか、導入の段階でちょっと混乱が起きてるのか。。。?)
また、この値が導入されたのは最近(6月中旬頃2)なので
それ以前にインストールされたパッケージについては
これらの値はnull
になっています。
これらの値を更新するにはreinstall
などする必要があります。
brew-fileでの取扱
そもそもこの情報はbrew-fileのIssuesでこれ使えないか、と教えてもらったもので 実際にこれらの情報を使える様にしてみました。
Use new
installed_on_request
andinstalled_as_dependency
flags · Issue #75 · rcmdnk/homebrew-file
brew file init
に新しく--on_request
というオプションを追加して
$ brew file init --on_request
とすると、installed_on_request
がtrue
のものだけをBrewfileに書き出す様になります。
もしくは環境変数で
export HOMEBREW_BREWFILE_ON_REQUEST=1
と設定しておくと常に--on_request
を付加している状態になります。
ただし、まだこの値がnull
のものもあるのでそういったものに関してはそのまま書き出す様にしています。
なので今現在--on_request
をしてもほとんどのパッケージが書き出されてしまう可能性がありますが
今後徐々に値が入っているパッケージが増えていくので徐々に使える様になるはずです。
leavesとの違い
以前、これに近いことをbrew leaves
の出力を使ってやっていました。
brew leaves
はどのパッケージからも依存されていないパッケージだけを表示するコマンドです。
$ brew file init --leaves
もしくは環境変数で
export HOMEBREW_BREWFILE_LEAVES=1
としておくとこのbrew leaves
の結果だけを書き出す様になります。
このleaves
を使う問題点としては、
例えばgo
を必要として最初にインストールした場合、
他のgo
に依存したパッケージを後からインストールすると
go
はbrew leaves
に残らなくなります。
これだと困るのでとりあえずの処置として
export HOMEBREW_BREWFILE_TOP_PACKAGES=go,coreutils
の様に環境変数で設定しておくとこれらのパッケージは常に書き出すことが出来る様にしています。
ただし、逆に何かの依存関係でインストールされたものも
その親のパッケージがアンインストールされると今度はそれがleaves
として残る様になってしまいます。
これらは正直いらないパッケージなのですがこれまでだと自分でそのパッケージを判断する以外に確認のしようがありませんでした。
これらを解決してくれるのが上のinstalled_on_request
などの値で、
実際にインストール時に値が振られるので
その後親のパッケージの削除などに左右される事無く値を見ることが出来ます。
今の自分の環境で調べてみると
- 全てのパッケージ: 223
- leaves: 127
- on_request (null含む): 210
となっています。
null
なものが多いのでほとんどのパッケージが書き出されている状態ですが、
全ての値が埋まれば大体同じ数になるはずで、
違いは
on_request
だけど後から入れたパッケージが依存している場合(on_request
のみに載る)、as_dependency
だけど親のパッケージがアンインストールされた場合(leaves
のみに載る)
になります。
必要のないパッケージの削除
その様な確認が出来る様になったので、何かのパッケージの依存パッケージとしてインストールされたものの、 親のパッケージがアンインストールされて最早不要になったパッケージを削除する事も出来ます。
brew-fileを使えば
$ brew file clean_non_request
brew uninstall unixodbc
###########################################
# This is dry run.
# If you want to enforce cleanup, use '-C':
# $ brew-file clean_non_request -C
###########################################
とすることでその様なパッケージを探すことが出来ます。
$ brew file clean_non_request -C
とするとそれらのパッケージを実際に削除します。
まとめ
Homebrewは未だにかなりアクティブに更新があって 細かな情報確認も出来る様になってきています。
なかなか全部追うのは大変ですが、まだ気付いてない機能もありそうなので 暇があったらちょっとずつ見ていきたいと思います。
-
出力は一行で書かれてるので
jq
で整形してあります。jq
はbrew install jq
でインストールできます。 ↩ tab: store installed_{as_dependency,on_request}. · Homebrew/brew@b99fb56 ↩