port のインストール順を決定するスクリプト

最近 MacBook を買い替えたので、MacPorts を入れ直しました。MacPorts は依存関係を勝手に解決して必要なものを芋蔓式にインストールしてくれます。しかし、そのように自動でインストールされた port の variants はデフォルトのままになってしまいます。あとで variants を変更しようものなら、それが単に +doc であったとしても、依存する port をすべてインストールし直さなければなりません。

たとえば、git-core を +doc+gitweb+svn+bash_completion でインストールすることを考えてみましょう。+svn を指定することで subversion が (インストール済みでなければ) 自動的にインストールされます。自動インストールされた subversion の variants はデフォルトのままなんですが、これを +mod_dav_svn+tools+bash_completion に変更しようとすると、上記のような問題点によって git-core を一度アンインストールしなければならないのです。自動的な依存関係の解決という便利な特徴が裏目に出てしまっています。

この問題を回避するには、ある port のインストール前に必要な依存関係を常に満足させ、自動インストールが発生しない状況を維持する必要があります。そのためには、インストールしたいパッケージの依存関係グラフ構造を辿り、その根本から順番に一つずつ variants を指定しながら port をインストールしていく必要があります。これをすべて人手で行うのは時間がかかる上に、膨大な依存関係を持つ port をインストールしなければならない場合は、人間の能力を越えてしまいます。こういうことは計算機にやらせるべきなんです。

そこで、port をインストールすべき順番を決定するためのスクリプトを作りました。名付けて port-scheduler.rb です。github の gist に置いたので、同じ問題で悩んでいる方がいたら使ってみてください [gist:36367]

このスクリプトの使い方は以下のとおりです。


起動するとプロンプト > が表示されます。コマンド ap で port を登録します。port を登録すると依存関係グラフを解析します。たとえば、上記の例で挙げた git-core を登録してみましょう。

> ap git-core
analyses dependencies of git-core...
analyses dependencies of curl...
analyses dependencies of pkgconfig...
analyses dependencies of zlib...
analyses dependencies of openssl...
analyses dependencies of expat...
analyses dependencies of libiconv...
analyses dependencies of gperf...
analyses dependencies of rsync...
analyses dependencies of popt...
analyses dependencies of gettext...
analyses dependencies of ncurses...
analyses dependencies of ncursesw...
analyses dependencies of perl5...
analyses dependencies of perl5.8...
analyses dependencies of p5-error...

このように、git-core をインストールするために必要なすべての port を調べ、それらを登録します。r コマンドで、現在登録されている port を、安全にインストールできる順に表示します。

> r
perl5.8 
perl5 
p5-error 
zlib 
pkgconfig 
curl 
gperf 
libiconv 
ncursesw 
ncurses 
expat 
gettext 
popt 
rsync 
openssl 
git-core 

さて、git-core の variants を指定してみましょう。ある port がどんな variants を持っているかは sv コマンドで調べます。

> sv git-core
git-core has the variants:
	doc: Install HTML and plaintext documentation
	gitweb: Install gitweb.cgi
	svn: Bi-directional subversion repository support
	bash_completion: Bash completion support

ここでは +doc+gitweb+svn+bash_completion とすべての variants を指定しましょう。もう一度 ap コマンドを、今度は variants を指定して実行します。

> ap git-core +doc+gitweb+svn+bash_completion
analyses dependencies of git-core...
analyses dependencies of curl...
analyses dependencies of pkgconfig...
analyses dependencies of zlib...
  (snip)
analyses dependencies of p5-svn-simple...
analyses dependencies of subversion-perlbindings...
analyses dependencies of p5-term-readkey...
analyses dependencies of bash-completion...

沢山追加されたので省略しちゃいました。この時点での安全なインストール順序は r コマンドで確認できます。

> r 
ncursesw 
ncurses 
readline 
sqlite3 
  (snip)
serf 
cyrus-sasl2 
subversion 
popt 
  (snip)
subversion-perlbindings 
p5-svn-simple 
bash-completion 
git-core +doc+gitweb+svn+bash_completion

長いので省略しましたが、最後の git-core の行で指定した variants が表示されていることに注目してください。+svn の影響で subversion がリストに加わりました。しかし、variants が指定されていません。そこで、subversion にも variants を指定しましょう。

> ap subversion +mod_dav_svn+tools+bash_completion
analyses dependencies of subversion...
analyses dependencies of apache2...
analyses dependencies of apr...
analyses dependencies of apr-util...
  (snip)
analyses dependencies of gettext...
analyses dependencies of serf...
analyses dependencies of cyrus-sasl2...
analyses dependencies of bash-completion...

最後に、インストール順序を確認しましょう。

> r
ncursesw 
ncurses 
readline 
sqlite3 
  (snip)
serf 
cyrus-sasl2 
bash-completion 
subversion +mod_dav_svn+tools+bash_completion
  (snip)
p5-libwww-perl 
subversion-perlbindings 
p5-svn-simple 
git-core +doc+gitweb+svn+bash_completion

subversion に +bash_completion を指定したことによって、bash_completion の位置が上がっていることに注目しましょう。tsort ライブラリは便利です。

現在のバージョンでは、既に依存関係を調査し終えている port に対して、何度も依存関係を調べてしまうので少しムダがあります。それから r の出力を直接パイプできたら嬉しいですよね。誰かやってくれないかなぁ。