[目次へ][6章へ][6.3へ][6.5へ] 最終更新:$Date: 2002/09/29 14:59:48 $

ここは、あと更新用スクリプトのバージョンアップと、実テスト。くらい…多分。


■■[6.4] 作業コピーを自動更新してみよう
■■■[6.4.1] 例えばWebページを自動更新したいとしよう?
■■■[6.4.2] 自動更新スクリプトの設置
■■■[6.4.3] 作業コピーをホームページに
■■■[6.4.4] 別の作業コピーで自動更新のテスト


■■6.4 作業コピーを自動更新してみよう

誰かがコミットした時に、どこかに置いてある作業コピーを自動更新したいときがあります。作業コピーはWebページかもしれませんし、コンパイルできるかチェックするためのものかもしれません。commit作業のメイン部分の完了時に外部プログラムを呼び出す設定はloginfoかmodulesでするということを説明しました。

loginfoを使うといろいろな処理が可能ですが、この目的ではそこまでの処理は必要ありません。サブディレクトリで動作を変えたいとか、コミットされたファイルをチェックして何か処理をさせたいとかいう場合には、loginfoを使うべきです。対象となるファイルひとつひとつ、サブディレクトリひとつひとつに細かい制御が必要でないのなら、modulesを使うのが、サブディレクトリへのパターンマッチなどを考える必要が無いので、簡単です。ただ、modulesの設定変更の反映には、放棄とチェックアウトが必要なのが不便だったりはします。

loginfoの話は第7章のコミットメールのところで説明しますので、ここではmodulesでの設定例を紹介します。

■■■6.4.1 例えばWebページを自動更新したいと思わない?

まず、自動更新させるための作業コピーを用意します。そうですね、例えばWebページをCVS管理下におき、公開領域に作業コピーを置くと仮定します。Webページのディレクトリは/home/pozzy/public_htmlだとします。

もし既にいくらかWebページを作ってしまっているなら、暫定的な作業スペースを用意して、public_htmlにあったファイルをコピーしてきて整理します。中にはCVSの管理下に置きたくないファイルがあるかもしれません。シンボリックリンクは後で張ることにして、削除してしまいましょう。

整理が済んだら、そのディレクトリ内でモジュールを登録します。GIFファイルやJPEGファイルなど、バイナリファイルが含まれている場合には、忘れずに-Wオプションで指定しましょう(cvswrappersで既に指定されている場合には必要ありません)。モジュール名はなんでもよいのですが、ひとまずpozzyhpとでもしましょうか。これまでの処理は、おおむね次のようになるでしょう【図6.4.1】。

【図6.4.1】前準備
▼
% cd /home/pozzy; mkdir tmp; cd tmp
% (cd /home/pozzy/public_html; tar cpf - .) | tar xpf -

(整理する)

% cvs -d /home/cvsroot import -W "*.gif -k'b'" -W "*.GIF -k'b'" -m "Pozzy's homepage" pozzyhp pozzy POZZYHP_1
% cd /home/pozzy
N pozzyhp/index.html
N pozzyhp/intro.html
cvs import: Importing /home/cvsroot/pozzyhp/images
N pozzyhp/images/BACK403.GIF
N pozzyhp/images/myphoto.gif

No conflicts created by this import
▲

これで、ひとまず前準備は済みました。次は、このモジュールがcommitコマンド実行時に自動更新されるように設定します。

■■■6.4.2 自動更新スクリプトの設置 ※入れ替えあり

この手の自動更新は頻繁に使いそうなので、【図6.4.2】のようなperlスクリプトを用意してみました。

【図6.4.2】自動更新スクリプト(CVSROOT/auto_update.pl) [auto_update.pl]
▼
#!/usr/bin/perl
# cvs path
$cvs = '/usr/bin/cvs';
$update = 'update -P -d';
$usage = "usage: auto_update.pl WORKDIR [MODE]";

# process arguments
die $usage, "\n" unless $workdir = $ARGV[0];
$chmod = $ARGV[1] ? "; chmod -R $ARGV[1]" : "";

# main update process which must be execute in background.
$cmd = "(cd $workdir; $cvs $update $chmod) &";
system($cmd);

