[CVS超入門] [CVSエラー対処]

▼CVS エラー対処

$Id: cvs-err.html,v 2.16 2016-12-23 16:44:01+09 kabe Exp $


リポジトリはどこすか

	% cvs checkout ...
	cvs checkout: No CVSROOT specified!  Please use the `-d' option
	cvs [checkout aborted]: or set the CVSROOT environment variable.

書いてある通りです。(英語読め。)

複数のリポジトリを使い分けている人は当然 CVSROOT環境変数は 設定してないでしょうから、cvs -d リポジトリ を明示します。

cvs update --help とかでも CVSROOT を要求されるのは なんとなく納得いかないが…

リポジトリじゃないっす

	% cvs checkout ...
	cvs [checkout aborted]: /repository/here/CVSROOT: No such file or directory

リポジトリには必ず CVSROOT/ ディレクトリがあるので、 リポジトリ指定を間違えた、てのが教科書的回答ですが、

cvs init をまだ実行していない
のがもっともありがちな場合でしょう。

CVS関係の解説やCVS自身が吐くエラーでは、 環境変数の CVSROOT と リポジトリ中の CVSROOT/ ディレクトリと リポジトリという意味で CVSROOT と書くことが ごっちゃになっていることがあります
が慣れるしかないような。


衝突しているからmergeせよ (import時)

ベンダから新版が出た。早速、ベンダ枝に import してみました

	% cvs import projX VENDOR REL_3
	...
	U projX/Makefile
	C projX/hello.c

	1 conflicts created by this import.
	Use the following command to help the merge:

		cvs -d path/to/CVSrepos checkout -jVENDOR:yesterday -jVENDOR projX

これは、(自分で改造している)幹ですでにcommitがあって、デフォルト枝が ベンダ枝から 1.x に戻っている ファイルに対して報告されます。 import に際し、なにか失敗があったというわけではないので安心してください。 import は正常に行われています。

ベンダ版からいじっているファイルが大量にあると、この conflict も 大量に出ます。 全ファイルのデフォルト枝をリセット していると、全部のファイルでconflictが報告されます(壮観)。

最後に出てきている cvs コマンドは、 「ベンダ側で行われた修正を取り込むにはこうするといいかも」程度のものです。 修正によっては闇雲にやらないほうがいいかもしれません。

作業領域にベンダ枝の変更を取り込むには 「前回のベンダ枝の点」→「今回のベンダ枝」 な変更を -j で取り込みます。

通常は、前回のベンダ枝の import 時に指定した点タグ (上ではREL_2と思われる) があるはずなので、

	work% cvs update -jREL_2 -jREL_3
	もしくは
	work% cvs update -jREL_2 -jVENDOR	#VENDORは枝タグなので、最新版を指す
この場合、「前回のベンダの点」は、作業領域なり現在の枝なりに 最後に取り込んだベンダ版です。今まで一回も取り込んでいない場合は 一番最初のimportで指定した点タグ (REL_1 とか 1.1.1.1)になります。

この -j による修正取り込みが、「ベンダの追っかけ」。
追っかけを行った後は、「今の幹は REL_3 の変更を取り込んだ」 という事実を 人間が覚えておく 必要があります。 でないと次回の追っかけ取り込み時に -j に何を書いたらいいかわからず 往生します。 間違えると、同じベンダ修正を2回適用するといった悲劇が。

邪魔だ、まずどかせ

	% cvs update -A -C
	cvs update: Updating .
	cvs update: move away Makefile; it is in the way
	C Makefile
	cvs update: move away my.c; it is in the way
	C my.c

一番ありがちと思われるのは、非CVSだった作業領域に むりやり上書きcheckout/updateしようとしたときとか。

とりあえず解決するには rm Makefile などとして 問題のファイルを消してから update すればよろし。 該当ファイルが RCS管理下だったのあれば、rcscleanで 消すほうが安全でしょう。

(結局のところ非CVS作業領域では 全部消さないと CVSでの操作はできない)

ソースを読んでもどういう時にこのエラーが出るのかよくわからんですが、 とりあえずこんな条件がそろうと文句を言われるようで…

このエラーについては、「わかりにくい」と src/client.cの注釈部分(!)に書かれているくらいで、 原因や何をすべきかがわかりにくい。 大文字小文字が縮退するファイルシステムで名前衝突したときも起こるようです。 (実際はclassify.cから出されていることの方が多い)


ロック解放待ち

cvs commit でエディタを起動している最中に、 変更点を思い出すため ^Z(suspend) で抜けるなり 他のウィンドウで cvs diffをすると

	% cvs diff main.c
	cvs diff: [06:07:08] waiting for user's lock in CVSROOT/src/main.c
	_
…でそのまま黙り込みます。^Cで抜けられますが。

◇原因

commitしている最中は、他の人がcommitするのを防ぐために リポジトリにはロックがかかっています。

cvs diff でも ロックがかかります。 パッチを作るために diff っている最中はリポジトリが変動されると困るため。

したがって、 commitの真っ最中に cvs diffをするとロック待ちになります。

◇対策

こんな場合はそこまで厳密なことを要求してないので、 -n (リポジトリはいじらない) で逃げます。

	% cvs -n diff main.c
	Index: main.c
	.............


残ってしまったロック

普通の状況では起こりませんが、 cvs が Segmentation Fault などで異常終了してしまうと、 起動中の cvs コマンドがなくてもCVSROOT下にロックが残ったままになってしまいます。

	$ cvs commit openbsd-compat/xmmap.c
	cvs commit: [07:11:22] waiting for kabe's lock in /home/kabe/cvsroot/openssh/openbsd-compat
	^Ccvs [commit aborted]: received interrupt signal

他に起動中のcvsが無いことを確認して、 なお waiting for user's lock が出ているのであれば、 表示されているパス以下のロックファイルを探して手動で消します。

	$ find ~/cvsroot -name '#*'
	/home/kabe/cvsroot/openssh/openbsd-compat/#cvs.rfl.vega.pgw.jp.22053
	$ rm /home/kabe/cvsroot/openssh/openbsd-compat/#cvs.rfl.vega.pgw.jp.22053


リポジトリが先へ進んでいる

commitは成長点に対してだけ 可能なので、リポジトリ側が(他人によって)更新されていて先に進んでいる場合、 commitすると怒られます。

	% cvs commit template.html
	cvs commit: Up-to-date check failed for `template.html'
	cvs [commit aborted]: correct above errors first!
	%

