SVNKit(1)
今時SVNのAPI触ってるなんて人に聞かれたら袋叩きにされるのだろうか。 とにかくRepositoryにある内容を取得したい。
ドキュメントを見るとAPIが2段階あるらしいことがわかる。
- high-level api (working copy api)
org.tmatesoft.svn.core.wc
およびorg.tmatesoft.svn.core.wc2
パッケージ- たぶん、実際SVNを使ったツールを開発するにあたっては当然必要になるワーキングコピーをベースにしたユースケースをカバーするAPI
- low-level api
org.tmatesoft.svn.core.io
パッケージ- リポジトリとプロトコルを直接的にインタフェースするとある
- 上記を構成するために使用される低レイヤーのAPIなんだろうか?
- 個人的にはこのレベルでもだいぶユースケースよりな設計の印象を受ける
SVNRepository
APIドキュメントを眺めているとどうやらリポジトリオブジェクトを作ってそこから操作をするらしい。
SVNRepository
オブジェクトを作るにはSVNRespositoryFactory
というファクトリクラスを使うらしいが、その前に接続先のプロトコル(http:
か、svn:
またはsvn+hoge:
か、file:
か)によってセットアップをしてやる必要があるらしい。
if (url.toLowerCase().startsWith("http")) { DAVRepositoryFactory.setup(); } else if (url.toLowerCase().startsWith("svn")) { SVNRepositoryFactoryImpl.setup(); } else if (url.toLowerCase().startsWith("file")) { FSRepositoryFactory.setup(); } else { fail(); }
こんな感じか。url
は普通にsubversionの接続先として使用するURLの文字列。
なんでsvn
の場合だけImpl
がついているのか。ってSVNRepositoryFactory
にそれをさせるわけにいかなかったってことか。しかしファクトリのセットアップを別のクラスに切り出して、そっちを呼ばせるというのも、なんだか妙な設計に思えるが・・・まあ大した実害はないかもしれない。
続いてリポジトリオブジェクトを作成
final SVNRepository repository = SVNRepositoryFactory.create(SVNURL.parseURIEncoded(url)); final ISVNAuthenticationManager authenticationManager = SVNWCUtil.createDefaultAuthenticationManager(user, password.toCharArray()); repository.setAuthenticationManager(authenticationManager);
ISVNAuthenticationManager
はその名のとおり接続時の認証情報を管理してくれるものらしい。この場合は単純にhttpのベーシック認証に渡すユーザ名とパスワードをSVNWUtil
というユーティリティに渡してインスタンスを作ってもらっている。なんでパスワードがchar
配列なのかよくわからないが、これは単にパスワードの平文文字列。たぶんSSH経由のSVNとかだとこの辺のやり方は認証方式に応じて変わるんだろう。
ISVNEditor
でとりあえずチェックアウトはこんな感じになるが
repository.checkout(-1, "trunk", true, new ExpEditor());
最後の引数に要求されているExpEditor
はISVNEditorを実装したオブジェクトで、どうもチェックアウト実行中にはリポジトリ中の変更情報が順に流れてくるのでそれを処理するハンドラというか、Visitorのようなものを実装する必要があるようだ。ExpEditor
自体は今回動きを確認するために適当に作った実装。
とりあえずどんな動きをするのか、ということでこんな構造のリポジトリを作った
[carrotsword trunk]$ ls -la total 20 drwxrwxr-x 2 carrotsword carrotsword 4096 Mar 6 01:55 . drwxrwxr-x 6 carrotsword carrotsword 4096 Mar 6 01:55 .. -rw-rw-r-- 1 carrotsword carrotsword 208 Mar 6 01:55 .project -rw-rw-r-- 1 carrotsword carrotsword 16 Mar 6 01:55 file1.txt -rw-rw-r-- 1 carrotsword carrotsword 7 Mar 6 01:55 file2.txt
一応コミットは何度かに分けてある
[carrotsword trunk]$ svn log --diff ... 略 ... ------------------------------------------------------------------------ r3 | test | 2016-03-04 03:15:19 +0900 (Fri, 04 Mar 2016) | 1 line commit2 Index: file2.txt =================================================================== --- file2.txt (revision 0) +++ file2.txt (revision 3) @@ -0,0 +1 @@ +commit2 \ No newline at end of file Property changes on: file2.txt ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: file1.txt =================================================================== --- file1.txt (revision 2) +++ file1.txt (revision 3) @@ -1 +1,2 @@ -commit1 \ No newline at end of file +commit1 +commit2 \ No newline at end of file ------------------------------------------------------------------------ r2 | test | 2016-03-04 03:14:34 +0900 (Fri, 04 Mar 2016) | 1 line commit1 Index: .project =================================================================== --- .project (revision 0) +++ .project (revision 2) @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>test</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + </buildSpec> + <natures> + </natures> +</projectDescription> Property changes on: .project ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: file1.txt =================================================================== --- file1.txt (revision 0) +++ file1.txt (revision 2) @@ -0,0 +1 @@ +commit1 \ No newline at end of file Property changes on: file1.txt ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property ------------------------------------------------------------------------ r1 | test | 2016-03-04 03:12:54 +0900 (Fri, 04 Mar 2016) | 1 line ------------------------------------------------------------------------
これに対して、ISVNEditorがどんな呼ばれ方をするのか。 各メソッドに呼ばれたメソッド名とパラメータを簡単に出力するだけの実装をして実行してみたところ、以下のような出力が得られた。
#targetRevision start > [rev.3] #openRoot start > [rev.3] #openDir start > trunk[rev.3] #changeDirProperty start > svn:wc:ra_dav:version-url /svn/test/!svn/ver/3/trunk #changeDirProperty start > svn:entry:committed-rev 3 #changeDirProperty start > svn:entry:committed-date 2016-03-03T18:15:19.061137Z #changeDirProperty start > svn:entry:last-author test #changeDirProperty start > svn:entry:uuid 5025b694-87bc-4570-9e45-8a2bcb52a122 #addFile start > trunk/file2.txt #changeFileProperty start > trunk/file2.txt svnkit:entry:sha1-checksum 54563f95fefa691baa82a522156322c21f7d6df3 #changeFileProperty start > trunk/file2.txt svn:wc:ra_dav:version-url /svn/test/!svn/ver/3/trunk/file2.txt #changeFileProperty start > trunk/file2.txt svn:entry:committed-rev 3 #changeFileProperty start > trunk/file2.txt svn:entry:committed-date 2016-03-03T18:15:19.061137Z #changeFileProperty start > trunk/file2.txt svn:entry:last-author test #changeFileProperty start > trunk/file2.txt svn:entry:uuid 5025b694-87bc-4570-9e45-8a2bcb52a122 #changeFileProperty start > trunk/file2.txt svn:mime-type text/plain #applyTextDelta start > trunk/file2.txt #textDeltaChunk start > trunk/file2.txt 0:0:7:1:7:8:0 #textDeltaEnd start > trunk/file2.txt #closeFile start > trunk/file2.txt #addFile start > trunk/.project #changeFileProperty start > trunk/.project svnkit:entry:sha1-checksum 4d0a7da34b1a6f2e1416d746bf268c1137453e14 #changeFileProperty start > trunk/.project svn:wc:ra_dav:version-url /svn/test/!svn/ver/2/trunk/.project #changeFileProperty start > trunk/.project svn:entry:committed-rev 2 #changeFileProperty start > trunk/.project svn:entry:committed-date 2016-03-03T18:14:34.687289Z #changeFileProperty start > trunk/.project svn:entry:last-author test #changeFileProperty start > trunk/.project svn:entry:uuid 5025b694-87bc-4570-9e45-8a2bcb52a122 #changeFileProperty start > trunk/.project svn:mime-type text/plain #applyTextDelta start > trunk/.project #textDeltaChunk start > trunk/.project 0:0:208:3:208:211:0 #textDeltaEnd start > trunk/.project #closeFile start > trunk/.project #addFile start > trunk/file1.txt #changeFileProperty start > trunk/file1.txt svnkit:entry:sha1-checksum 994c650e0954fd76b6859dae6d87caf2fad19e35 #changeFileProperty start > trunk/file1.txt svn:wc:ra_dav:version-url /svn/test/!svn/ver/3/trunk/file1.txt #changeFileProperty start > trunk/file1.txt svn:entry:committed-rev 3 #changeFileProperty start > trunk/file1.txt svn:entry:committed-date 2016-03-03T18:15:19.061137Z #changeFileProperty start > trunk/file1.txt svn:entry:last-author test #changeFileProperty start > trunk/file1.txt svn:entry:uuid 5025b694-87bc-4570-9e45-8a2bcb52a122 #changeFileProperty start > trunk/file1.txt svn:mime-type text/plain #applyTextDelta start > trunk/file1.txt #textDeltaChunk start > trunk/file1.txt 0:0:16:1:16:17:0 #textDeltaEnd start > trunk/file1.txt #closeFile start > trunk/file1.txt #closeDir start > #closeDir start > #closeEdit start >
これは面倒そう!
ざっと見る限り、コミットされているファイルの内容が見えない。
これはtextDeltaChunk
の引数に渡されるSVNDiffWindow
オブジェクトがその情報を持っている。
適当に吐き出してみたところSVNヘッダ+ファイルの内容のバイナリストリームを持っているっぽい。
ということは、その内容を指定のパスに吐き出してやれば(checkoutだけど)export相当のことはできるようになるのかも。
今回はこの辺で。