# last message.
$date = `date`; chomp($date);
$mesg = "$workdir automatically updated at $date";
print "$mesg\n";
▲

一番つまずく可能性があるのは、updateコマンドをバックグラウンド実行しなければいけないというところです。このプログラムが呼び出されるcommitの実行中には、ディレクトリにロックがかかっており、updateコマンドを実行することができません。実行しようとすると、ロック解除を待って止まってしまうのですが、commit動作そのものもそこで止まってしまい、結果永遠に待ち続けることになります。これを回避するためには、updateコマンドをバックグラウンドで実行することでプログラムの実行から切り離し、プログラム本体が終了した後にupdateコマンドが実行されるようにしましょう。これが、【図6.4.2 11行目】の最後に「&」がつけられている意味です。【図6.4.2 11行目】自体は「作業コピーのディレクトリに移動して、cvs updateコマンドをバックグラウンド実行せよ」という意味の文字列です。実際の実行は次の【図6.4.2 12行目】でsystemという関数を呼び出すことでおこなっています。

プログラムの他の部分は、最初の【図6.4.2 1-4行目】が環境および変数の設定、【図6.4.2 6-8行目】が引数の処理、【図6.4.2 14-17行目】までが最後のメッセージ出力です。環境および引数の設定については、各自の環境に合わせて変更してください。第1引数は作業コピーのディレクトリでなければなりません。これは必須で、無い場合は実行されません。第2引数はあってもなくてもよいのですが、更新後に作業コピーのファイル属性を変える必要がある場合には、ここに指定することで再帰的に変更されます。このスクリプト程度では指定する必要はないでしょう。最後のメッセージ部分は、もっと改良すると楽しいかもしれません。例えば、引数にメールアドレスを指定できるようにして、自動更新を通知することもできるでしょう。

Clumn 自動更新スクリプト =====================================================================================

もっとよいスクリプトがあるかもしれませんし、内容が理解できれば簡単なので自分で作ってもよいでしょう。漢字コード変換パッチをあてると、loginfoに以下の自動更新用コードが追加されたりします。

▼
#^www (date; cat; (sleep 2; cd /usr/local/www/data; cvs -q update -d) &)>>$CVSROOT/CVSROOT/updatelog 2>&1
▲

===========================================================================================================

このスクリプトはどこに置いても構わないのですが、筆者の単なる趣味で、CVSROOTに管理ファイルとして登録します。登録する前に、実行権がついていることを確認し、なかったら設定しておきましょう。後で使います。実行権を確認したら、6.1.3節で説明されたように、checkoutlistにこのファイルを加えて、CVSROOTに追加登録します【図6.4.3】。