commitは、作業領域の「元の版」(-rBASE) に対して 行われますが、 リポジトリが先に進んでいると成長点である仮想タグ HEADが先に進み、BASEは成長点ではなくなります。

% cvs stat template.html
===================================================================
File: template.html     Status: Needs Patch
                           /これがBASE
   Working revision:    1.2     Wed Mar 30 04:45:15 2005
   Repository revision: 1.3     /home/cvs/CVSroot/projectY/template.html,v
                           \これがHEAD

◇対策

正しい方法は、まず cvs update して作業領域をHEADへ移してから cvs commit する。

cvs update での影響を知りたいなら、 cvs diff -rBASE -rHEAD [filename] で出るdiffでアタリをつけます。


ファイルを消した

ファイルを rm で消しただけで cvs remove をしていないと、commit時に

% cvs commit
cvs commit: Examining .
cvs commit: Examining htdocs
cvs commit: Examining htdocs/input
cvs commit: Up-to-date check failed for `htdocs/input/getid_02.php'
cvs [commit aborted]: correct above errors first!
% _
ファイル数が少ないうちはエラーがあるとわかりますが、 多いと大量の Examining ... に埋もれてしまい、 一番最後に出てくる「直せ!」の原因がわかりにくい場合もあります。

該当ファイルを cvs status すると Status: Needs Checkout と表示されるので、CVS的には 「リポジトリにはあるファイルが作業領域にない。updateしておくべきじゃないの?」と 認識されているわけです。 cvs -n update でも同様の warning が出ます。

% cvs -n update
cvs update: Updating .
cvs update: Updating htdocs
cvs update: Updating htdocs/input
cvs update: warning: htdocs/input/getid_02.php was lost		#from working directory
U htdocs/input/getid_02.php
% _
cvs update で -n をつけていないと、 せっかく消したファイルが復活 します。状況がわからないうちは -n で 様子を見ましょう。

cvs remove ファイル してから再度 commit すればOK。 該当ファイルがたくさんあるなら、上のディレクトリで単に cvs remove (引数なし) でも 一応該当ファイルは全部処理してくれます。 消したくないファイルが消えていた場合も消されるので、ファイル名を 指定しない cvs remove は要注意。

なお、CVSでは cvs remove で消したファイルは完全に消えるわけではなく、 リポジトリの Attic/ に収容されるので、古い版は消えずに取り出せます。

逆に、知らないファイルに対し Needs checkout や was lost と言われているなら、 他の人がリポジトリにファイルを追加したということですので、 cvs remove してはいけません。おとなしくupdateで自分の作業領域に 追加します。 (removeしたら殺されます)


リポジトリにファイルがない

普通の使い方をしていれば起こらないのですが、 リポジトリのファイルを直接消すといった 操作で、作業領域とリポジトリとでファイル存在に食い違いがあると

	% cvs -n update
	cvs update: Updating .
	cvs update: `munin.apcupsd' is no longer in the repository
	% _

