ビルドログ保持/分析ポリシのメモ

軽い気持ちで考えてたけどコレ意外と難しいぞ。。

やりたいこと

  • "コンパイラ警告が出現したコミットをO(1)で特定する"
  • → 全リビジョンをビルドしてコンパイラ警告を保存しておき、行番号情報を除いた上でそのblameを取る

しかし、現状の開発はGitでやっているので当然マージ等も発生し、"全リビジョンのビルド"自体が現実的にはできない。もっと悪いのはlibpngのような外部ライブラリをリポジトリにマージの形で抱えていることで、当然libpng等の変更をいちいちビルドしていたらいくらお金があっても足りないのでビルドの間引きはどうしても考える必要がある。
最新版のビルド警告だけを保持してblameだけで良い? → ダメ。警告の出現タイミング != ソース行の導入タイミング。ヘッダやプラットフォームSDK自体の非互換修正、ツールチェーンの更新等によって新たに警告が出現するのはよくあること。

履歴の分類(Main/Sub)による直線化ヒストリの定義

まず、マージによって導入される変更を細かく追うのは諦める。
Gitのようなバージョンコントロールシステムの履歴はDAGになるが、このうち"左側"の履歴だけをMain historyと呼び、そうでない履歴をSub historyと呼ぶことにする。Gitではマージの左右の概念が無いが、一般的には左がMainというかpublicにpushされていたリビジョンになることが多いように思う。残念ながらGitはrefにログが無いのでマージが有った場合履歴の左右どちらがメジャーなのかを決定するための情報が無い。(GitHubのNetwork graph https://github.com/ashinn/chibi-scheme/network はおそらくpush履歴を使用しているのではないだろうか。)
Sub historyはビルドログ自体を保持しない。このため、Sub history側で新規に増えたコンパイラ警告は、Main historyと交差するマージコミットにattributeされることになる。しかし、Sub history側のblameによって結果を近似できる可能性がある。
一方、Main historyは全リビジョンをビルドする。Main history、ようするにメイン開発者である自分のコミットは全リビジョンをビルドするのは現実的と言える -- そもそもCIしているので常に達成されている。Main history直線になるという重要な特徴がある。Gitはファイルヒストリを持たないためこのようにしてシミュレートしてやる必要があるが、SubversionのようなVCSでは、ancestryとしてこの概念を直接的に持っている(マージは後付けで付与された機能であり、本来のリポジトリフォーマットとしては、あるファイルには高々1つの祖先が常に存在する)。
この分類の導入によって、"Main historyはパーフェクト、Sub historyはblameによる近似"という目標に再設定できる。

取り組む課題

Main/Sub historyの概念の導入で問題が多少シンプルになった。次に取り組む課題としては、
blameメタデータをGitリポジトリに突っ込むフォーマットを考える。blameをO(1)またはそれに近いパフォーマンスにするためには、blameデータのキャッシュが必須になる。Gitはまぁまぁの品質のデルタ圧縮をコンテンツに対して行えるため、blameデータ自体もテキストデータにしてGitリポジトリにしておけば、容量を節約しつつデータベースとして機能させることができる。はず。
ホワイトスペースの扱いコンパイラ警告の出現場所の特定という意味では、(Pythonのようなホワイトスペースが意味を持つ言語を除くと)ホワイトスペースの変更はblameに影響させないのが望ましい。しかし、ホワイトスペースの変更自体もそこまで頻繁に起こるものでもないので、ヒューリスティクスの失敗ということで無視してしまっても良いかもしれない。
Sub historyの漸近的な解決。バグを追うようなケースで、sub historyをビルドしたいようなケースも考えられる。その結果をblameデータリポジトリに投入するためにはどのようなフォーマットが考えられるだろうか?
revert処理のモデリング = 行編集モデルの拡張。Revertによって一旦削除された行を再導入した場合、警告の発生したリビジョンも実際に書かれたリビジョンに戻したい。このためには、現在 "新規"/ "削除" の2操作しか存在しない編集モデルに、"復帰"を導入する必要がある。おそらく、他ファイルへのコピーのような操作も拡張できるだろう。