cvs commitinfo で起きた問題2006年08月30日 11時40分44秒

cvs を使っていたら、以下のようなエラーが出た。症状としては、かなり深刻な被害をもたらすこともありうる件である。

cvs client: refetching unpatchable files
cvs update: warning: include/some.h was lost
U include/somefile.h
cvs update: warning: src/another.c was lost
U src/another.c 

ファイルの内容が cvs の予期している内容と異なってしまった為に、アップデート用のパッチが当たらなくなってしまった為に、ファイル全体を再取得している。こうなると、もしローカルでこのファイルを編集していた時に、変更ごと破棄されて、最新の CVS のリビジョンを取得することになってしまう。もし変更した量が多かったら、大変なことになってしまう。

実は、commitinfo を CVSROOT に追加したためだった。commitinfo は cvs の commit をやった時に、RCS ファイルが更新される直前に、実行されるプログラムを書いたものだ。

実は、一部の特殊文字が少々問題を起こすので、commitinfo を使って、文字コードの変換をしていたのだ。それが諸悪の根源だった。

nfs 上の cvs レポジトリを含め、ローカルにレポジトリがある場合は問題ないのだが、pserver を使った場合には問題が発生し使えなかった。rsh や ssh では、試していないので現状がどうだか判らない。

pserver を使っている場合、cvs commit の時に、ファイルが一度、サーバの /tmp に複写される。commitinfo で起動されるプログラムは、この /tmp に複写されたプログラムに対して、動作する。その後に、RCS 形式で、ファイルの履歴が取られるのだ。それ故、commitinfo でファイルを編集すると、/tmp のファイルが更新されることになる。もとの、cvs クライアントに残っているファイルは編集前のものだ。

それ故、cvs が各ワークエリアで管理しているリビジョン番号は正しいのに、内容は異なる状態になる。その後に、誰か他の人が commit をする。その後に、cvs update をやるとパッチ形式で、他の人の変更点が送られてくるのだ。残念ながら、ここにあるのは特殊文字を処理する前のもので、パッチは処理後からの変更を送ってくる。それ故、パッチが当たらなくなり、ファイルを破棄して再取得する。

これがローカルにあるレポジトリに対してだと、commitinfo から実行されるプログラムは、直接ワークエリアにあるファイルに対して実行される。それ故、ファイルの不整合が起きないのだ。