メッセージからはエラーなのかWarningなのかわかりませんが、単なる noticeです。 一度 update すれば消えます。

	% cvs update munin.apcupsd
	cvs update: `munin.apcupsd' is no longer in the repository	#まず通知

	% cvs update munin.apcupsd
	cvs update: nothing known about `munin.apcupsd'			#次からは何も出ない
	% _

逆に言えば、 「リポジトリからは消したが、作業領域にはしばらく残しておきたい」 場合は、cvs update してはいけない ということになります。 作業領域のCVS/Entries を直接いじって、 該当ファイルのエントリを消します。


作業領域にもリポジトリにもファイルが無いが、形跡はある

普通の使い方では起きませんが、 import したあとのゴミ掃除などで

してからupdateすると、./CVS/Entries には エントリがまだ残っているので、痕跡の旨のメッセージが出ます。
	% cvs -n update
	cvs update: Updating .
	cvs update: warning: TMP.html is not (any longer) pertinent

warning ですが、 正常に./CVS/Entriesから消され、 2回目以降のupdateではメッセージは出ません。 性質的には is no longer in the repositoryのメッセージと同じ。


リポジトリにファイルがないが、変更済ファイルがある

上と同じく通常の状態では起こりませんが、

と、cvs update しても修正ファイルは消えません。 変更があるということは、どこかに残したいかもしれないものであるため。
	% cvs update
	cvs update: Updating .
	cvs update: conflict: `main.cf.mailsv' is modified but no longer in the repository
	C main.cf.mailsv		#一応 Conflict として報告される
	% _

消してもよいことをCVSに教えるため、作業領域から明示的に rm してから cvs update して整合性をとります。

	% rm main.cf.mailsv		#自分で明示的に消して、不要なことをアピール

	% cvs update
	cvs update: Updating .
	cvs update: warning: `main.cf.mailsv' is not (any longer) pertinent	#1回目は通知が出る

	% cvs update
	cvs update: Updating .			#それ以降は何も出ない
	% _


リポジトリではディレクトリごと削除された

普通の使い方では起きませんが、 import したあとのゴミ掃除などで

と、 ./CVS/Entries にはエントリがまだ残っています。 が cvs -n update -dすると 分かりにくいエラーが出ます。

	% cvs -n update -dP
	cvs update: Updating .
	cvs update: Updating C2
	cvs update: cannot open directory /home/CVS/projx/C2: No such file or directory
	cvs update: skipping directory C2
	% _

恐ろしいことに単なる update では何もメッセージが出ません。 (バグ?)

	% cvs update -dP
	cvs update: Updating .
	% _

リポジトリのディレクトリを直接消した場合は、 各自の作業領域の CVS/Entries から、該当ディレクトリの情報を 消すしかないようです。

	::::::::::::::
	CVS/Entries
	::::::::::::::
	D/C2////		←これを手動で消す
	D/conf////
	...
作業者が他にいる場合は、「手動で消してね」と知らせる必要があります。 (∴公開リポジトリの場合はメーリングリストで周知する必要がある)


2000年以前の日付

% cvs -d ~/cvsroot checkout -d . PasswdBattler
cvs checkout: /home/kabe/cvsroot/PasswdBattler/passwdbattler,v: non-standard date format for revision 1.1.1.1 (1993.09.01.07.52.55)
...

普通の使い方では起きません。 リポジトリの *,v を直接いじって、 コミット日付を無理やり過去に戻したあとの初回の checkout 時に出ます。

なんでかはわかりませんが、2000年以前の日付は

date    93.11.01.05.26.29;  author yoshinov;  state Exp;
と、2000年問題非対応なフォーマットでないと警告が出るようです。 警告だけで、ファイルのタイムスタンプは正常に取り出されるし、 以降の cvs update では警告は出ません。


かべ@sra-tohoku.co.jp