【図6.4.3】auto_update.plを管理ファイルとして追加する
▼
% cat >> checkoutlist
auto_update.pl Auto updater auto_update.pl cannot be retrieved
% cvs add -m "Auto updater" auto_update.pl
cvs add: scheduling file `auto_update.pl' for addition
cvs add: use 'cvs commit' to add this file permanently
% cvs commit -m "Add auto_update.pl" auto_update.pl checkoutlist
RCS file: /home/cvsroot/CVSROOT/auto_update.pl,v
done
Checking in auto_update.pl;
/home/cvsroot/CVSROOT/auto_update.pl,v  <--  auto_update.pl
initial revision: 1.1
done
Checking in checkoutlist;
/home/cvsroot/CVSROOT/checkoutlist,v  <--  checkoutlist
new revision: 1.3; previous revision: 1.2
done
cvs commit: Rebuilding administrative file database
▲

ls -Fしてauto_update.plができていれば成功です【図6.4.4】。実行権をつけるのを忘れて登録した場合には、chmod +xでauto_update.plとauto_update.pl,vにつけておいてください。

【図6.4.4】auto_update.plを管理ファイルとして追加する
▼
% ls -F /home/cvsroot/CVSROOT
CVS/               commitinfo     editinfo,v  notify     val-tags
Emptydir/          commitinfo,v   history     notify,v   verifymsg
auto_update.pl*    config         logfile     passwd     verifymsg,v
auto_update.pl,v*  config,v       loginfo     rcsinfo
checkoutlist       cvswrappers    loginfo,v   rcsinfo,v
checkoutlist,v     cvswrappers,v  modules     taginfo
commandlog.pl      editinfo       modules,v   taginfo,v
▲

なお、modulesを使って外部プログラムとして呼び出す場合には、外部プログラムに引数を渡すことができません。なので、【図6.4.5】のようなラッパー(wrapper=包むもの)を作成して、これをプログラムとして指定することにします。たとえば、/home/pozzy.bin/update.shなどにおきます。シンボリックリンクの張り直しなど、固有の動作もここで実行するように書くこともできると思います。

【図6.4.5】modules登録用ラッパー(/home/pozzy/bin/update.sh)
▼
#!/bin/sh
/home/cvsroot/CVSROOT/auto_update.pl /home/pozzy/public_html
▲

なお、ここではローカルなリポジトリを考えて上記のような構成としましたが、遠隔にあるリポジトリへの自動更新も、自動更新スクリプトをCGIとして作成すれば、リポジトリ側からそのCGIを呼び出して実行し、自動更新をおこなわせることが可能かと思います。そうすることができれば、例えばプロバイダに容量制限がある場合でも、どんどん増殖していくリポジトリを他へ移すことができるわけです。今のところ用がないので作ってはいませんが、CGIはちょっと作ってみてたりします。

さて、このラッパーをmodulesに登録します【図6.4.5】。これをCVSROOTにコミットすれば、設定は終わりです。次は本当に動いているかテストしてみましょう。

【図6.4.6】modulesに設定する
▼
pozzyhp -i /home/pozzy/public_html/bin/update.sh pozzyhp
▲

■■■6.4.3 作業コピーをホームページに

登録が済んだら、public_htmlを一旦退避し、pozzyhpをチェックアウトし、public_htmlに改名します【図6.4.7】。そして、シンボリックリンクや管理下に置かなかったファイルを足したりする後処理をします。-dオプションを使ってチェックアウトした場合、modulesの登録がうまくいかないかもしれません(1.11.1p1の場合。バグ?)。

【図6.4.7】さて、ホームページをすげ替えよう
▼
% mv public_html public_html.bak
% cvs -d /home/cvsroot checkout pozzyhp
cvs checkout: Updating pozzyhp
U pozzyhp/index.html
U pozzyhp/intro.html
cvs checkout: Updating pozzyhp/images
U pozzyhp/images/BACK403.GIF
U pozzyhp/images/myphoto.gif
% mv pozzyhp public_html

(後処理をする)
▲

なお、CVSディレクトリにCheckin.progができていることを確認しておけば完璧です。

■■■6.4.4 別の作業コピーで自動更新のテスト

さて、ここでどこでもいいですから別の所(別の場所であれば、遠隔でも構いません)に、pozzyhpの作業コピーを取り出します【図6.4.6 1行目】。そして、適当に編集して、commitします【図6.4.8 4行目】。途中の出力はどうでもよいので省略しますが、【図6.4.8 8行目】に「/home/pozzy/public_html/bin/update.shを実行した」というメッセージが表示されていることに注目してください。次にスクリプトの最後で出力するようにしていたメッセージが出力されています【図6.4.8 9行目】。

これで最後のはずですが、プロンプトが表示された後で、何も入力していないのに、updateが実行された時のメッセージが出力されるはずです【図6.4.8 10-14行目】。これがバックグラウンドで実行されて、ロックが解除されるのを待っていたupdate実行プロセスが、commitの終了を確認し、処理を再開した証拠というわけです。

【図6.4.8】自動更新のテスト
▼
% cvs -d /home/cvsroot checkout pozzyhp
% cd pozzyhp

(編集)
% cvs commit -m "fix bug in index.html and add mailto to intro.html"
cvs commit: Examining .

(中略)

done
cvs commit: Executing ''/home/pozzy/bin/update.sh' '/home/cvsroot/pozzyhp''
/home/pozzy/public_html automatically updated at Thu Aug 29 23:29:50 JST 2002
% cvs update: Updating .
U index.html
U intro.html
cvs update: Updating images
▲

このようにcommitコマンド実行時の更新が自動化できることがわかりました。