普通のCGIとしてbzr+httpプロトコルに応答

レンタルサーバーでbzrを使いたい!という話。

bzrは、ftp越しに書き込みもできます。できますが、転送効率も考えて*1やはり格好良くbzr+httpプロトコルを使いたいところです。
PythonVCSの雄hgは、hgweb.cgiを普通に設置するだけで、http越しのclone、pushがサポートされます。対するbzr-smart.pyは、FastCGIか、mod_pythonが必要なように書かれています。さくらのライトプランではFastCGImod_pythonも使えないため、困ります。

http://doc.bazaar-vcs.org/latest/en/user-guide/index.html#serving-bazaar-with-fastcgi

ところが、これを普通のCGIとして設置することで、bzr+http://でbranch、pushができてしまいましたので、ここにメモっておきます。

bzrはあらかじめsetup.py install --home=~/bzrしておきます。ライトプランではtelnetは使えませんが、展開後のファイルとsetup.pyを実行するスクリプトをアップロードして、スクリプトCGIとして叩けばどうにでもなります。

構造はこうなります。

  • repository (親ディレクトリ)
    • .htaccess
    • .htpasswd
    • bzr-smart.cgi (下記参照)
    • fcgi.py (bzrのドキュメントに書かれたリンク先から取ってくる)
    • my-branch (bzr initしたリポジトリを丸ごとアップロード)

リポジトリ本体も、HTTP越しに見えるところに置いておかないと、jailなんとかってエラーになります。

bzr-smart.cgi

#!/usr/bin/env python

import sys
sys.path.insert(0, "/home/myaccount/bzr/lib/python") #bzrをインストールした位置/lib/python

from bzrlib.transport.http import wsgi
import fcgi

smart_server_app = wsgi.make_app(
    root='/home/myaccount/www/repository/', #リポジトリの親ディレクトリの絶対パス
    prefix='/repository/', #ドキュメントルートからの相対パス
    path_var='REQUEST_URI',
    readonly=False, #書き込みを許可
    load_plugins=True,
    enable_logging=True)

fcgi.WSGIServer(smart_server_app).run()

このファイルをCGIとして設置し、実行権限を付けておきます。アクセスして404になることを確認。Webからの閲覧機能は無いため404でOKです。

.htaccess

RewriteEngine on
RewriteRule ^.+/\.bzr/smart$ bzr-smart.cgi

<Limit POST PUT>
Require valid-user
AuthName "てきとう"
AuthType Basic
AuthUserFile /home/myaccount/www/repository/.htpasswd
</Limit>

ライトプランでも、幸いにしてmod_rewriteは使えますので、リポジトリ/.bzr/smartへのアクセスを、bzr-smart.cgiで処理するようにします。
POSTやPUTには認証もかけておきます。bzr+httpプロトコルは常にPOSTでアクセスを行いますので、これはbzr+httpプロトコル全体への認証となります。つまりpushだけ認証するといったことはできません。そもそもbzrは通常のhttp越しでもbranchを行えますので、httpは読み取り専用、bzr+httpは書き込み権有りといった使い分けを行います。もしbzr+httpを使って読み取り専用で公開したい場合はreadonly=True。

これで、bzrクライアントを使ってアクセスできるようになります。

% bzr branch http://.../repository/my-branch/ local-dir #公開用
% bzr branch bzr+http://.../repository/my-branch/ local-dir #自分用
% bzr push bzr+http://.../repository/my-branch/ #書き込み

*1:測定したわけではないですが、bzrのリポジトリの主流はpacked形式なので、ftp経由で書き込むのは効率悪い予感がします。予感だけ。