(English)
Based on r872564 (partially updated about cvs2svn)
CVSユーザを乗っ取ること。より正確に言うなら、CVSに良く似た、でも多くの問題点が修正されている、新しいバージョンコントロールシステムを開発している。 詳細はプロジェクトのフロントページを参照のこと。
いや、Subversionはオープンソースでありフリーソフトウェアだよ。 CollabNetは、何人かのフルタイム開発者へ給料を払っていて、コードのコピーライトをもっているけど、でもそのコピーライトは、Debian Free Software Guidelinesへ完全準拠なApache ライセンスだ。 言い換えれば、ダウンロードや改変、そして再配布は、あなたが望むように、自由に行える。 CollabNetや他の人に許諾を得る必要はない。
はい、全くもって。 重要プロダクトで十分使えるよ。
Subversion は2000年から開発が続けられていて、1年を過ぎた頃から、自分自身をホストできるようになった。我々がα版と宣言した年の1年後には、Subversionは、プライベートな開発者や実際の業務など、既に数多くの場所で使われるようになっていた。 その時から、2年以上をバグ修正と安定化に費やし、1.0になったんだ。 他のプロジェクトでは、もっと早い段階で「1.0」って宣言するじゃないかと思う。 でも我々はその名称を使うのを、意図的に、出来るだけ引き伸ばそうと決心した。 多くの人々がSubversionが1.0 になってから使おうと考えていることも、そのバージョン名が非常に特別な意味を持っている事にも気がついていたからだ。 だから、この規律を守り続けたんだ。
クライアントとサーバは、最大、1世代のメージャーリリースバージョンを跨がない限り動作するように設計されている。 例えば、1.Xクライアントは、1.Yのサーバとともに動作するだろう。 但し、クライアントとサーバのバージョンが一致しない場合には、何らかの機能が使えないかもしれない。
クライアントとサーバの相互接続性ポリシーに関しては、Subversion Community Guideの「Compatibility」セクションに書かれている。
最近のUNIXや、Win32、BeOS、OS/2、MacOS Xで動作する。
Subversionは ANSI C で書かれていて、APR(Apache Portable Rutime Library)をポータビリティ実現の為に使っている。 Subversionクライアントは、APRを稼動可能なOS上ならば何処ででも動作するだろうから、多くの環境で使うことが出来る。 Subversionサーバ(つまり、リポジトリ側)についても同様だけど、Win9xプラットフォーム(Win95/Win98/WinME)では、Berkeley DBリポジトリを使うことは出来ない。 これは、Win95上の Berkeley DB に、shared-memory セグメント問題が存在するためだ。(version 1.1から導入された)FSFSリポジトリにはこの制約は存在しない。 しかし、Win9xのファイルロックサポートの制限により、こちらもWin9x 上では、動作しない。
整理すると、Subversionクライアントは、APRが動作するプラットフォーム上でならばどこででも動作する。 Subversionサーバも、APRが動作する全てのプラットフォームで動作するが、Win95/Win98/WinMeではリポジトリを提供することは出来ない。
いや違う。「Subversion Filesystem」は、OSに実装されているようなカーネルレベルのファイルシステムではない。 これはSubversionのリポジトリインターフェイスで、リビジョン間の状態が保持されているディレクトリツリーを保存する、という意味では、「版付けされたファイルシステム」と言える。 リポジトリへアクセスするプログラムを書くことは、他のファイルシステムAPIを使うプログラムを書くのと同じようなものだ。 大きな違いは、この特別なファイルシステムでは、書き込みが行われてもデータが失われない、ということ。 最新の状態を取得するの同様、古いファイルツリーの状態を簡単に取り出すことが出来る。
サーバの要求は多くの要素が関係してくる。 例えば、ユーザ数や、コミットを初めとするサーバ関連操作の頻度、リポジトリのサイズ、独自に設定したリポジトリフックの負荷などだ。 もし、Apacheを使っているならば、Apache自体がメモリ使用量の最大要因となるだろう。
同じサーバ上で動作している、他のアプリケーションを考慮に入れるのを忘れないこと。 例えば、リポジトリブラウザを使うのであれば、Subversion 自体とは関係なくリソースが必要になる。
一般的に行って、同等のCVSリポジトリと比べて、より少ないサーバメモリで済むことは期待して良いよ。
いや、Subversion は一連のライブラリセットで、コマンドラインクライアントが付属してくるんだ。 Subversionには2種類のサーバプロセスが存在する。 1つは svnserv。これは、小さなスタンドアロンプログラムで cvs の pserver に似ている。 もう1つは、mod_dav_svn という特別なモジュールと組み合わせて Apahce httpd-2.0 を使うやり方。 svnserve は独自のプロトコルを使うけど、mod_dav_svn は、WebDAV をネットワークプロトコルとして使う。 より詳しく知りたい場合には、Subversion Book の6章を参照のこと。
端的に言えば「違う」。
もう少し詳しく言うと、もし、リポジトリにアクセスしたいだけならば、Subversion クライアントを build しさえすれば良い。 もし、ネットワークから使えるリポジトリを提供したいならば、Apache2か「svnserve」サーバを設定しなければならない。
ネットワークからアクセス可能な Subversion サーバの設定方法に関しては、詳細が Subversion Bookの6章に書いてある。
いや、Subversion サーバとして svnserve を利用すればよい。 十二分に動いてくれるよ。
もし、WebDAVや、Apache サーバに付いている、他の「便利な機能」を使いたいな、と思ったら、その通り、Apache 2.0 が必要になる。 とは言え、Apache 1.x をポート番号80で可動させたまま、Apache 2.0 を別のポートで実行させる、って選択肢もある。異なるバージョンのApacheは、同じマシン上で問題なく同居させることが可能だ。 httpd.conf の中にある Listen ディレクティブを、「Listen 80」から「Listen 8080」などの適当なポート番号へと変更した上で、リポジトリ URL を告知するときに、そのポート番号を明確に示す(例えば、http://svn.mydomain.com:8080/repos/blah/trunk/とかね)だけ。
僕達は、SCM の未知なる世界を切り開こうってわけじゃないし、この世に存在する各種SCMが有している最良の機能群を、全てとりこもう、と考えているわけでもない。 ただ、CVSを置き換えよう、と頑張っているだけ。最初の質問を読んでみて。
リポジトリ全体という単位で割当られるグローバルなバージョン番号は、ユーザの観点からは無意味だ。 これは根底にあるスキーマデザインの目的実現のための、内部実装の一つである。 とはいえ、ユーザインターフェイス的には、憂鬱な気になる、長ったらしい日付や時間の文字列を入力するよりは、場合によっては、少しだけ楽になる、ということはあるけれど。
リビジョン番号は、ただリポジトリの為に、また、ユーザの利便性のために存在するに過ぎない。それは、あなたがリポジトリへ格納しているものとの関係性は一切ない。 コードベースの変更レートに関する正確な指標としては、リポジトリのリビジョン番号変化は、決して適切なものではない。コードベースの変更レートに関する全体把握の為には、より適した、もっと複雑な手法が他に存在する。
この質問は、ちょっと厄介だ。 というのは、皆「チェンジセット」に対して、少しづつ異なる定義を持っているように思えるし、少なくとも、バージョンコントロールシステムが「チェンジセット機能を持つ」という意味に対して異なる期待を抱いているだろうから。
以後の議論の為に、チェンジセットを簡単に定義しておこう。「チェンジセットとは、一意な名前をもった変更の集合である」。 「変更」には、ファイルコンテンツに対するテキスト的な編集や、ツリー構造に対する修正、また、メタデータに対するちょっとした調整も含まれる。 より一般的に言うならば、チェンジセットとは、あなたが参照できる名前をもったパッチのことだ。
Subversionは、バージョン付けされたツリーを第一階オブジェクトとして扱っており(リポジトリは、ツリーの配列だ)、チェンジセットは(近接のtreeと比較することで得られる)そこからの導出物だ。 ArchやBitkeeperなどのシステムでは、逆の理念の上に作られていて、これらのシステムはチェンジセットを第一階オブジェクトとして管理するように設計されている(リポジトリはパッチの集合体だ)。 ツリーは、パッチの集合を互いに組み合わせることで導出される。
どちらかの哲学が、他方よりも絶対的に素晴しい、というわけではない。 この議論は少なくとも30年は遡れる。 この2つの設計は、ソフトウェア開発のタイプによって、適していたり、そうでなかったりする。 ここでは、この議論を行うのは止めにして、その代わり、Subversionを使ってあなたは何が出来るのか、ということを説明しよう。
Subversionでは、グローバルリビジョン番号「N」は、リポジトリ内のツリーの名前である。 これはN番目のコミットを終えたリポジトリの姿だ。 またこれは暗黙的に一つのチェンジセットの名前にもなる。 もし、ツリーNとツリーN-1を比較すれば、コミットされたパッチそのものを引き出すことが可能だ。
これ故に、「リビジョンN」を、ただツリーとしてだけではなく、チェンジセットとして同様に捉えることも容易い。 もしあなたが要求管理システム(issue tracker)をバグ管理に使っているならば、特定のリビジョン番号を、バグを修正した特定のパッチを参照する為に用いることができる。 例えば、「この問題は、リビジョン9238で修正しました」という具合に。 他の人は 'svn log -r9283' と実行することで、そのバグを修正した完全なチェンジセットに関して読むことが出来るし、'svn diff -r9237:9238'とすれば、パッチそのものを見ることができる。 また、svn の merge コマンドもリビジョン番号を利用する。特定のチェンジセットを、あるブランチから他のブランチへマージするには、そのチェンジセット名を merge の引数へと与えればよい。 'svn merge -r9237:9238 branchURL'は9238番のチェンジセットをあなたの作業コピーへとマージすることになるだろう。
これは、チェンジセットを根源オブジェクトに据えて構築されたシステムみたいに複雑なことは出来ないけれども、でも、CVSよりは凄く便利だよね。
Subversion 1.1(ならびにそれ以降)では、通常通りにsvn addコマンドを使って、シンボリックリンクをバージョンコントロールすることが可能だ。
詳細な回答: Subversion リポジトリは、シンボリックリンクに対する内部的なコンセプトを有しているわけではない。 ただ「バージョン管理されたシンボリックリンク」を、'svn:special' プロパティを持つ普通のファイル、として格納しているだけだ。 UNIX 上の svn client は、 こプロパティを参照し、そのファイルをシンボリックリンクとして、作業コピー上へ展開する。 Win32システムには、シンボリックリンクは存在しない為、win32版のクライアントは、そのような展開を行わない。 ただ、普通のファイルとしてオブジェクトが作られるだけだ。
ベクター形式の Subversion ロゴが、Subversion リポジトリ内にあるwww ツリーの中の logo ディレクトリにあるよ。
特に、Adobe Illustrator ドキュメントと共に、EPSバージョンもその中に納められている。
もし、このFAQの残りを読んでも回答を見付けられなければ、以下のリソースをあたってみると良いだろう。
我々のメイリングリストでは、SPAM配信を防ぐ為に、モデレータ制を採用している。 その為、何れのリストに対するあなたの最初の投稿も、モデレータがそのメイル流すまでの間、遅延してしまうかもしれない。 一度投稿が認められれば、以後、同じアドレスからの投稿は自動的に承認されるので、遅延状態になることはなくなるだろう。 勿論、あなたの投稿アドレスが変更された場合には、再びモデレータの許可を待つことになるけど。
Subversion クライアントを使おう。
$ svn co http://svn.collab.net/repos/svn/trunk subversion
あなたのローカルマシンにある subversion という名前のディレクトリの中へ Sunversion のソースツリーのコピーがチェックアウトされるよ。
http://svn.collab.net/repos/svn/trunk/READMEを参照。特に「セクションIV」の「Quickstart Guide」参照のこと。
もっと詳しい情報を知りたい人は、The Subversion Bookの5章を読もう。
多くの人は cvs2svn という変換ツールを利用しているようだ。 cvs2svn のソースコードは https://github.com/mhagger/cvs2svn に置かれている。 もしあなたが Linux あるいは BSD 由来のシステムを利用しているならば、 ディストリビューションはまだそのパッケージを供給しているかもしれない。
cvs2svn があなたの用途に合わなければ Lev Serebryakov が書いた refinecvs を http://lev.serebryakov.spb.ru/refinecvs/ から入手して試みることはできるかもしれない。
Subversion クライアントを適切に設定することで、プロキシを超えることが出来るよ。 まずはじめに、「servers」設定ファイルを編集して、どのプロキシサーバを使うか指定しよう。 このファイルが置かれている場所は使っている OS に依存する。 LinuxやUnixでは「~/.subversion」ディレクトリの中に置かれている。 Windowsでは「%APPDATA%\Subversion」中にある(「echo %APPDATA%」を試してみよう。これは隠しディレクトリなので注意)。
このファイルの中には、各要素の説明がコメントとして書かれている。 もしこのファイルが存在しない場合には、最新のSubversionクライアントを入手して、適当なコマンドを実行してみよう。 設定ディレクトリとテンプレートファイルが作成される。
次に、プロキシサーバ自身が、Subversionの利用している全てのHTTPメソッドをサポートしているかどうかを確認する必要がある。 いくつかのプロキシサーバは、標準では、次のメソッド群をサポートしていない: PROPFIND、REPORT、MERGE、MKACTIVITY、CHECKOUT。 一般的に、これを解決する方法、どのプロキシソフトウェアを使っているかに依存する。 例えばSquidでは、設定オプションをこんな風にしてみよう。
# TAG: extension_methods # Squid only knows about standardized HTTP request methods. # You can add up to 20 additional "extension" methods here. # #Default: # none extension_methods REPORT MERGE MKACTIVITY CHECKOUT
(Squid 2.4以降では、PROPFINDについてはすでにサポートされている)。
プロキシサーバへ通過を許可させる、その他HTTPメソッドに関しては、「Subversionが使っている全ての HTTP メソッドは?」も併せて参照のこと。
プロキシに Subversion トラフィックを通過させるのが難しい、または不可能で、でも Subversion のソースコードをチェックアウトしたい場合には、プロキシを迂回することができるかもしれない。 いくつかのプロキシは、80番ポートをフィルタしているにもかかわらず、81番ポートは何でも許可してたりする。このため、svn.collab.net のリポジトリサーバは、80番ポートと同様に81番でも待ち受けている。 というわけで、
svn checkout http://svn.collab.net:81/repos/svn/trunk subversion
を試してみよう。もしかすると、プロキシは素通ししてくれるかもしれない。 別の戦略としては、SSL上でチェックアウトする、というのもあって、多くのプロキシがこれを許可している。
svn checkout https://svn.collab.net/repos/svn/trunk subversion
勿論、あなたの使っている svn クライアントが、SSLサポートを有効にしてビルドされている必要がある。 これには./configureスクリプトへ --with-sslを渡せばよい。 「https」スキームをサポートしているかどうかは、svn --versionで確認することができるよ。
簡単な案は、Apache ではなくsvnserveサーバを使うこと。 詳細は、Subversionブックの第6章を参照のこと。
でも、もしあなたの管理者がApacheの実行を認めてくれないんだったら、3690番ポートでカスタムサーバプロセスを実行するのも認めてくれそうにないよね! というわけで、残りの回答は、管理者が既存のSSHインフラを使うことを許可してくれたら、って想定で書きます。
もし、以前にCVSサーバを使っていたのだとすれば、多分、CVSサーバへログインするのに SSH を使っていた筈。 ra_svn Subversion アクセス手法は、Subversion で、これと同等のことを実現するための方法だ。 ただ Subversion リポジトリURLの前に「svn+ssh」を付けるだけで良い。
$ svn checkout svn+ssh://your.domain.com/full/path/to/repository
これにより、SSHプログラムがリモートマシン上でプライベートな「svnserve」プロセスを稼動させ、あなたのUIDによるリポジトリアクセスや、暗号化されたリンク上での情報トンネリングを司ってくれる。
また、これとは別の解決策としては、SSHポートフォワーディングの力を借りて、保護されているサーバへ ra_dav 経由で接続する、というのもある。 SSHを経由することで、ファイアウォールの背後に位置している、Subversion サーバへアクセス可能なマシンへと接続することができるだろう。 SSHサーバが、Subversionのインストールされたサーバと同じでマシンでなくてもよい、という点に注目して欲しい。 もちろん同じでも構わないけど、同じである必要性はない。
まずは、Subversionリポジトリを提供しているHTTPサーバへと接続する為の、ローカルなポートフォワードを作る。 それから、このローカルポートを経由してSubversionサーバへ「接続」する。 これで、リクエストがSSHサーバを経由して、Subversionサーバへ「トンネル」されることになる。
例を示そう。ra_dav の設定された Subversion サーバが、会社のファイアウォールの背後に立っている。 IPアドレスは10.1.1.50 だ(このサーバを、svn-server.example.comと呼ぼう)。 会社は、皆がアクセス可能な ssh-server.example.com 経由でのSSHアクセスを許可している。 内部的には、Subversion リポジトリへ http://svn-server.example.com/repos/ours 経由でアクセスできる。
例: クライアントは、ポートフォワーディングを使ってssh-serverへ接続し、そのポートフォワードを経由して、チェックアウトする。
% ssh -L 8888:svn-server.example.com:80 me@ssh-server.example.com % svn checkout http://localhost:8888/repos/ours
svn-server.example.com は、non-trustedユーザによる、非特権ポート上で稼動している httpd インスタンスでも構わないことに注意しよう。 この方法では、Subversion サーバに対して root アクセス権限を必須とはしない。
Joe Orton は以下を注記してくれた。
サーバは、MOVEならびにCOPYリクエストの同期先のヘッダで使われているホスト名に敏感なので、この個所には少し注意を払う必要がある。 この方法を上手く機能させる為には、「ServerAlias localhost」が必要になるかもしれない。
SSHポートフォワーディングに関する幾つかのリンクはこちら。
それは取り扱うプロジェクトに依存する。 もしそれらのプロジェクトに関連性があって、データを共有する可能性があるなら、一つのリポジトリ内に幾つかのサブディレクトリを作るという方法が最良だ。 例えばこんな感じ。
$ svnadmin create /repo/svn $ svn mkdir file:///repo/svn/projA $ svn mkdir file:///repo/svn/projB $ svn mkdir file:///repo/svn/projC
もし、それらのプロジェクトが完全に関係性がなく、プロジェクト間でデータを共有する可能性がないのなら、恐らく、独立した無関係のリポジトリを作るのがベストだろう。
$ mkdir /repo/svn $ svnadmin create /repo/svn/projA $ svnadmin create /repo/svn/projB $ svnadmin create /repo/svn/projC
この二つのアプローチの差は、(Ben Collins-Sussman<sussman@collab.net>によれば)次の通り。
片方のリポジトリについて、履歴の完全な維持、という点を気にしないのであれば、一つのプロジェクトの下へ単に新しいディレクトリを作った上で、そこへもう片方のデータをインポートすれば良い。
もし、両方のリポジトリの履歴を維持したいのならば、'svnadmin dump'を使って片方のリポジトリのダンプを取り、'svnadmin load'で、そのダンプをもう片方のリポジトリへロードすることになる。 リビジョン番号は変わっちゃうけれど、でも履歴は維持できるよ。
Peter Davis <peter@pdavis.cx>は、svnが有するCVSモジュール同様の機能を使う方法について述べている。
異なるディレクトリツリーのマージを行うのであれば、CVSモジュールのsvn版を使うことが出来るよ。
svn:externalsプロパティをディレクトリにセットしよう。これで、オリジナルディレクトリがチェックアウトする時には何時でも、他のリポジトリからディレクトリをチェックアウトさせることが出来るようになる。 リポジトリの分離を維持したまま、作業コピー上では、それらがマージされたかの様に見える。 インポートされたディレクトリへコミットすれば、外部のリポジトリに対して効果が発生する。
このマージは完全にはクリーンではない。インポートは作業コピーにしか影響を及ぼさないから、二番目のリポジトリからインポートされたモジュールへアクセスするために、最初のリポジトリのURLを使うことは出来ない。 両者は異なるURLのままなんだ。
あわせてmiscellaneous utilitiesも探して見よう。 複数のリポジトリをマージする時に、リビジョンの選択や並び換えを行うために役に立つツールを見つけることが出来る。 特に、基本的な操作を行うためにはsvn-merge-repos.plという perl スクリプトが、また、より高度な再編成を行う際にはSvnDumpToolという python クラスが有益だ。
もしあなたのリポジトリが、Berkeley DB をバックエンドに使っているならば(Subversion 1.0と1.1で作られたリポジトリでは、これがデフォルト。それ以降の版ではデフォルトではない)、リモートファイルシステム(例えば、NFS)上にリポジトリを置くことはお勧めしない。 Berkeley DBのデータベースとログファイルをリモートファイルシステム上に格納することは出来るが、Berkeley DB の共有リージョンファイルをリモートファイルシステム上へ格納することは出来ないから、リポジトリは、たった1台のファイルシステムクライアントからしかアクセスできないだろうし、また、1台のクライアントにすら提供できないSubversionの機能も存在するだろう。
もしあなたがリポジトリのバックエンドにFSFSを使っているならば、リポジトリを最近のNFSサーバ(即ち、lockをサポートしている、ってこと)上に格納しても大丈夫だろう。
作業コピーはNFS上へ格納することができる(基本的なところでは、ホームディレクトリがNFSサーバ上に位置している、というのがある)。 Subversionは、チェックアウト時、大量のリネーム処理を内部的に行っている為、LinuxのNFSサーバを使う場合には'subtree checking'を無効化すべきだ、との報告がある(デフォルトでは有効になっている)。 subtree checking を無効化する方法については、NFS Howto Server Guideとexports(5)を参照のこと。
我々は、少なくとも1通、SMBでアクセスした後、作業コピーがWedged になった、というレポートを受け取っている。問題のサーバはやや古めのバージョン(2.2.7a)のSambaを稼動していた。この問題は新しめのSamba(3.0.6)では再発していない。
リポジトリは、あなたの全てのデータを、リポジトリの /db/ サブディレクトリ内にある Berkeley DBの「環境」内に蓄積している。 この環境は、テーブルの集合やログファイル(log.*) の束を格納している。Berkeley DB はテーブルに行われた全ての変更を記録するので、実行が遮られた場合でも、首尾一貫した状態へと復元することが可能だ(詳細はこちら)。
ログファイルは永遠に成長を続け、あなたが(リポジトリ管理者として)何らの処理を行わない限りは、ディスク空間を食いつづけるだろう。ある時点で、Berkeley DB が実際に使用するログファイルは僅かでしかない(この投稿と続くスレッドを参照)。 というわけで、残りは安全に削除することができる。もし、あなたが全てのログファイルを永遠に保存しておくのであれば、Berkeley DBは、リポジトリがこの世に生を受け手から後、施された全ての変更を、理論上は再現することが出来ることになる。 でも現実的には、もしバックアップをとっているなら、多分、ディスク空間という面で、コストに見合わないと思うよ。
どのファイルが削除可能かを確認するためには、svnadmin
を使おう。cron でこんな感じのジョブを実行すると良いだろう。
$ svnadmin list-unused-dblogs /repos /repos/db/log.000003 /repos/db/log.000004 [...] $ svnadmin list-unused-dblogs /repos | xargs rm # ディスク空間を取り戻した!
この変わりに、Berkeley DB の db_archive
コマンドを使うこともできる。
$ db_archive -a -h /repos/db | xargs rm # ディスク空間を取り戻した!
svnadmin hotcopy
やhotbackup.py
も参照のこと。
注意:もしあなたが Berkeley DB 4.2 を使っているならば、Subversion は、自動ログ削除機能を有効にしてリポジトリを作成しているだろう。
svnadmin create
を実行時に、--bdb-log-keep
オプションを指定することで、これを変更することが可能だ。
Berkeley DBマニュアルに書かれた (dead link: http://www.oracle.com/technology/documentation/berkeley-db/db/api_c/env_set_flags.html#DB_LOG_AUTOREMOVE) DB_LOG_AUTOREMOVE
フラグを参照のこと。
リポジトリにアクセスできるユーザの数を、極力少なくしよう。例えば、apache や 'svnserve -d'を特定ユーザで起動し、リポジトリ全体をそのユーザの所有にする。他のユーザには、file:///URL経由でのリポジトリアクセスを許可しないようにし、また 'svnlook' や 'svnadmin' は、そのリポジトリ所有者権限でだけ実行されるようにしよう。
もしクライアントが、file:/// や svn+ssh://経由でアクセスするならば、複数ユーザからのアクセスを無効化させる方法は存在しない。 この場合、第6章の最終セクションを読んで、下のほうにある「チェックリスト」サイドバーへ十分注意を払おう。 このリストには、このシナリオを安全に行う為の幾つかのステップが概説されている。
注意: SELinux / Fedora Core 3+ / Red Hat Enterpriseをお使いの方々へ通常の Unix パーミッションに加え、SELinuxの元では、全てのファイル、ディレクトリ、プロセスなどが「セキュリティコンテキスト」を有している。 プロセスがファイルへアクセスしようとした場合、Unixパーミションチェックの他に、システムは、プロセスのセキュリティコンテキストが、ファイルのコンテキストと互換性があるかを確認しようとする。
Fedora Core 3 は(他にも同様のシステムはあるけど)、SELinux が標準でインストールされ、また設定されるので、Apacheは非常に制限されたセキュリティコンテキストの中で実行されることになる。 SubversionをApacheの元で動作させる為には、Apacheからのアクセスを許可するよう、リポジトリのセキュリティコンテキストを設定しなければならない(もしくは、この制限機能はちょっと過剰だなぁ、と思うならば、Apache側で制限を無効化しよう)。 ファイルのセキュリティコンテキストを設定するためには、chcon コマンドが使われる(chmodが伝統的なUNIXパーミッションをセットするのと似た方法だ)。 例えば、リポジトリへ問題なくアクセスできるようにする為には、次のコマンドを実行し、
$ chcon -R -h -t httpd_sys_content_t PATH_TO_REPOSITORY
セキュリティコンテキストを設定しなければならないだろう。
ある種のクライアント操作、例えば、チェックアウトや更新は「リードオンリー」だ。 アクセスコントロールという観点で言えば、Apacheはこれらの操作をその様に扱う。 しかし、libsvn_fs(リポジトリファイルシステムAPI)は、ツリー差分を生成する為、一時データを書き込む必要がある。 その為、リポジトリへアクセスするプロセスが機能する為には、Berkeley DBに対して、常に読み込みと書き込みのアクセスが必要になる。
特に、リポジトリは、多くの「リードオンリー」操作に対し、2つのツリーを比較する事で対応する。 1つのツリーは、大抵 HEADリビジョンで、もう片方は概ね一時的なトランザクションツリーだ。というわけで、書き込み権限が必要になる。
この制限は、Berkeley DBをバックエンドを使っている場合にだけ生じ、FSFSバックエンドでは発生しない。
ファイルやコミットに関する全ての痕跡を完全に消し去りたい、という特別な場合がある(例えば、誰かが間違えて、極秘ドキュメントをコミットしちゃった、とか)。 これは、そう簡単な話ではない。 というのも、Subversionは決して情報を失うことのないよう、よくよく考えて設計されているのだから。 リビジョンは、他のリビジョンの上に構築される、不変のツリーだ。 あるリビジョンを履歴上から除去した場合、ドミノ倒しのように以降に続く全てのリビジョンを目茶苦茶にしてしまい、恐らく全ての作業コピーがだめになってしまうだろう。
とはいえ、プロジェクトとしては、いつの日か、svnadmin obliterate コマンドを実装する、というプランを持っている。 このコマンドを使うことで、情報を永久に消し去ることが出来るようになるだろう(issue 516を参照の事)。
それまでの間は、あなたの取り得る手段としては、svnadmin dumpでリポジトリのダンプを取り、そのファイルをパイプ経由でsvndumpfilterを通過させ(不正なパスを取り除く)、その出力をsvnadmin loadコマンドへ読み込ませる、ということになる。 詳細は、Subversion bookの第5章を参照の事。
ログメッセージは、各リビジョンの属性として貼り付けられた上で、リポジトリに中に保存されている。 デフォルトでは、一度コミットされてしまったログメッセージ属性(svn:log)は、変更することが出来ない。 これは、リビジョン属性(svn:logはその中の一つ)への変更は、以前のプロパティ値を完全に廃棄してしまう為で、この操作が誤って実行されないよう、Subversionは、あなたを守ってくれている、というわけだ。 とは言え、リビジョン属性を変更する為の方法は、幾つか存在する。
最初の方法は、リビジョン属性の変更を有効にしたいリポジトリ管理者向けのものだ。 これは「pre-revprop-change」と呼ばれるフックを作ることで実現される(実現方法の詳細に関しては、Subversion book のこのセクションを参照)。 この「pre-revprop-change」フックは、ログメッセージが変更される前に、古いログへアクセスするので、何らかの方法(例えば、メイルで送る、など)により、このログを保存することは可能だ。 ひとたびリビジョン属性の変更が有効化されれば、svn propeditかsvn propsetへ--revpropスイッチを引き渡すことでリビジョンのログメッセージ変更が可能になる。例えば、こんな感じ。
$ svn propedit -r N --revprop svn:log URL $ svn propset -r N --revprop svn:log "new log message" URL
ここで N は、ログメッセージを変更したいと思っているリビジョンの番号で、URLはリポジトリの場所。 もし、このコマンドを作業コピーの中で実行するのであれば、URLを指定する必要はない。
ログメッセージを変更する2番目の方法は、svnadmin setlogを使う方法。 これは、ファイルシステム上のリポジトリの場所を指定して実行しなければならない。 リモートのリポジトリを、このコマンドを使用して変更することはできない。
$ svnadmin setlog REPOS_PATH -r N FILE
REPOS_PATHにはリポジトリの場所を、N には変更したいログメッセージのリビジョン番号を、FILEには新しいログメッセージの書かれているファイルを指定する。 もし「pre-revprop-change」フックが適切に動作していない(または、何らかの理由で、フックスクリプトを迂回したい)場合には、--bypass-hooks オプションが利用可能だ。 しかし、このオプションを使う場合には、十分に注意すること。例えば、メイルによる変更伝達や、リビジョン属性を追跡するためのバックアップシステムを迂回してしまうことになるかもしれない。
まず最初に、Subversion Community Guideを読むこと。
熟読したら、[PATCH]という単語と1行説明をサブジェクトに記述し、(あなたの MUA がメイルをぐちゃぐちゃにしてしまわないことが前提で)パッチをメイル内へインラインで取り込んだ上で、そのメイルをdevリストへ送ろう。 その後、コミッタはそれを拾い上げ、適用を行い(必要に応じてフォーマットや内容の変更が行われる)、チェックインすることになる。
基本的な手順はこんな感じ。
$ svn co http://svn.collab.net/repos/svn/trunk subversion $ cd subversion/www [ make changes to faq.html ] $ svn diff faq.html > /tmp/foo $ Mail -s "[PATCH] FAQ updates" < /tmp/foo
勿論、Subversion Community Guideに従って、あなたのメイルには、そのパッチが何を為してくれるのか、という点に関する、分かりやすい十分な長さの説明文が含まれている筈。 って、説明するまでもないよね。だって、実際にコードをハックし始める前に、既にこのガイドを読んで、完全に理解しているんだもんね :)
例えば、/etc 内の幾つかを、あなたのリポジトリ内で、バージョン管理下に置きたいのだと仮定してみよう。
# svn mkdir file:///root/svn-repository/etc \ -m "リポジトリ内に/etcに対応するディレクトリを作る" # cd /etc # svn checkout file:///root/svn-repository/etc . # svn add apache samba alsa X11 # svn commit -m "僕の設定ファイル群への最初のバージョン"
ここでは、ちょっと見珍しい、svn checkoutの便利な機能を使っている。 ディレクトリを、リポジトリから既存のディレクトリ内に対して、直接チェックアウトすることができる。 まず最初に新しい空のディレクトリをリポジトリの中へ作る。 それから、それを/etcの中にチェックアウト。 これで/etcは作業コピーへと変化する。 一度この作業が済んだ後は、普通にsvn addコマンドをつかって、ファイルやサブツリー群をリポジトリへ追加することができる。
svn import を強化して、インポートされたツリーを自動的に作業コピーへ変換できるようにする、というのは課題だ。issue 1328を参照。
サブバージョンのリポジトリデータベーススキーマは、開発中、まれに変更になる場合がある。古いリポジトリ(Subverision 1.0 より前の開発版で作られたもの)は、アップグレードをする際、以下の手順が必要になるかも知れない。 もし、スキーマ変更が、Subversionリリース X と Yの間で起こった場合、Yへとアップグレードするリポジトリ管理者は、以下手順を踏む必要がある。
ダンプとロードの方法の詳細に関しては、Subversion bookのこのセクションを参照のこと。
注意: Subversion のほとんどのアップグレード時には、ダンプやロードは必要ない。 これが必要になる場合、リリースアナウンスや、新版の CHANGES ファイルで、十分な告知がなされるだろう。 もしあなたがその様な告知を目にしていないのであれば、それはスキーマに変更はない、ということであり、ダンプ/ロードも必要ない。
TortoiseSVNには、Windows 上で Subversion サーバを設定する為の、素晴らしいドキュメントが同梱されている。 https://tortoisesvn.net/docs/release/TortoiseSVN_en/tsvn-serversetup.html#tsvn-serversetup-apache-5へアクセスして、SSPI認証のセクションを参照してみよう。
設定上の重要な箇所は、次の行。
SSPIOfferBasic On
この行が無くても、SSPIをサポートしているブラウザでは、ユーザのクレデンシャルを要求するだろう。 しかし、SubversionのようなSSPIをサポートしていないクライアントは要求しない(現在のリリースのNeon(SubversionのHTTPライブラリのこと)は、ベーシック認証しか扱えない)。 クライアントが決してクレデンシャルを要求しない為、認証を必要とする操作はすべて失敗となる。 この行を加えることにより、mod_auth_sspiに対して、クライアントに対してはベーシック認証を使うことを、一方で、クレデンシャルの認証を行うためには、Windowsドメインコントローラを用いることを、指示することになる。
我々としては、可能な限り「.svn」と生活を共にすることをお勧めするよ。 とは言え、Windows上でASP.NETを使っているならば、 ここ で説明しているようにSVN_ASP_DOT_NET_HACK環境変数を設定する必要があるかもしれない。
または、完全にカスタムな名前を管理用ディレクトリの名前として使うことも可能だろう。 我々としては、これはお勧めしない。と言うのも、あなたの作業コピーは、多分、あなたがカスタマイズした以外のSubversionクライアントでは使えないだろうから。 しかし、どうしてもやらなければならない、というのであれば、ただsubversion/include/svn_wc.hの
#define SVN_WC_ADM_DIR_NAME ".svn"
を、例えば、
#define SVN_WC_ADM_DIR_NAME "SVN"
へと変更し、クライアントを再コンパイルすれば良い。
この問題は、2つの状況で発生する。 Windows のような大文字小文字(つまり文字ケース)を区別しないファイルシステム上でファイルを追加した場合、意図せずファイル名の文字ケースが誤った状態で登録してしまったことに気がついたのかもしれない。 あるいは、単に、リポジトリ内にある既存ファイルの大文字小文字を変更したい、と考えたのかもしれない。
もしあなたが、文字ケースを区別するファイルシステムを使っているならば、全く問題はない。ただファイルを新しい名前に変更するだけだ。例えばこんな感じ。
svn mv file.java File.java
しかし、これは、Windowsのような大文字小文字を区別しないOS上では上手くいかないだろう。 Windows上でこれを実現するためには、ファイルをどこかへ一時的にコピーしておき、Subversion上からそのファイルを消した後、そのコピーを正しい文字ケースで追加することになる。 また、より良い方法は、Subversion URL を使って、move 操作を実行することだ。URLを使う方法がお薦めで、なぜなら、そのファイルの履歴が保存されるし、すぐに結果が反映されるることになるから。
とはいえ、どちらの方法も Windows 上の作業コピーには問題を残す。 というのも、名前の競合したファイルを更新する時、Windows は未だ混乱に陥るからだ(多分、次のようなメッセージが表示されるだろう。 svn: Failed to add file 'File.java': object of the same name already exists)。 この問題を解決する方法の1つは、ワーキングコピーを削除して、チェックアウトし直すことだ。 もし、これをしたくない場合には、2段階の更新手順を踏まなければならない。
大文字小文字の間違っている各ファイルに対して、次のコマンドを実行し、文字ケースを変更する。
svn mv svn://svnserver/path/to/file.java svn://svnserver/path/to/File.java
作業コピーを更新するため、適切なディレクトリへ移動して、次の操作を実行。
svn update file.java svn update
最初の更新処理で、file.javaを作業コピーから消し去り、次の更新処理でFile.javaを追加して、作業コピーを正しい状態にする。 もし、問題のあるファイルが数多く存在するならば、次の方法で、作業コピーを更新することも可能だ。
svn update * svn update
今まで見てきたように、間違った文字ケースで追加されたファイルを、文字ケースを区別しないOS上で修正するのは、骨が折れる。 是非、ファイルを最初に登録する時点で、正しく登録するようにしよう! 最初からこの問題を防ぐために、check-case-insensitive.plファイルを呼び出すpre-commitフックを作成すれば良い。 このファイルは、Subversion ソース tarball 内の、contrib/hook-scriptsディレクトリ内に置かれている。
以下で示すように、リビジョン番号を覚えることなく、branch からtrunk へマージを行なうことが可能だよ。また、その逆も可能(例には示してないけどね)。
以下の例では、/home/reposという既存リポジトリがあり、この中にbarという名前の branch を作りたいということを、また、このbranch は、fooという名前の編集対象ファイルを含んでいることを仮定している。
branch のマージトラックするため、このリポジトリには、tags/branch_traces というタグを記録しておくための場所が用意されている。
# ブランチとタグをセットアップ $ svn copy file:///home/repos/trunk \ file:///home/repos/branches/bar_branch \ -m "start of bar branch" $ svn copy file:///home/repos/branches/bar_branch \ file:///home/repos/tags/branch_traces/bar_last_merge \ -m "start" # brach の作業コピーをチェックアウト $ svn checkout file:///home/repos/branches/bar_branch wc $ cd wc # foo.txt ファイルを編集して commit。 $ echo "some text" >>foo.txt $ svn commit -m "edited foo" # trunk へ switch して、変更点を branch からマージ $ svn switch file:///home/repos/trunk $ svn merge file:///home/repos/tags/branch_traces/bar_last_merge \ file:///home/repos/branches/bar_branch # ここで foo.txt の中身を確認してみよう。先の変更が取り込まれているはず。 # マージをcommit。 $ svn commit -m "Merge change X from bar_branch." # 最後に、現在の状態を反映しておく為、追跡用 branch を更新。 $ svn delete -m "Remove old trace branch in preparation for refresh." \ file:///home/repos/tags/branch_traces/bar_last_merge $ svn copy file:///home/repos/branches/bar_branch \ file:///home/repos/tags/branch_traces/bar_last_merge \ -m "Reflect merge of change X."
Subversion ではリポジトリー全体でリビジョン番号が増加してゆくから、どのキーワードもその番号へ変更することはできない。 それをやろうとすれば、毎更新とコミット時、作業コピーの中にある全てのファイルを検索し、恐らく更新してまわるはめになるだろう。
あなたが欲しい情報(作業コピーのリビジョン)は、svnrevisionコマンドを使って取得することが出来る。 これは、与えられたパスの作業コピーに対するリビジョン番号情報を表示してくれる(詳細はsvnversion --helpを参照のこと)。
これをビルドやリリースプロセスに統合することで、ソース自身にこの情報を引き渡すことが可能だ。 例えば、GNU makeを使ったビルド環境では、Makefileへこのような処理を加えれば良い。
## ## これを使うには、yourfile.c の中で次のような感じにすればよい ## printf("このプログラムは SVN の revision %s からコンパイルされました\n",SVN_REV); ## SVNDEF := -D'SVN_REV="$(shell svnversion -n .)"' CFLAGS := $(SVNDEF) ... continue with your other flags ...
(これは、GNU版ではないmakeでは動作しないかも知れないことに注意。 もしあなたのビルドプロセスがポータビリティを必要としているならば、この方法を使ってはならない)
または、こんなのをどうぞ。
## ## すべてのビルドで、作業コピーのリビジョン文字列を記録する ## svn_version.c: FORCE echo -n 'const char* svn_version(void) { const char* SVN_Version = "' \ > svn_version.c svnversion -n . >> svn_version.c echo '"; return SVN_Version; }' >> svn_version.c ## ## これで、svn_version.o をリンクするすべての実行ファイルは、 ## svn_version() 関数を呼び出すことが出来る。この関数では、 ## ビルドが行われたまさにその時のリビジョン番号の記載された ## 文字列を取得することが可能だ。 ##
Windowsユーザは、SubWCRev.exeコマンドが使えるだろう。 これは、TortoiseSVNのダウンロードページから入手できる。 これは、指定されたファイル中に書かれている全ての $WCREV$ タグを、現在の作業コピーのリビジョンへと置き換える。
存在しない。 CVSの $Log$ と同等品は存在しないんだ。 もし、特定ファイルのログを取得したいのならば、'svn log your-file-name'を実行するか、'svn log url-to-your-file'を実行すればよい。 なぜ、$Log$ がマズイかを説明した、メイリングリストに流れた記述を次に。
"$Log$ は、branch間の変更をマージし始めた途端、全く持って恐怖となる。 ほとんど確実にその箇所で競合が生じることになり(なぜって、それがこのキーワードの特質だから)、自動的な競合の解消は、どうやっても不可能となる。"
加えて、次の通り。
Subversion のログメッセージは可変であり、svn:log リビジョン属性を用いることで変更することができる。 だから、あるファイルで$Log$を展開したとしても、古い内容となってしまっている可能性がある。 更新処理では、$Log$ キーワードへ遭遇する度に、実際にはそのファイルが変更されていない場合であっても、適切なログメッセージを取得しなければならならなくなるだろう。
僕はそんなことは気にしないよ。どうであれ、それを使いたいんだ。実装する気はない?
ない。 我々は、それを実装する気も、この機能を実装したパッチを受け入れる気もない。 もしあなたが、changelog 等を含んだファイルを配布したい、と考えているのならば、ビルドシステムで、この制約を回避できると思う。
回答: その手のファイルは、バージョン管理下に置かないようにしよう。 その変わりに、そのファイルのテンプレートを、「file.tmpl」といった名前で、バージョン管理下に置こう。
そして最初の 'svn checkout' 実行後、そのテンプレートを、あなたのユーザ(または、あなたのビルドシステム)に、普通のOSのコピーを使って適切な名前でコピーさせ、そのコピーをカスタマイズさせる。 このファイルはバージョン管理されていないから、決してコミットされることはないだろう。 またあなたが望むなら、そのファイルを、上位ディレクトリの svn:ignore 属性へ追加することも出来る。 こうすれば、'svn status' コマンドを実行しても、'?' のように表示されることはなくなるよ。
ssh は独自のパスフレーズを有していて、独自の認証キャッシュ機構を備えている。 この認証キャッシュは Subversion 外にあるので、Subversion とは独立して設定しなければならない。
OpenSSH には、ssh-ketgen という鍵生成プログラムと、ssh-agent というパスフレーズキャッシュプログラム、そして、ssh-addという、パスフレーズをエージェントのキャッシュへ追加するプログラムが同梱されている。 ssh-agentを簡単に使う為に人気のあるスクリプトがkeychain だ。Windows では、ssh の有名な代替クライアントとしてPuTTY がある。 OpenSSH の鍵をインポートする為には、PuTTYgen を、パスフレーズをキャッシュする為には、pageant を参照の事。
ssh-agentの設定方法はこのドキュメントの範疇外だけど、Googleで、ssh-agent を検索すれば、すぐに回答を得られるだろう。 もの凄く せっかちなあなたは、次のリンクを参照のこと。
http://mah.everybody.org/docs/ssh
注意: ここでは、あなたが OpenSSH を使っていると仮定している。 世の中には、他のssh実装も存在していて、恐らく、それら実装でも同じようなことが出来るとは思うんだけど、詳細を把握していない。
あなたは、色々な login ファイル、例えば .bash_profile等と格闘して、でもどうにもならなかったんだね! これは、Subversion クライアントが ssh を起動するとき、ssh は、それらのファイルを無視する為だ。 でも、PATHを変更する必要なんてないんだ。そのかわりに ssh へ直接svnserveコマンドのフルパスを教えてやれば良い。 ここでは、その方法を説明しよう。
svn+ssh アクセスが必要な各ユーザに対して、Subversion 専用の(つまり、通常、ログインでは使わない)新しい ssh のpublic-keyペアを生成しよう。 そのキーペアには、特別の名前を付けておこう。 例えば、~/.ssh/id_dsa.subversion といった具合だ。 その鍵のうち、公開鍵を、サーバマシン上にある彼らの ~/.ssh/authorized_keysファイルへ追記する。 但し、行の先頭、ssh-rasかssh-dssという語の前に、ちょっとだけマジックを挿入してね。
before |
---|
ssh-dss AAAAB3Nblahblahblahblah |
after |
command="/opt/subversion/bin/svnserve -t" ssh-dss AAAAB3Nblahblahblahblah |
当然、/opt/subversion/bin/svnserveは、あなたの環境に適した値へ置き換えること。 また、Subversion リポジトリへのフルパスを、(-rオプションを使って)コマンドへ指定しても良いだろう。 ユーザはタイピングする手間を少し省くことができる。
このcommand=マジックは、例えユーザが、他のコマンドを実行しようとした場合でも、リモートマシンの sshd に対し、svnserve を実行させるように仕向ける。 詳細は sshd(8) のマニュアルページ(AUTHORIZED_KEYS FILE FORMATセクション)を参照のこと。
さて、あなたのユーザが Subversion クライアントを実行する際には、彼らのキーペアの秘密鍵が「指示されている」SVN_SSH環境変数が設定されていることを確認しよう。 (Bourne Again シェルでは)こんな感じになる。
SVN_SSH="ssh -i $HOME/.ssh/id_dsa.subversion" export SVN_SSH
このファイルでは、この問題をより深く解説しているよ。
他の質問への回答だけど、この中に書かれた~/.ssh/authorized_keysファイルのハックに関するセクションを参照のこと。 svnserveをPATHへ含める件に関しては、無視してよいよ。
Subversion はファイルのコンテンツをデフォルトでは変更しない。 もし変更したい場合には、ファイルに対し、明示的にsvn:eol-styleやsvn:keywordsプロパティを設定する必要がある。 これが Subversion を CVSのデフォルト動作よりもずっと安全なものにしているだけど、この安全さは、ある種の不便さも引き起こす。
最初の質問に応えよう。既にリポジトリへ格納されている全てのファイルへ属性を付与する為には、面倒な作業が必要になる。やり方は、(作業コピー内にある)全てのファイルに対してsvn propsetを実行し、それをsvn commitすること、せいぜいこれだけだ。 多分、スクリプトを書くと作業が楽になると思う。
では、新規ファイルはに関してはどうだろう? 生憎、コミットされかかっているファイルに対して、サーバ側で属性を自動的に与える仕組みは用意されていないんだ。 これは、全てのユーザは、ファイルをsvn addする度、忘れずに、属性を適切に設定せねばならない、ということを意味する。幸い、この作業を補助するクライアントサイドのツールがある。 Subversion Book の auto-props機能に関して読んでみよう。 全てのユーザがクライアントの auto-props 設定を適切に行っているかどうかを、あなたは確認する必要がある。
また、ファイル属性を付け忘れた新規ファイルのコミットを拒否する pre-commit フックスクリプトを書くことも可能だ(例えば、http://svn.collab.net/repos/svn/trunk/contrib/hook-scripts/check-mime-type.plを参照)。 でもこのアプローチは、やりすぎかもしれない。例えば、もしsvn:eol-styleを付け忘れた人がいた場合、他の誰かが、そのファイルを異なるOS上で開いた瞬間に気がつくと思う。 一旦気がつけば、直すのは簡単。 ただ、属性を設定して、コミットするだけだ。
注意: 多くのユーザが、ランタイム設定、例えばauto-propsの設定等を、サーバからクライアントへ自動的に「ブロードキャスト」する機能が欲しい、と言ってきている。 これは、機能要求としては既に受け付けられているんだけど(issue 1974)、この機能は開発者の間で現在議論中なので、まだ作業には取りかかっていない。
Subversion コマンドラインクライアントは、SVN_EDITOR環境変数で定義されたエディタを起動する。 この環境変数は、ログメッセージの入力や編集に利用される一時ファイル名と共に、直接OSへと引き渡される。
SVN_EDITOR文字列は、そのままシステムのコマンドシェルへ引き渡されることになるため、エディタ名やエディタへのパスにスペースが含まれている場合、クォートで囲む必要があるだろう。
例えば、Windows 上で、エディタにC:\Program Files\Posix Tools\bin\vi
を利用する場合、この変数を次のように設定することになる。
set SVN_EDITOR="C:\Program Files\Posix Tools\bin\vi"
Windowsのシェルでは、クォートをエスケープする必要のないことに注意。
クォートはset
コマンドの構文には含まれていないからね。
Unixシステムでは、あなたのシェル特有の変数設定方法に従う必要がある。 例えば、bash では、こんな感じだ。
SVN_EDITOR='"/usr/local/more editors/bin/xemacs"' export SVN_EDITOR
エディタの起動時にコマンドラインオプションが必要な場合、通常のコマンドラインと同様、エディタ名に続けてそのオプションを指定した上で、SVN_EDITOR環境変数へ設定すればよい。
例えば、上記のエディタへ-nx -r
オプション指定したい場合、こんな感じになるだろう。
Windowsでは、
set SVN_EDITOR="C:\Program Files\Posix Tools\bin\vi" -nx -r
UNIX/bashでは、
SVN_EDITOR='"/usr/local/more editors/bin/xemacs" -nx -r' export SVN_EDITOR
SVN_EDITOR は、Subversion 特有の、エディタを指定する為に利用される変数だ。 Subversion では、より汎用的な EDITOR 変数もサポートしているけれど、もし Subversion で特有の挙動が必要ならば、SVN_EDITOR 変数を使うのが最良だよ。
もし、そのリポジトリが現在稼働中のものならば、簡単な答えは「あなたがインストールしている Berkeley DB のバージョンだよ」となる。 しかし、もしそのリポジトリが、バックアップや不明なソースから作られたもので、どのバージョンの Berkeley DB で作られたのが手がかりがないなら、こんな感じで調べよう。
適当なコマンドを使って、リポジトリ内で最も大きな番号の割り振られた db/log.* ファイルについて、(10進で)12番目と16番目のオフセットから2つの4バイトの整数値を調べよう。 GNU od を使う場合はこんな感じ:「od -j12 -N8 -tx4 log.<number>」。Mac OS X のhexdump を使う場合には、こんな感じ:「hexdump -s12 -n8 -x log.<number>」。 最初の整数は、マジックナンバーである 0x00040988 となっている筈だ。 これは、そのファイルがBerkeley DBのログファイルであることを示している。 2番目の数値が、ログフォーマットのバージョンだ。 下のテーブルで、Berkelet DB のバージョンを確認しよう。
ログフォーマットバージョン | Berkeley DBバージョン |
---|---|
5 (0x00000005) | 4.0 |
7 (0x00000007) | 4.1 |
8 (0x00000008) | 4.2 |
10 (0x0000000a) | 4.3 |
11 (0x0000000b) | 4.4 |
12 (0x0000000c) | 4.5 |
13 (0x0000000d) | 4.6 |
あなたのリポジトリへpost-commiフックスクリプトを加えることにより、何時でも簡単にこれを実現することができる。 フックスクリプトについて、Subversion Book の第5章を参照のこと。 基本的なアイディアは、その「ライブサイト」を一般的な作業コピーにした上で、post-commit フックスクリプトにより、作業コピー上で 'svn update' を実行させれば良い。
実際には、幾つか注意すべき点がある。 コミットを司るサーバプログラム(svnserveまたはapache)は、post-commitフックスクリプトを実行することになるプログラムと同一だ。 これは、このプログラムが、作業コピーを更新できる適切なパーミションを有していなければならないことを意味する。 言い換えれば、その作業コピーは、svnserveやapacheを稼動させているのと同一ユーザに所有されていなければならない。 または、少なくとも、その作業コピーは、適切なパーミッションを有している必要がある。
もしそのサーバが、所有権を有していない作業コピー(例えば、ユーザ joe の ~/public_html/ 領域)をアップデートする必要があるなら、更新を司る +s バイナリプログラム(setuidされたプログラムのこと)を作る、という方法がある。 これは、Unix が +s されたスクリプトの実行を許可しないためだ。 次の小さなCプログラムをコンパイルしよう。
#include <stddef.h> #include <stdlib.h> #include <unistd.h> int main(void) { execl("/usr/local/bin/svn", "svn", "update", "/home/joe/public_html/", (const char *) NULL); return(EXIT_FAILURE); }
そして、このバイナリをchmod +sし、ユーザ 'joe' に対して所有権を与える。 その後、post-commit フックで、このバイナリを起動する為のようにすればよい。
そのフックの実行が上手く行かない場合には、「どうしてリポジトリのフックが動作しないの?」を参照のこと。
また恐らく、そのライブ作業コピー内にある .svn/ ディレクトリを、apache が公開してしまわないようにしたい、と考えるかもしれない。 次の行をhttpd.confへ追加しよう。
# Subversion 作業コピー管理ディレクトリの表示を不許可にする <DirectoryMatch "^/.*/\.svn/"> Order deny,allow Deny from all </DirectoryMatch>
Subversion では、ファイル単体のチェックアウトはサポートしていない。 サポートしているのは、ディレクトリ構造でのチェックアウトだけだ。
ただし、'svn export' を使うことでファイルを単体でエクスポートすることは出来る。 これは、そのファイルコンテンツを取得し、バージョン付けされた作業コピーは作成しない。
どうにも出来無い。試行するのも不味い考えだ。
作業コピーの基本デザインには、2つのルールがある。(1)ファイルを編集はあなたの望むのようにどうぞ。 (2)ツリーに対するどんな変更(追加、削除、移動、コピー)も、Subversionクライアントを用いること。もしこの規則に従のであれば、Subversionクライアントは完全に作業コピーを管理できる。 もしも、名前の変更や再配置がSubversion 外で行われた場合、UIは侵害され、作業コピーは破壊されることになるだろう。 クライアントは、何が起ったのか推測することができない。
人々は、時たま、この問題にぶちあたる。 というのも、バージョン管理を「透過」にしたいと考えるからだ。 ユーザには作業コピーを使わせ、その後に、何が行われたのかを推測し、適したクライアントコマンドを実行する為のスクリプトを走らせる。 生憎、このテクニックで走り通せるのは、僅かな距離だけだ。 'svn status' により、消失したファイルやバージョン管理されていないアイテムを知ることができる、スクリプトは自動的に 'svn rm' や 'svn add' を実行できる。 しかし、もし移動やコピーが発生したら、はい、ご愁傷様。 例えそのスクリプトが、これらを発見する素晴らしい方法を実現したとしても、'svn mv'や'svn cp'は、それが起こってしまった後では、実行することができない。
まとめ: 作業コピーは、完全に Subversion の管理下へ置こう。 Subversionは透過となるようにはデザインされていない。 もし、あなたが透過性を求めるならば、apache サーバを立ち上げ、Subversion bookの Appendix C に書かれている「SVNautoversioning」機能を使ってみよう。 これは、ユーザに対して、リポジトリをネットワークディスクのように mount させることを許可するもので、そのボリュームに対して行った如何なる変更も、サーバへ自動的にコミットされるようになる。
3つの手順がある。
ここでは、あなたは /svn/myrepos という、BDBをバックエンドに使っているリポジトリを持っていて、FSFSバックエンドを使うように変更したいと思っている、としよう。
無事、新しいリポジトリが全て正常に動作しているのを確認してから古いリポジトリを削除しよう。
反対に FSFS から BDB へと移行させる場合には、svnadmin createコマンドで BDB を指定しよう。
初めてファイルがSubversionへ追加、もしくはインポートされるとき、ファイルがバイナリファイルかどうかが判定される。 現時点では、Subversionはファイルの先頭の1024バイトを見るだけだ。 もし、何れかのバイトが0である場合、または、15%以上が非アスキー表示可能文字であった場合、そのファイルはバイナリと判断される。 とはいえ、このヒューリスティックな手法は、将来、改良されるかも。
ファイルがバイナリだと判断された場合、そのファイルは svn:mime-type 属性へ「application/octet-strem」が設定される(この挙動は、auto-props機能を用いることで、または、手動でsvn propsetを実行して属性を設定することで、何時でも上書きが可能だ)。
Subversionは以下のファイルをテキストとして扱う。
これ以外のファイルは全てバイナリとして扱われる。つまり、Subversion は、以下の通りに動作する。
これ以外の点に関しては、Subversion はバイナリファイルをテキストファイルと同様に扱う。例えば、svn:keywords やsvn:eol-style 属性をセットした場合、Subversion はキーワード置換や、改行コード変換を、バイナリファイルに対しても実行するだろう。
ファイルがバイナリか否か、変更点を格納する為に利用されるリポジトリ容量へは影響を及ぼさないし、クライアントサーバ間でやり取りされるトラフィックの量にも影響しないことに注意して欲しい。 蓄積や転送に於いては、Subversionは、バイナリとテキストファイルの両者に対して同様に上手く機能する差分化手法を用いる。 これは、'svn diff'コマンドで使われる差分化手法とは、全く関係がない。
svn diffには、それを実現するオプションはないけど、
svn log -vq -r10で希望の結果が入手できるよ。
svn log -vq -r123:456 | egrep '^ {3}[ADMR] ' | cut -c6- | sort | uniq
あなたは、
svn mv svn://server/trunk/stuff/* svn://server/trunk/some-other-dir
というような感じでやりたいんだろうけど、でもこれは、
svn: Path 'svn://server/trunk/stuff/*' does not exist in revision 123
といったような、訳の分からないエラーメッセージが表示されて、失敗になってしまう。
短くて、悲しい回答だけど、これを行うビルトインの方法はないんだ。 多くのコマンドは、mvで見たように、任意個の引数を扱うことができない。 また、何れにしても、Subversionは "*" のようなワイルドカードを、shell がやっているようには、展開しない。
もしも、全てのソースファイルと移動先のディレクトリとを含んだ作業コピーを持っているのであれば、シェルのワイルドカード機能を移動処理に利用する事ができる。 例えば、こんな感じだ(Bash用)。
for i in stuff/*; do svn mv $i some-other-dir; done svn ci -m "moved all the stuff into some other dir"
また、移動元のファイル名のリストを準備した上で、そのリストの各要素に対して "svn mv" を行うことも出来る。 こんな感じになるだろう。
s=svn://server/trunk/stuff/ svn ls "$s" | \ while read f do svn mv "$s/$f" svn://server/trunk/some-other-dir -m "Moved just one file" done
但し、この方法は、ソースファイル毎に commit が発生することには注意して欲しい。 先の方法(作業コピーを使う方法)が全体で一度しか commit しないのとは、対照的だ。
「svnmucc」または「mucc」と呼ばれるプログラムがあり(名前は、Subversion のバージョンに依存する)、ソースコードが Subverision と共に配布されているのだけど(Subversion 1.4 以前では .../contrib/client-side/mucc/mucc.c に、Subversion 1.5以降では、.../tools/client-side/svnmucc/svnmucc.cにある)、このプログラムは、今回の問題を解決するのに使えると思う。
注意: release 1.5 で、Subversion は「cp」と「mv」で複数のファイルを同時に指定することが可能になった。
サードパーティのコードに対するローカルな変更管理に対し、サードパーティからのアップグレードも含め、Subversion を使いたいという要求を、しばしば耳にする。 即ち、分岐した自身のブランチを維持しつつ、上層の提供元から公開される新しいリリースも組み入れたいわけだ。 これは、一般的にベンダーブランチと呼ばれていて(この名称は Subversion 以前から使われている)、Subversion を使ってこれを管理するテクニックは、ここで説明されている。
もし、ベンダーコードがリモートの Subversion リポジトリで管理されているならば、ベンダーコードのコピーを管理に、Pistonが利用できる。
次善の策ではあるけれど、もしsvn_load_dirs.plを使うのに多くの時間を費やしていたり、よりラクな方法を探しているならば、Jon Steven によって書かれた Subversion Vendor Branches Howtoのステップ・バイ・ステップ解説を参照してみよう。 この方法では、古いコードを新しいコードへ上書きする際、Subversion のバックエンドが提供している容量の増加を抑制する為の手法は用いない。 ベンダーコードのインポート毎に、完全に新しいコピーが作成され、同一ファイルに対しても容量削減は行わない。
あなたのリポジトリで利用されている Berkeley DB データベースは、中断に対して弱い。データベースにアクセスしているプロセスが、環境を「綺麗に」閉じずに消えてしまった場合、データベースは、首尾一貫性が失われた状態になってしまう。 これが生じる原因は、一般的に次のようなものだ。
ほとんどの場合、こうした現象に対しては、「svnadmin revover」を実行すべきだ。 これは、リポジトリを正しい状態へと引き戻す。 詳細に関してはこちらの質問を参照。 ディスク容量不足が、度重なるチェックアウトや更新によって引き起こされている場合、リポジトリのクラッシュを引き起こす可能性がある。 この場合にはリカバリは不可能だ(というわけで、バックアップを取ろう)。
セグメンテーションフォルトや、強制的な kill、またディスク不足はかなり稀だ。パーミッション問題は非常に一般的である。 一つのプロセスがリポジトリへアクセスし、誤って所有権やパーミションを変更してしまう。 その後、他のプロセスがアクセスを試み、そのパーミッションによってお陀仏、というわけだ。
これを防ぐ最良の方法は、リポジトリのパーミッションと所有権を正しく設定すること。 我々の推奨に関してはこちらを参照の事。
あなたのリポジトリは壊れていないし、データも失われていない。 あなたのプロセスが、リポジトリへ直接アクセスしている(mod_dav_svn、svnlook、svnadmin または、file:// URL を使っている)ならば、データへアクセスするために、Berkeley DB を利用している。 Berkeley DB は、ジャーナリングシステムで、つまり、これから行おうとしている操作を、実際に行なう前に、全て記録する。 もし、あなたのプロセスが(Control-Cやセグメンテーションフォルトによって)終了した場合、未終了の作業内容が書かれたログファイルと共に、ロックファイルが残されたままとなる。 そのデータベースへアクセスを試みる他のプロセスは、そのロックファイルが消え去るまで、ただハングアップし続けることになる。 リポジトリを目覚めさせる為には、Berkeley DB に対し、作業を終了するか、データベースを首尾一貫している以前の状態へと巻き戻すかを指示する必要がある。
WARNING:もし、リカバリ実行中に他のプロセスがリポジトリへアクセスしたら、そのリポジトリは深刻なダメージを受ける可能性があるよ!
絶対的に確認しなければならないことは、この作業実行前に、リポジトリに対するアクセスを禁止すること(Apache をシャットダウンするとか、'svn' の実行属性を落としちゃうとか)。 このコマンドは、データベースを所有し、管理しているユーザ権限で実行しなければならず、root として実行してはならない。rootで実行した場合、データベースを管理している非rootユーザ(多くの場合、これは、あなただったり、Apacheプロセスだったりするんだけど)ではオープンすることのできないroot所有のファイルが、dbディレクトリへ残されてしまう。 また、recover を実行する場合には、正しい umask が設定されていることも確認すること。これを忘れると、リポジトリへのアクセスを許可されているグループに属しているユーザが、締め出されてしまうことになるだろう。
まず次のコマンドを実行しよう。
svnadmin recover /path/to/repos
コマンドが終了したら、リポジトリ内のdb
ディレクトリ内にあるパーミションを確認しよう。
時には、"svnadmin recover"が上手く動作しない場合がある。この場合、こんな感じのエラーメッセージが表示されるかもしれない。
Repository lock acquired. Please wait; recovering the repository may take some time... svnadmin: DB_RUNRECOVERY: Fatal error, run database recovery svnadmin: bdb: Recovery function for LSN 175 7066018 failed on backward pass svnadmin: bdb: PANIC: No such file or directory svnadmin: bdb: PANIC: fatal region error detected; run recovery
または、こんな感じだ。
Repository lock acquired. Please wait; recovering the repository may take some time... svn: DB_RUNRECOVERY: Fatal error, run database recovery svn: bdb: DB_ENV->log_flush: LSN of 115/802071 past current end-of-log of 115/731460 svn: bdb: Database environment corrupt; the wrong log files may have been removed or incompatible database files imported from another environment [...] svn: bdb: changes: unable to flush page: 0 svn: bdb: txn_checkpoint: failed to flush the buffer cache Invalid argument svn: bdb: PANIC: Invalid argument svn: bdb: PANIC: fatal region error detected; run recovery svn: bdb: PANIC: fatal region error detected; run recovery [...]
このような場合には、Berkeley DB 自体のdb_recoverユーティリティを試してみよう(dead link: http://www.oracle.com/technology/documentation/berkeley-db/db/utility/db_recover.html) db_recover ドキュメントを参照のこと)。 このコマンドは、大抵、Berkeley DB がインストールされた 「bin/」サブディレクトリの中にある。例えば、Berkeley DB をソースからインストールしたのならば、/usr/local/BerkeleyDB.4.2/bin/db_recoverかもしれない。 Berkeley DB が予めインストールされたシステムでは、単純に /usr/bin/db_recoverかもしれない。 もし、複数のBerkeley DB がインストールされているならば、試そうとしているdb_recover のバージョンが、リポジトリの使っている Berkeley DB のバージョンと一致していることを確認しよう。
db_recover を 「-c」 フラグ(「catastrophic recovery: 悲劇からの復活」)付きで実行する。 冗長性の為に 「-v」 を付けても良いし、「-h」へ引数を渡して、どの db 環境をリカバリーするのかしても良い(これで、該当ディレクトリへ cd する必要がなくなる)。 つまりこんな感じだ。
db_recover -c -v -h /path/to/repos/db
このコマンドを、リポジトリを所有しているユーザとして実行しよう。 ただし、今一度、これを実行している間は、(svnserver や Apache をシャットダウンするなどして)他のプロセスがリポジトリへアクセスしないことを確認すること。
http:// アクセスを使っている場合、「Cannot allocate memory」エラーは、httpd エラーログの中に、こんな感じで書かれている。
[Wed Apr 07 04:26:10 2004] [error] [client 212.151.130.227] (20014) Error string not specified yet: Berkeley DB error while opening 'strings' table for filesystem /usr/local/svn/repositories/svn/db: Cannot allocate memory [Wed Apr 07 04:26:10 2004] [error] [client 212.151.130.227] Could not fetch resource information. [500, #0] [Wed Apr 07 04:26:10 2004] [error] [client 212.151.130.227] Could not open the requested SVN filesystem [500, #160029] [Wed Apr 07 04:26:10 2004] [error] [client 212.151.130.227] (17) File exists: Could not open the requested SVN filesystem [500, #160029]
これは、通常のオペレーションでは発生しない筈だが、発生した場合の解決策は、ここで述べたように、データベースリカバリを実行することだ。 もし、これが何度も起こるようならば、多分、db/DB_CONFIG ファイルの中のデフォルトロックパラメタ(set_lk_max_locks、set_lk_max_lockers、並びにset_lk_max_objects)値を引き上げる必要があるだろう。 既存リポジトリの DB_CONFIG を変更した場合には、その後にリカバリを実行することを忘れないこと。
あなたの作業コピーは壊れていないし、データも失われていない。 Subversionの作業コピーはジャーナリングシステムで、つまり、これから行おうとしている作業を、実際に実行する前に、全て記録する。 もし svn クライアントプログラムが(セグメンテーションフォルトや kill によって。Control-Cは含まない)手荒に終了された場合、1つ以上のロックファイルが、未終了の作業に関するログファイルと共に、残されたままになっている('svn status' コマンドを実行すると、ロックされたディレクトリの隣に'L'が表示されるだろう)。 作業コピーへとアクセスする他の全てのプロセスは、このロックを見つけると、失敗となる。作業コピーを目覚めさせる為には、svn client に対し、作業を終了させる旨、指示する必要がある。単純に次のコマンドを実行しよう。
svn cleanup working-copy
この現象を引き起こす3つの可能性がある。
失敗したコミットの残骸が、作業コピーに残っている。
新しいリビジョンがサーバへと追加され、クライアントがpost-commit 管理タスク(ローカルなテキストベースコピーの更新中を含む)を実行している間に、あなたのコミットが、まずい状況になったのかもしれない。 これは様々な理由で起こる可能性があり、(稀には)データベースのバックエンドの問題によって、または、(より一般的には)まさにマズいタイミングでネットワークが切断した等が考えられる。
この現象が発生した場合、あなたが今コミットしようとしているその変更は、既にコミットされている可能性がある。 'svn log -rHEAD' を使って、「失敗したと考えられている」あなたのコミットが、実際には成功しているかどうかを確認してみよう。 もしコミットが成功していたならば、'svn revert' を使ってローカルな変更を元に戻し、その後'svn update'を行って、サーバから変更を取得しよう('svn update'だけが、ローカルコピーを最新にする、という事に注意。revert はそれを行わないよ)。
混在リビジョン
Subversion でコミットを行うと、クライアントは、そのコミットが関与したノードのリビジョン番号だけを変化させる。 作業コピーの中にある全てのノードを変化させるわけではない。 これは、最後にコミットした時期に応じて、単一の作業コピー内に於いても、ファイルやサブディレクトリが異なるリビジョンになるかもしれない、ということだ。ある種の操作(例えばディレクトリの属性変更)では、もしリポジトリ内に、より新しいバージョンのノードが存在する場合には、データの喪失を防ぐため、コミットが拒否される。 詳細は、Version Control with SubversionのMixed revisions have limitationsを参照の事。
この問題は、作業コピー内で 'svn update' を実行することにより解消することが出来る。
実際に古いのでは? つまり、あなたがファイルのコピーを最後に更新してから、既に誰かがそのファイルを変更していて、そのファイルに対して変更をコミットしようとしているのではないだろうか? これも 'svn update' で解決できるよ。
新しいファイルをパッチへ含める為に、svn diffコマンドで生成されるパッチに、その新規ファイルが含まれるように、恐らくあなたは、svn addコマンドを実行したのだと思う。 もしそのパッチがコードベースへとコミットされ、その後svn updateを実行すると、あなたは、次のようなエラーメッセージを目にするはずだ。"svn: Failed to add file 'my.new.file': object of the same name already exists".
このエラーメッセージが表示される理由は、未だ自身の作業コピー内に、ファイルのローカルコピーが残されているためだ。 この問題を解決する手順は次の通り。
リポジトリから取得した新しいファイルと、あなたのオリジナルのファイルと比較してみるのも良いだろう。
Subversion はリポジトリへのアクセスにプラグインシステムを採用していて、現在、次の3つのプラグインがある。 ra_local は、リーカルリポジトリへのアクセスするためのもの、ra_davはWebDAV 経由でリポジトリへアクセスするためのもの、そして、ra_svn は svnserve サーバ経由で、ローカルまたはリモートのリポジトリへアクセスするためのものだ。 Subversion を使って何らかの操作を行おうとすると、プログラムはそのURLスキームに応じて、プラグインを動的にロードしようとする。 'file://'URLでは ra_localをロードしようとするし、'http://' URLでは ra_dav をロードしようとする、といった具合だ。
あなたが目にしたエラーは、動的リンカ/ローダがロードするプラグインを見つけられなかった、ということ。 これは通常、Subversion を共有ライブラリと共にビルドした上で、'make install' を事前に実行せずに、実行させようとした時に発生する。別の可能性としては、make install は実行したんだけど、動的リンカ/ローダが認識できない場所に、ライブラリがインストールされた、というもの。 Linuxでは、リンカ/ローダにライブラリを見つけさせるためには、そのライブラリディレクトリを/etc/ld.so.sonf へ追加し、ldconfig を実行しなければならない。もし、こうしたくない、または root 権限をもっていない場合には、LD_LIBRARY_PATH環境変数へそのライブラリディレクトリを指定することでも可能だ。
多分、あなたのシステムには古い /usr/local/bin/apr-configと/usr/local/bin/apu-configが残っている。 これらを取り除き、一緒にビルドしようとしている apr/と apr-util/ が完全に最新のものであることを確認した上で、もう一度試してみよう。
恐らく、最新のプラットフォームSDKを入手する必要がある。 VC++6.0に同梱されている版は、最近の使用には適していない。
こんな感じ。
svn import file:///d:/some/path/to/repos/on/d/drive
詳細は Subversion Book のRepository URLsをどうぞ。
VS.Net は ASP.Net と呼ばれるサブシステムをもっていて、これは、IISを通じたリモート公開を行うためにWebDAVを利用する。 このサブシステムは、「.」で始まるどのようなパス名も受け付けない。 これはリモートに Subversion の作業コピーをリモート公開しようとするときに問題となる。 なぜならば、「.svn」サブディレクトリが存在するからだ。エラーメッセージとしては、「unable to read project information」といったものが、表示される。
これを迂回するには、SVN_ASP_DONT_NET_HACK環境変数へ適当な値を設定しよう。 これは Windows クライアントに対し、作業コピー内では、ディレクトリの名前として「_svn」を使うように指示するためのものだ。 詳細は、Subversion 1.3 のリリースノートに書かれた関連セクションを参照のこと。 また、この質問では、管理ディレクトリ名をカスタマイズする他の方法に関して説明している。
例えば、あるユーザがレポートしてくれたんだけど、ローカルアクセスでは問題なく動作する import が、
$ mkdir test $ touch test/testfile $ svn import test file:///var/svn/test -m "Initial import" Adding test/testfile Transmitting file data . Committed revision 1.リモートホストからでは動作しない。
$ svn import http://svn.sabi.net/test testfile -m "import" nicholas's password: xxxxxxx svn_error: #21110 : <Activity not found> The specified activity does not exist.
我々は、httpd プロセスが REPOS/dev ディレクトリへ書き込みできないときにこの現象が生じることを確認している。 パーミションを確認し、Apacheがdav/ ディレクトリ(や、勿論 db/ へ)書き込み出来ることを確認して欲しい。
Window XP Service Pack 1 をインストールする必要があるね。
hacking.html#net-traceを参照のこと。
簡単に言えば「それがあなたの為だから」。
Subversion はあなたのデータを守ることに対して大変に高い優先度を設定している。 これは、単にバージョン管理されたデータに対してだけではない。 既にバージョン管理されているデータに対する改変や、バージョンコントロールシステムへ追加されることが指示されているファイルに対しても、慎重に取り扱われる。
svn revertコマンドに対し、たとえターゲットが '.' だけだったとしても、明示的なターゲット指定を必要としたのは、これを達成するための一つの手段だ。 この要求は(再帰処理を行いたい場合には、--recursive(-R)フラグを指定する必要がある、という要求も含めて)、あなたが実行しようしている内容を、しっかりと認識して欲しいからだ。 ひとたびファイルが元に戻されてしまえば、ローカルで行なわれた変更は永遠に失われてしまうことになるのだから。
あなたの apr-util は DB-3 とリンクされていて、svn は DB-4とリンクされている。 残念ながら、これらのDBシンボルは違わないんだ。 mod_dav_svn が Apache のプロセス空間へロードされると、結局 apr-util の DB-3 に対してシンボル名を解決することになる。
確実な解決方法は、apr-util を DB-4 に対してコンパイルすること。 次の適切なスイッチを apr-util か apache の configure 実行時に引き渡せばよい。 「--with-dbm=db4 --with-berkeley-db=/the/db/prefix」
これは、Sunversion 自体の問題ではないんだけど、Subversion ユーザが出くわす問題だ。
Red Hat9 と Fedora は、NPTL(the Native Posix Threads Library)をサポートしたカーネルを前提としている Berkeley DB と共に配布されている。
RedHat が提供しているカーネルにはこのサポートが組み込まれているけれど、もしあなたが自分でカーネルをコンパイルする場合には、NPTLサポートを組み込まないかもしれない。 この場合、こんな感じのエラーが表示されることになるだろう。
svn: Berkeley DB error svn: Berkeley DB error while creating environment for filesystem tester/db: Function not implemented
この問題は、次にあげる何れかの解決方法で修正可能だ。
LD_ASSUME_KERNEL
環境変数が2.2.5
にセットされているかを確認し、もし設定されている場合には、Subversion(Apache)を起動する前にその設定を解除する(多分、この変数は Red Hat 9 上で Wine または Winex を実行するために設定したのだろう)。Berkeley DBのNPTLバージョンを使う為には、NPTLをサポートした glibc ライブラリも一緒に使う必要がある。これは大抵 i686 版を意味するだろう。 詳細は、https://svn.haxx.se/users/archive-2004-03/0488.shtmlを参照のこと。
リポジトリに対して、Apache 経由での匿名書き込みを許可している場合、Apache サーバは決して SVN クライアントにユーザ名を求めないし、認証無しでの書き込み処理を許可する。 その為、Subversionは誰か操作を行っているのか分からず、ログはこんな感じになる。
$ svn log ------------------------------------------------------------------------ rev 24: (no author) | 2003-07-29 19:28:35 +0200 (Tue, 29 Jul 2003)
Apacheに対してアクセス制限を行う為の設定方法は、Subversion bookを参照のこと。
これは、ファイルシステムの変更を監視している、様々な Windowsのサービス(アンチウイルスソフトウェアやインデキシングサービス、COM+イベント通知サービス)によって引き起こされる。 これは、実際には Subversion のバグではない為、修正するのが困難だ。 現状の調査結果のまとめがここにある。 多くの人々にとって、この問題の発生頻度を削減するための回避策が、revision 7598で実装された。 もし、これよりも以前の版を使っているならば、最新の版へアップデートしてみて欲しい。
これは、通常、システムにエントロピーが不足している為に生じる。 多分、ハードディスクやネットワーク割り込みといったソースからエントロピーを集めるよう、システムを設定する必要がある。 この変更を行う方法は、システムのマニュアルページ、特に random(4)と rndcontrol(8) を参考にしてほしい。
httpd.conf の設定ミスが原因。大抵、このエラーは、Subversionの仮想「location」を、2つの異なるスコープ内で同時に存在するよう、定義してしまっている場合に発生する。
例えば、リポジトリを<Location /www/foo>として公開していて、一方 DocumentRoot も/wwwとして設定している場合、問題が生じる。 /www/foo/barへのリクエストが発生した場合、Apache は/foo/barという名前を持つ実際のファイルをDocumentRootの中から探せばいいのか、mod_dav_svn に対して/www/fooリポジトリの中から/barというファイルを取得してくるように指示すればいいのか分からない。 通常、前者が勝つことになり、結果、「Moved Permanently」 エラーとなる。
解決策としては、リポジトリの<Location>を、通常の Web 共有として既に公開されている領域とオーバーラップしないようにするか、もしくはその中へ収めるべきだ。
または、リポジトリ URL と同名のオブジェクトを、Web ルートへ置くことでも構わない。 例えば、あなたの Web サーバのドキュメントルートが /var/www にあり、Subversion のリポジトリが/home/svn/repoに位置していると想定しよう。 従って、リポジトリをhttp://localhost/myrepoで提供するように Apache を設定すればよい。 もし、その後に/var/www/myrepoディレクトリを作った場合には、301 エラーを引き起こすことになるだろう。
これは、恐らく、Apache HTTPサーバ(バージョン2.0.48以前)の既知のバグだ。 パッチをhttps://bz.apache.org/bugzilla/show_bug.cgi?id=25040から取得することができる。 併せて、あなたの状況が、https://issues.apache.org/jira/browse/SVN-1608に書かれている内容と一致するかどうかを調べて見た方が良いだろう。
コンフィギュレーション時とビルド時に、CFLAGS 環境変数へ-qlanglvl=extended を設定して、xlc を少し融通の利くようにしてあげよう。 これで、エラー無しにコンパイルできるようになる筈だ。 詳細は、https://svn.haxx.se/dev/archive-2004-01/0922.shtmlならびに、関連スレッドを参照のこと。
issue 695を参照の事。 svn checkout -Nの現在の実装は、少し壊れている。 このコマンドの実行結果は、不足エントリのある作業コピー、ということになるんだけど、その「不完全性」には気づかない。 どうやら、CVSユーザのある種の人々は、このパラダイムへ幾分依存しているようなんだけど、Subversion の開発者は、そうではない。 現状では、あなたの手続きを変更する以外、回避策は存在しない。 リポジトリの個別のサブディレクトリ群をチェックアウトし、手動で作業コピーへ重ねてあげよう。
この件に関するエラーメッセージは、少し誤解を招いている。恐らく Apache は、mod_dav_svn.soが依存しているDLLを読み込むことが出来ないのだろう。 Apache をサービスとして実行している場合には、通常のユーザと同じPATHを有していないのかもしれない。 libdb4*.dll、intl3_svn.dll、libeay32.dllそしてssleay32.dll がApache\binかApache\modulesの中に存在することを確認し、存在しない場合には Subversion のインストールされたディレクトリからコピーしよう。
もし、それでもまだ問題が解決しない場合には、mod_dav_svn.soに対してDependency Walkerのようなツールを使用し、未解決な依存性が他に存在しないか確認して調べてみよう。
フックは、外部プログラムを呼び出すことを期待されているんだけど、その呼び出しが、全然生じていないよう感じだ。
Subversion はフックスクリプトを起動する前に、全ての環境変数を取り除く。その中には、Unixでは $PATHが、Windows では %PATH% が含まれる。結果、スクリプトでは、絶対パス名の記述された他のプログラムだけを実行可能だ。
Debugging tips:
もしあなたが Linux や Unixを使っているならば、以下の手順に従って、そのスクリプトを「手動で」実行してみよう。
「env」に対する最初の引数は、ダッシュであることに注意。これは、確実に環境を空にするためのものだ。$ env - ./post-commit /var/lib/svn-repos 1234
外部(external)の diff コマンドを使うとき、Subversion は、やや複雑なコマンドラインを組み立てる。 最初は --diff-cmd で指定された値。次に来るのは、--extensions で指定された値(もし --extensions が空ならば、無視される)、または、--extensions が指定されていない場合(または''が指定された場合)には '-u'。 3番目と4番目には、Subversion は -L と最初のファイルラベル(例えば、"project_issues.html (revision 11209)")を引き渡す。 5番目と6番目には、別の '-L' と2番目のラベル。 7番目と8番目には、1番目と2番目のファイル名(例えば、「.svn/text-base/project_issues.html.svn-base」と「.svn/tmp/project_issues.html.tmp」)。
もし、あなたの愛用している diff コマンドが、これらの引数をサポートしていない場合、引数群を無視し、最後のファイル名だけを取り扱う、小さなラッパースクリプトを作る必要があるかもしれない。
警告: Subversion は、外部の diff プログラムを、受信したファイルを変更する為には期待していないことに注意して欲しい。 そうした場合、作業コピーをごちゃ混ぜにしてしまうだろう。
詳細は、issue#2044を参照のこと。
はい、落ち着いて。まずは、深呼吸を1回。
Windows 2000以降の場合、svn 1.2 以上の版は、data の暗号化にWindowsの標準的なAPI を使っている。 この為、該当ユーザだけが、キャッシュされたパスワードを解くことができる。
Mac OS Xの場合、svn 1.4 以上の版では、あなたの svn パスワードを暗号化し、保存する為に、システムの Keychain 機能を使っている。
Subversion 1.6 では、UNIX/Linuxに於いてこの件へ取り組むつもりだ。 GNOME KeyringとKWallteのサポートが実装されつつあり、共に、パスワードを暗号化した上でディスクへ格納する手助けとなる。 これらのプログラムは、コンパイル時ならびに、実行時に必要だ。 もし存在しない場合には、クライアントは、平文でパスワードを保存しようと、フォールバックするけれど、でも、決して最初に許可を得ることなく、パスワードを平文でキャッシュしないように変更されている。
Subversion1.5以前の場合、UNIX/Linuxでは、パスワードは、~/.subversion/auth/ へ平文で格納されることになる。 しかし、注意してもらいたいのは、そのキャッシュされたパスワードが格納されているディレクトリ(大抵 ~/.subversion/auth)のパーミションは、700に設定されていて、即ち、あなただけが読みだし可能となっている。
とはいえ、もしあなたが本当に気に病んでいるならば、パスワードのキャッシュ機構を、完全に off にすることができる。svn 1.0 クライアントの場合、ランタイム設定ファイルへ 'store-auth-creds = no' と書くだけだ。svn 1.1 以上のクライアントの場合、より狭い範囲にのみ適用される 'store-passwords = no' を使うことができる(つまり、サーバ証明は、まだキャッシュされる)。 パスワードキャッシングに関するより詳細な説明は、Nightly Build 版Subversion bookの第6章、「Client Credentials Caching」を参照のこと。
最後に、CVS は長期に渡り、パスワードを .cvspass ファイルへ保存している、ということを指摘しておこう。 .cvspass に書かれたパスワードは、暗号化されているように見えるけど、実際には、ただ非常に簡単な、本質的には rot13 同等のアルゴリズムでスクランブルされているだけだ。 これは簡単にクラックされ得る。 スクランブルの有益性は、ただ、ユーザ(例えば root)が、予期せずパスワードを目にしてしまうのを防ぐために過ぎない。 Subversion に於いては、この点に対して深く気にしている人は存在しない。 もし、あなたが興味を持っているならば、dev@リストへパッチを送って欲しい。
Berkeley DB 4.1 は、やや不安定な点のあることが分かっている。 4.0や4.2の方がベターだ。このエラーメッセージは、4.1が時に壊れてしまうことを示す、唯一の兆候である。
問題は、Berkeley DB をバックエンドに使った Subversion リポジトリ構成しているテーブル内の、あるデータベースフォーマットフィールドが壊れつつある、ということだ。 理由は不明だが、ほとんど常に'copies'テーブルで発生し、'btree' タイプから'recno'タイプへと変更となっている。 シンプルな回復方法は以下の通り。 もしこの方法が成功しなかったら、Subversion Usersメイリングリストへ問い合わせてみよう。
APRに於ける0.9ブランチの初期のバージョン(これは Apache 2.0.x とSubversion 1.xで使われているんだけど)では、大きなファイル(2Gb+)のコピーがサポートされていない。 'svnadmin hotcopy' 問題を解決する修正が行われ、APR 0.9.5+ とApaache 2.0.50+ に取り込まれている。 この修正は全てのプラットフォームで動作するわけではないけれど、Linux 上では動作するよ。
Berkeley DB 4.3 より前の版では、svnadmin recoverは Berkeley DB リポジトリをその場でアップグレードするように動作していた。 しかし、Version 4.3 での Berkeley DB の動作変更に伴い、今では、これは失敗してしまう。
リポジトリをその場で Berkeley DB 4.3 以降へアップグレードするには、以下の手順に従おう。
これにより、リポジトリを Berkeley DB 4.3 から利用することが可能だ。
注意: これは、Apache 2.0.x でリポジトリが提供されていることを想定している。
APR 0.9.6 には、Tiger 上で稼動させると生じるバグがあり、64Kb より大きなファイルをチェックアウトしようとすると発症する。 チェックアウト失敗の結果は、しばしば、意味不明なメッセージを伴っている。あなたがクライアント側で目にするかもしれない幾つかのメッセージを以下に示そう(エラー詳細は異なっているかもしれない):
svn: Invalid diff stream: [tgt] insn 1 starts beyond the target view position
svn: Unexpected end of svndiff input
svn: REPORT request failed on '/path/to/repository' svn: REPORT of '/path/to/repository/!svn/vcc/default': Chunk delimiter was invalid
Apache の error_log 中にも、次のようなエラーが書き込まれているかもしれない。
[error] Provider encountered an error while streaming a REPORT response. [500, #0] [error] A failure occurred while driving the update report editor [500, #190004]
このバグの存在を確認するには(あなたがリポジトリを提供しているマシンへアクセスできると仮定しているけど)、file:// URL を使って、チェックアウトを試してみることだ。 これはApacheを経由せずに、直接ファイルシステムへアクセスすることになる。 もし、チェックアウトの結果が完全に上手く行った場合、おそらくこれが原因である可能性が高い。
現在のベストな解は、APR1.2.0+へアップグレードすることだ。
代案としては、Apache の configure 実行前に以下の環境変数を設定した上で、Apache と Subversion とをそれぞれソースから再構築しても良いだろう。
setenv ac_cv_func_poll no
または、Bourne シェル記法ではこんな感じ。
ac_cv_func_poll=no; export ac_cv_func_poll
APR / APRUTILを別々にビルドした(つまり、Apache のtarball に付属している版を使わなかった)場合、APRの configure を実行する前にこの環境変数を設定しなければならない。 というのも、そこが問題の潜んでいる場所だから。
もし、Subversion trunk ソースのビルド時、最後のリンク段階で次の様なエラーが表示されるなら、
/usr/local/apache2/lib/libaprutil-0.so.0: undefined reference to `db_create' /usr/local/apache2/lib/libaprutil-0.so.0: undefined reference to `db_strerror'
おそらく、あなたは Debian GNU/Linux システムを使っていて、'libtool' をアップグレードをする必要があるからだろう(また、Debian のパッケージャーは、'libtool' を少しいじる必要があって、これが Subversion のビルドで幾つかの問題を引き起こしているのかも、とも聞いた。 とはいえ、これは又聞きにすぎない。 私は、この FAQエントリを書く前に、詳細を確認している時間がとれなかったんだ。 ともかく、本件に関して詳細な議論の行われた、https://svn.haxx.se/dev/archive-2006-02/1214.shtmlとそのスレッドを確認して欲しい)。
何れにせよ、2005/11/15 時点の newly-dist-upgraded 'testing'ディストリビューションである Debian GNU/Linux システム上でこの問題に遭遇した時には、唯一の解法は、libtool 1.5.20を、通常の「./configure && make &&sudo make install」手順に従ってソースから構築することだった。 その後、私の Subversion 作業コピーツリーで 'make clean' を実行し、'./autogen.sh', './configure','make'とやって、全てが上手く行くようになった。
この事象に関する別のレポートとしては、https://svn.haxx.se/dev/archive-2003-01/1125.shtmlがあるけど、ここで述べられた解法は、このスレッドの中では言及されていないことに注意して欲しい。
簡潔な答え: svnserverに--listen-host=0.0.0.0オプションをつけて実行しよう。
ちょっとだけ長い答え: FreeBSD デーモンは、デフォルトでは tcp6 しか listen しない。このオプションは、tcp4 でも listen するように指示する。
あなたが登録しようとしているディレクトリには、既に.svnサブディレクトリが存在している。 確かにこれは作業コピーなんだけど、でもこれは、あなたがディレクトリを追加しようとしているのとは異なったリポジトリから取得されたものだ。 これは多分、(svn copyではなく)OSの「copy」コマンドを使って、サブディレクトリをこの作業コピー内にコピーした、または、他の作業コピーをこの中へコピーした為に起こったのだろう。
簡単でキタナイ解法は、あなたの追加しようとしているディレクトリ内にある、全ての.svnディレクトリを削除することだ。 これで、「add」コマンドが動作するようになるだろう。 もしあなたが Unixを使っているならば、次のコマンドで、dir配下にある.svnディレクトリを削除することが出来る。
find dir -type d -name .svn -exec rm -rf {} \;
とは言え、もしこのコピーが同じリポジトリからきたものならば、本当は、そのコピーを消去、もしくは移動させてから、svn copyを使って、正しくコピーするべきだと思う。 これは、履歴を維持することも出来るし、リポジトリ使用量を削減することも出来る。
もしこのコピーが異なるリポジトリからのものだったなら、「何故このコピーを行ったのか」と言う点を自問してみるべきだ。 また、このディレクトリを追加することで、望んでいないディレクトリのコピーがリポジトリへと追加されてしまうことのないよう、注意しよう。
これは、大抵、APRが /dev/random を使うようにコンパイルされていて、サーバが十分なエントロピーを収集できなかった時に発生する。 もし Subversion が、そのサーバ上で APR を使う唯一のアプリケーションであるならば、configureへ--with-devrandom=/dev/urandomオプションを指定してAPRを再コンパイルしても問題はないだろう。 一方、APRを他のプロセスでも使っているシステムの上では、これは行うべきではない。 他のサービスの安全を損なう可能性がある。
これは、OpenSSL 0.9.8 の発生し得る問題だ。古いバージョンへダウングレードする(または、恐らく新しいバージョンへアップグレードする)ことで、この問題を解決できることが知られている。
あなたは、古いバージョン(pre-1.4)の Subversion コマンドラインクライアントとSubclipseの両方を使っている。 あなたは、最近Subclipse をアップグレードし、それ以後、コマンドラインクライアントが次のメッセージを表示するようになった。
svn: This client is too old to work with working copy '/path/to/your/working/copy'; please get a newer Subversion client
これは Subversion の作業コピーフォーマットが非互換なものへと変更された為に生じている。 新版の Subclipse はあなたの作業コピーをバージョンアップし、その為、あなたのコマンドラインプログラム(こちらは旧版)は、それを読めなくなってしまった(この問題は、Subclipse 特有ではない。 この問題は、あなたが1.4以降のコマンドラインクライアントを、より古い版のコマンドラインクライアントと一緒に使った場合にも起こり得る)。 解法は簡単で、あなたのコマンドラインクライアントを1.4以降の版へとアップグレードすることだ。
バージョン管理されていない(また、もしかしたら ignore されている)アイテムが作業コピーにあるような場合、svn switchはエラーになる。 切り替え処理は停止し、作業コピーは半分切り替わった状態のまま取り残される。
不運な事に、もし間違った修正方法を採用した場合、作業コピーは利用不可能になってしまう。 このような事態に陥った場合、時折、ユーザは、svn cleanupするようにと指示される。 しかし、svn cleanupも失敗するかもしれない。 issue #2025を参照して欲しい。
ユーザは手動で、問題を引き起こしたディレクトリやファイルを取り除き、その後svn cleanupを実行して、切り替え処理を継続させることで、この状況から復活させることが可能だ。
素のクリーンなチェックアウトした状態からの切り替えは、エラーになることなく、常に上手く動作することに注意して欲しい。 あなたが開発プロセスの一部としてsvn switchを使っている場合、機能させるためには3つの方法がある。
# 確認した上で、バージョン管理されていないファイルを消去 svn status --no-ignore | grep '^[I?]' | sed 's/^[I?]//' svn status --no-ignore | grep '^[I?]' | sed 's/^[I?]//' | xargs rm -rf
幾つかの例が、ここ issue 2505にある。 問題は、svn client が切り替え処理を安全に、且つ、バージョン管理されていない如何なる物も消去することなしに行おうという点にある。
このような問題を示すために、ここで2つの典型的な例を示そう。 ここではカバーされていない、他の svn switch エラーもあるけれど、それらは、素のチェックアウトから切り替えることで回避できる。
wc/$ svn switch $SVNROOT/$project/branches/$ticket-xxx svn: Won't delete locally modified directory '<dir>' svn: Left locally modified or unversioned files
バージョン管理されてない全てのファイルを除去し、切り替えを継続させることで、この状況から回復できる。
wc/$ svn switch $SVNROOT/$project/branches/$ticket-xxx svn: Won't delete locally modified directory '<dir>' svn: Left locally modified or unversioned files
この場合、単にバージョン管理されていないアイテム群を取り除くだけでは回復できないだろう。 cleanupは失敗に終わるが、しかし、svn switch は「svn cleanup」を実行するよう指示してくる。
wc/$ svn switch $SVNROOT/$project/branches/$ticket-xxx svn: Directory '<dir>/.svn' containing working copy admin area is missing wc/$ svn cleanup svn: '<dir>' is not a working copy directory wc/$ svn switch $SVNROOT/$project/branches/$ticket-xxx svn: Working copy '.' locked svn: run 'svn cleanup' to remove locks (type 'svn help cleanup' for details)
このディレクトリ(と、同様のエラーを繰り返し「switch」を妨げる他の全てのバージョン管理されていないファイル)を消去した上で切り替えを継続することで、回復できるだろう。
TortoiseSVN クリーンアップエラーは、ちょっと違っている。こんな感じだ。
Subversion reported an error while doing a cleanup! <dir>/<anotherdir> is not a working copy directory
ここで述べた各事例に於いて、「svn switch」が失敗した場合には、作業コピー半分切り替わった状態のままになってしまう。 「svn status」では、切り替わったアイテム(トップディレクトリと異なっている)には「S」を付けて、また、問題のあるディレクトリには「!」を付けて、また、問題のあるファイルには「~」を付けて(ロックを示す L が付くかもしれない)示してくれる。 こんな感じだ。
wc/$ svn status ! . ! <dir> S <switched_things> ~ <dir>/<thing_that_is_now_unversioned>
Naming a File(ファイルの名前付け)に関する WindowsAPI ドキュメントを注意深い解読により、これが生じた原因に関する、最も一般的な理由を解き明かすことが出来る。 手短に言えば、Windowsパス関数群のUnicodeバージョンを使っていて、且つ、相対パス指定ではなく絶対バス指定を使っている場合に限り、非常に長いパス名を指定することができる。 幸いにも、Subversion が使っているApache Portable Runtime(APR)ライブラリは、絶対パス名(C:\WorkingCopy\file.txtなど)を、Windows API が要求している形式(\\?\C:\WorkingCopy\file.txt)へ透過的に変換することが可能であり、また逆変換も可能だ。 残念な点は、この長いパス名の恩恵は、絶対パス名を使ったときにしか受けられない、ということだ。
もしパス名の長さが、あなたの直面している問題の唯一の原因であるように思えるならば、相対パスではなく(また、何も指定しないのではなく)、絶対ターゲットパス名を Subversion のコマンドラインクライアントへ指定してみよう。 言い替えれば、次のように指定したり、
C:\> svn up WorkingCopy
また、
C:\> cd C:\WorkingCopy C:\WorkingCopy> svn up
とする変わりに、
C:\> svn update C:\WorkingCopy
とする、ということだ。 もし、問題が消え去ったならば、おめでとう! あなたは Windows のパス長制限にぶちあたっていたわけで、そして今、その回避方法を理解したわけだ。
どうしてこの問題は、TortoiseSVN では発生しないんだろう? それは、TortoiseSVN は Subversion API に対して、常に絶対パス名を引き渡しているからだ。
では、なぜ、Subversion コマンドラインクライアントは、常に入力を絶対パスへと変換し、それを使う、という風にしないんだろう? Subversion 開発者達はある原則に従っている。その原則とは、ユーザ体験の観点から、ツールの出力としてパスを表示する場合には、入力として渡されたパスの記法に合わせるべきだ、というものだ。 また、ある相対パスを絶対パスへと変換することは簡単な作業なのだか、逆変換は、複雑性で溢れている(言い替えれば、我々の優先度リストの上位には位置していない、困難な問題だということだ)。
時々、作業コピーのメタデータフォーマットは、マイナーリリース間で互換性を持たずに変更になる。例えば、Subversion 1.4.4で作られた作業コピーを有しているとして、でも、ある日、Subversion 1.5.0 を試してみることにした。 その後、1.4.4へ戻そうとするものの、でもそれは機能しない。 上記のエラーが表示されるだけだ。
これは、1.5.0 があなたの作業コピーフォーマットを、ある新しい機能(今回の例では、チェンジリスト、keep-localフラグ、そして、可変深度ディレクトリ)をサポートするべく、アップグレードしたためだ。 1.4.4 はこれらの新機能に関しては何も知らないが、少なくとも、作業コピーのフォーマットが、自分の扱うことが出来ない、何やら上位の版へとアップグレードされている、ということだけは認識することが出来る。
1.5.0 では、正当な理由で作業コピーをアップグレードした。 というのは、1.4.4 は、これらの新機能について知らないから、もし 1.4.4 が作業コピーのメタデータに触れたならば、重要な情報が消失し、場合によっては破壊してしまうかも知れない、ということに気がついたからだ(例えば、issue#2961を参照の事)。
しかし、この自動アップグレードという振る舞いは、あなたが、ただ新しい Subversion のリリースを、本格的にインストールするのではなく、ただ試してみたいだけ、という場合には、煩わしいものだろう。 この為、我々は安全に作業コピーをダウングレードさせるスクリプトを配布している。
http://svn.collab.net/repos/svn/trunk/tools/client-side/change-svn-wc-format.py
「--help」オプションを付けて、スクリプトを実行することで、使い方が表示される。 Subversion の将来の版がリリースされた場合、起こりうるダウングレードのシナリオと、その影響とを記して、このFAQエントリを最新状態に保つように努力するつもりだ。
Neon ライブラリは Subversion サーバとクライアントとを HTTP を介して接続するために使われるのだけれど、通常、静的ライブラリとしてビルドされる。 しかしこれは、その後で、別の動的ライブラリと結合される。 これにより、64-bit AMD システム上では、ビルドプロセスの最中に次のようなエラーを引き起こす。
subversion-1.4.6/neon/src/.libs/libneon.a(ne_request.o): relocation R_X86_64_32 against `a local symbol' can not be used when making a shared object; recompile with -fPIC /home/jrandom/subversion/subversion-1.4.6/neon/src/.libs/libneon.a: could not read symbols: Bad value
これに関しては開発者向けリスト上で話題になった。
解決策は、Subversion の configure スクリプトへ「--enable-shared」オプションを付与することだ。
Subversion のテストデータをRAMディスク上に置いた場合、テストの実行速度を劇的に改善することができる。 Linuxシステム上では、以下のコマンドにより、RAM ディスクを好きなタイミングでmount出来る。
mount -t tmpfs tmpfs /path/to/src/subversion/tests/cmdline/svn-test-work -o uid=$USER,mode=770,size=32m
または、もっと永続性のある解法が希望ならば、次のような行を、/etc/fstab
ファイルへ追加しよう。
tmpfs /path/to/src/svn/subversion/tests/cmdline/svn-test-work tmpfs defaults,user,noauto,exec,size=32m
テストの実行に必要となるRAMディスクの最低サイズは、おおよそ、700MBだ。 しかし、テストターゲットへクリーンアップ用のフラグを付与することで、(上のコンフィギュレーションの例で見たように)必要となるスペース容量を、即ちメモリ使用量を、大幅に削減することが可能だ。 クリーンアップは、I/O処理の増加を意味するが、テストデータはメモリ上にある為、パフォーマンスの低下にはつながらないだろう。 こんな感じだ。
make check CLEANUP=true
RAM ディスクの利用に関する、オリジナルの信用できる議論は、https://svn.haxx.se/dev/archive-2003-02/0068.shtmlを参照のこと。
Unix系システムに於いては、make install
を実行する前の状態では、Subversion ソースツリー内にある動的に構築された「実行形式」と言うのは、実のところ、再リンクを行い実際のバイナリを実行させる為のlibtoolによって生成されたシェルスクリプトである。
以下で見るように、これはデバッグ作業を複雑なものにする。
subversion$ gdb subversion/svn/svn
... "/path/to/subversion/subversion/svn/svn": not in executable format: File format not recognized
これは、configure の実行時 --disable-shared
引数を使って、静的結合されたバイナリを作ることで回避することができるし、また、これらをインストールして、デバッガにインストールした版を指定することでも回避できる。
しかし、多くの場合、ソースツリーのただ中でデバッグできることが、必要だったり便利だったりする。
そこで、デバッガ内で実バイナリを実行できるように、シェルスクリプトの最後のexec
文を編集しよう。
gdb を使うならば、exec "$progdir/$progname"
をexec gdb --args "$progdir/$progname"
に置き換える、ということだ。
このトリックは、libtoolが生成したシェルスクリプトに対してホワイトボックステストを実行する場合にも、大変に有益だよ。
デフォルトの場合、gcc はしばしばプライベート変数や関数を、適切な操作へとインライン展開することにより、最適化した上で除去する。これは、コードをデバッガで追っているときには、面倒なステップとなる。
unix系のシステムでは、make
時に最適化を行わせないようにする事で、回避可能だ。
subversion$ make EXTRA_CFLAGS=-O0
(これは「ダッシュ、オー、ゼロ」だよ)。また、configure
実行時に、次のようにすることで、この変更をより永続性のあるものへとすることが出来る。
subversion$ ./configure --enable-debug
実運用向けのインストール時には、Subversion をソースからインストールする前に、余分な引数を与えずに make
やconfigure
を再実行して、この操作を元に戻すことを忘れないように。
Subversion クライアントは、mod_dav_svn サーバモジュールに対して、WebDAV/DeltaV プロトコルのサブセットを話す。端的な回答は次の通り。
OPTIONS, PROPFIND, GET, REPORT, MKACTIVITY, PROPPATCH, PUT, CHECKOUT, MKCOL, MOVE, COPY, DELETE, LOCK, UNLOCK, MERGE
プロトコルの詳細は、ここに記載されている。
http://svn.collab.net/repos/svn/trunk/notes/webdav-protocolSee Poul-Henning Kamp's post to freebsd-hackers: https://www.freebsd.org/doc/en_US.ISO8859-1/books/faq/misc.html#BIKESHED-PAINTING.
Jim Blandy、彼は Subversion の命名とリポジトリデザインを行ったんだけど、「Subversion」を「Subversion」と発音している。
Subversion のソースコードを通して、幾つもの「baton」オブジェクトへの参照が存在する。 これは、関数に対してコンテキストを提供するただのvoid*データ構造だ。他のAPIでは、これらはしばしば、void *ctxやvoid *userdataと呼ばれるが、Subversion の開発者は、この構造を「batons」と称している。 というのも、これらは相当数、引き回されることになるからだ。
wedged リポジトリとは:
Subversion リポジトリは、2つの異なる内部パーツから構成される。 ワーキング区画と、ストレージ区画だ。 Wedged リポジトリとは、ワーキング区画には何らかの理由でアクセスすることができないが、ストレージ区画は問題のないリポジトリのことを言う。 従って Wedged リポジトリでは、データの損失は生じていない。 但し、リポジトリへアクセス出来るようにする為には、ワーキング区画を修正する必要がある。 その方法は、このエントリを参照のこと。
corrupted リポジトリとは:
corrupted な Subversion リポジトリとは、ストレージ区画がダメージを受けているリポジトリのことで、従って、リポジトリ内に於いて、一定量のデータ損失が生じている。
The Jargon File の 'wedged'の定義を併せて参照すると良いだろう。