Gentoo/FreeBSD で portage が動かない件
http://bugs.gentoo.org/show_bug.cgi?id=337465
3週間ほど前の version から portage が FreeBSD 上で動かなくなっています。レスポンスの速い portage のメンテナさんと問題解決すべく作業中…。
どうやって問題のポイントをしぼっているかを書いてみます。
git bisect
portage は git でバージョン管理されています。 git には git bisect という強力な機能があります。 簡単に言えば、バグを発生させた commit を二分木検索で見つけだす機能です。 今回はこれを使いました。
$ git bisect start HEAD v2.2_rc60 -- $ git bisect run ./pym/portage/tests/runTests
まず、 "git bisect start
すると、 git が勝手にその中間を checkout してきます。ここで手動でテストして OK なら "git bisect good", だめであれば "git bisect bad" としてやっていきます。 good, bad をつけるたびに git が自動的に次にテストするべき位置を checkout します。
しかし、ここでは ./pym/portage/tests/runTests というテストスクリプトがすでに存在しているので、これを使って bisect を自動化できます。 "git bisect run ./pym/portage/tests/runTests" とすると、指定されたプログラムが正常終了(返り値 が 0) の場合 "git bisect good" を、そうでない場合には "git bisect bad" が実行されていきます。(ちなみにビルドがそもそもできない、など commit が不完全な場合には 125 を返すことで、その commit を skip する(good とも bad ともつけない)ことができます。
こうやってしばらく待っておけば
ce6be8caaaba3151f6d7681180c21a6f2a756a40 is the first bad commit commit ce6be8caaaba3151f6d7681180c21a6f2a756a40 Author: Zac Medico <zmedico gentoo.org> Date: Thu Aug 19 22:56:26 2010 -0700 Make the make.globals path relative to EPREFIX, and add comments possible alternative behavior for target systems. :040000 040000 e2fa6633a30546ff05faba396365b8c0138671bd 5dcd2ca0cdf8525157632f49f57efcb45ea79032 M pym bisect run success
結果がでてきます。 この commit を詳しくみていってそのまわりを見ていけばバグの原因も見つけられることでしょう。
commit ce6be8caaaba3151f6d7681180c21a6f2a756a40 Author: Zac Medico <zmedico gentoo.org> Date: Thu Aug 19 22:56:26 2010 -0700 Make the make.globals path relative to EPREFIX, and add comments possible alternative behavior for target systems. diff --git a/pym/portage/package/ebuild/config.py b/pym/portage/package/ebuild/config.py index 46cac3b..2f886fc 100644 --- a/pym/portage/package/ebuild/config.py +++ b/pym/portage/package/ebuild/config.py @@ -723,8 +723,30 @@ class config(object): self.configdict["env"] = LazyItemsDict(self.backupenv) # make.globals should not be relative to config_root - # because it only contains constants. - for x in (GLOBAL_CONFIG_PATH,): + # because it only contains constants. However, if EPREFIX + # is set then there are two possible scenarios: + # 1) If $ROOT == "/" then make.globals should be + # relative to EPREFIX. + # 2) If $ROOT != "/" then the correct location of + # make.globals needs to be specified in the constructor + # parameters, since it's a property of the host system + # (and the current config represents the target system). + global_config_path = GLOBAL_CONFIG_PATH + if eprefix: + if target_root == "/": + # case (1) above + global_config_path = os.path.join(eprefix, + GLOBAL_CONFIG_PATH.lstrip(os.sep)) + else: + # case (2) above + # For now, just assume make.globals is relative + # to EPREFIX. + # TODO: Pass in more info to the constructor, + # so we know the host system configuration. + global_config_path = os.path.join(eprefix, + GLOBAL_CONFIG_PATH.lstrip(os.sep)) + + for x in (global_config_path,): self.mygcfg = getconfig(os.path.join(x, "make.globals"), expand=expand_map) if self.mygcfg:
ちなみに今回の場合、この変更で make.global から読みこまれていた設定が読みこまれなくなっていました。この設定が今まではうまく根本のバグが隠蔽していたようです……。根本のバグの原因はいまだに見つかっていません… orz