ruby で subversion を扱う実験
subversion-rubybindings というのがあるのを知った。
インストールは macport で。
$ sudo port install subversion-rubybindings
インストールできたことの確認。
$ ruby -rsvn/client -e 'p Svn::Client::Context.new.methods'
["log_message", "prop_list", "revprop_set", "pd", "methods", "method", "rm", "praise", "taint", "rpl", "instance_variable_defined?", "plist", "cleanup", "status", "commit", "rpset", "propget", "add_ssl_server_trust_prompt_provider", "__id__", "singleton_methods", "add", "rm_f", "add_simple_provider", "mkdir", "annotate", "object_id", "mv", "add_simple_prompt_provider", "respond_to?", "export", "nil?", "update", "pl", "blame", "lock", "add_username_provider", "rps", "__send__", "switch", "protected_methods", "merge_peg", "tainted?", "mv_f", "list", "ann", "prop_set", "untaint", "st", "instance_of?", "diff_summarize", "equal?", "copy", "set_notify_func", "relocate", "revprop_del", "display", "prop_get", "add_ssl_client_cert_prompt_provider", "private_methods", "hash", "diff", "send", "revprop", "url_from_path", "pset", "kind_of?", "freeze", "eql?", "merge", "add_ssl_client_cert_file_provider", "id", "rpdel", "pget", "public_methods", "instance_eval", "revprop_get", "ps", "uuid_from_path", "is_a?", "diff_summarize_peg", "ls", "unlock", "type", "ci", "rpd", "pg", "add_ssl_client_cert_pw_prompt_provider", "cat", "instance_variables", "up", "co", "rp", "progress_func", "frozen?", "log_msg_func2", "log", "propdel", "to_a", "progress_func=", "log_msg_func2=", "set_cancel_func", "revert", "add_ssl_client_cert_pw_file_provider", "class", "revprop_list", "delete", "config", "proplist", "_auth_baton", "instance_variable_get", "import", "==", "rpget", "progress_baton", "log_msg_baton2", "===", "uuid_from_url", "config=", "prop_del", "to_s", "extend", "del", "progress_baton=", "cp", "log_msg_baton2=", "info", "resolved", "diff_peg", "clone", "set_log_msg_func", "auth_baton", "instance_variable_set", "=~", "rpg", "open_ra_session", "auth_baton=", "pdel", "add_username_prompt_provider", "remove", "inspect", "move", "checkout", "propset", "add_ssl_server_trust_file_provider", "dup", "rplist"]
インストールされたバージョンはこれだ。
$ port installed | grep subversion
subversion @1.4.4_0 (active)
subversion-rubybindings @1.4.4_0 (active)
参照:
http://svn.collab.net/viewvc/svn/trunk/subversion/bindings/swig/ruby/?sortby=file#dirlist
svn の cimmit, diff, status などすべての操作が出来るようだ。
(java-binding もある。
ruby, java のどちらをつかうにせよ、xfy/xvcd で subversion を扱うことができそうだ。
svn の gui クライアントをつくるとか、
xfy 作成したファイルや xvcd ファイルの 保存先を subversion にして履歴管理をできるようにする
とかが実現できるかも知れない。
リモートファイルシステムとして subversion を使うことで、共同編集が可能になるなどソーシャルな
ものができると考えている。
)
ruby-binding を利用したプログラム例を以下で見つけた。
- http://blog.wolfman.com/articles/2006/09/04/using-ruby-svn-bindings-to-get-file-status
> > Using Ruby SVN bindings to get file status
しかし ここの記事中コードのままでは、次のようなエラーがでてしまう。
in `svn_client_status2': subversion/libsvn_subr/auth.c:176 No provider registered for 'svn.username' credentials (Svn::Error::AUTHN_NO_PROVIDER)
そこで
ctx.auth_baton[Svn::Core::AUTH_PARAM_DEFAULT_USERNAME] = ''
ctx.add_username_provider
ctx.add_simple_provider
といったコードを追加して、エラーを回避することができた。
最終的なプログラムと 実行例を示す。
$ cat status.rb
# See http://blog.wolfman.com/articles/2006/09/04/using-ruby-svn-bindings-to-get-file-status
# http://www.nabble.com/Ruby-bindings'-excessive-memory-usage-t726131.htmlrequire "svn/core"
require "svn/client"
require "svn/wc"
require "svn/repos"
require 'pp'# define Consts for all the numeric status values
NONE = 1
UNVERSIONED = 2
NORMAL = 3
ADDED = 4
MISSING = 5
DELETED = 6
REPLACED = 7
MODIFIED = 8
MERGED = 9
CONFLICTED = 10
IGNORED = 11
OBSTRUCTED = 12
EXTERNAL = 13
INCOMPLETE = 14
# I added these so I can amalgamate repo and local status
UPDATED = 15
MODIFIED_NEWER = 16
NEWFILE = 17$modes= { # Map status to English
NONE => "None",
UNVERSIONED => "unversioned",
NORMAL => "normal",
ADDED => "file added",
MISSING => "missing",
DELETED => "file removed",
REPLACED => "deleted and then re-added",
MODIFIED => "modified",
MERGED => "received repos mods",
CONFLICTED => "file modified and in conflict",
IGNORED => "ignored",
OBSTRUCTED => "unversioned resource is in the way of the versioned resource",
EXTERNAL => "unversioned path populated by an svn:external property",
INCOMPLETE => "directory doesn't contain a complete entries list",
UPDATED => "newer version in repository",
MODIFIED_NEWER => "modified and newer version in repository",
NEWFILE => "new file in repository",
nil => "Unknown status"
}# this amalgamates the most common status between local and repository
def compute_status(status)
# if modified in repo and localy
return MODIFIED_NEWER if status.repos_text_status == MODIFIED && status.text_status != NORMAL
# if added in repo and does not exist locally
return NEWFILE if status.repos_text_status == ADDED && status.text_status == NONE
# if repo is none then use local status
return status.text_status if status.text_status != NORMAL
# if normal locally but changed in repo
return UPDATED if status.repos_text_status == MODIFIED
# otherwise it must be normal
NORMAL
enddef showDate(time)
if (time == nil)
"nil"
elsif (time == 0)
"0"
else
Time.at(time/1000000).strftime('%Y/%m/%d %H:%M:%S %Z')
end
endctx = Svn::Client::Context.new()
ctx.auth_baton[Svn::Core::AUTH_PARAM_DEFAULT_USERNAME] = ''
ctx.add_username_provider
ctx.add_simple_providerproject = "/Users/kato/zzz/test2/svn-reps"
rev = ctx.status(project) do |path, status|
astat= compute_status(status)
puts "#{path}: #{status.text_status},#{status.repos_text_status} = #{$modes[astat]}"unless status.entry.nil?
puts(" name: #{status.entry.name}")
puts(" url: #{status.entry.url}")
puts(" repos: #{status.entry.repos }")
puts(" revision: #{status.entry.revision}")
puts(" kind: #{status.entry.kind}")
puts(" schedule: #{status.entry.schedule}")
puts(" deleted: #{status.entry.deleted}")
puts(" absent: #{status.entry.absent}")
puts(" incomplete: #{status.entry.incomplete}")
puts(" cmt_date: #{showDate(status.entry.cmt_date)}")
puts(" cmt_rev: #{status.entry.cmt_rev}")
puts(" cmt_author: #{status.entry.cmt_author}")
puts(" prop_time: #{status.entry.prop_time}")
puts(" text_time: #{showDate(status.entry.text_time)}")
end
end
実行させてみよう。まずは svn で状態を確認する。
$ svn status
? status.rb
! test02.txt
A status2.rb
作成した ruby プログラムで得られる状態がこれ。
$ ruby status.rb
/Users/kato/zzz/test2/svn-reps/test/status2.rb: 4,1 = file added
name: status2.rb
url: file:///usr/local/svn-reps/test/status2.rb
repos: file:///usr/local/svn-reps
revision: 0
kind: 1
schedule: 1
deleted: false
absent: false
incomplete: false
cmt_date: 0
cmt_rev: -1
cmt_author:
prop_time: 0
text_time: 0
/Users/kato/zzz/test2/svn-reps/test/test02.txt: 5,1 = missing
name: test02.txt
url: file:///usr/local/svn-reps/test/test02.txt
repos: file:///usr/local/svn-reps
revision: 47
kind: 1
schedule: 0
deleted: false
absent: false
incomplete: false
cmt_date: 2007/08/25 15:21:32 JST
cmt_rev: 47
cmt_author:
prop_time: 0
text_time: 2007/08/25 15:20:26 JST
/Users/kato/zzz/test2/svn-reps/test/status.rb: 2,1 = unversioned
3 ファイルの add, missing, unversioned の状態が svn コマンドと同様の取得できていることが判る。
他の参照記事:
- http://www.oneofthewolves.com/2007/03/06/ruby-subversion-bindings-finally-some-documentation/
> > One of the Wolves » Ruby Subversion Bindings. Finally Some Documentation.
- http://alcove.onlyconnect.jp/node/33
> > Ruby Subversion Binding : リポジトリの作成 | alcove
« ピックアップ:Macで打つ特殊文字ショートカット集, Windows XPのPCメーカーへの出荷は来年1月で終了, etc... | トップページ | ピックアップ:ブラウザだけで遊べる『World of Solitaire』,歩いていけばお台場は近い, etc... »
この記事へのコメントは終了しました。
« ピックアップ:Macで打つ特殊文字ショートカット集, Windows XPのPCメーカーへの出荷は来年1月で終了, etc... | トップページ | ピックアップ:ブラウザだけで遊べる『World of Solitaire』,歩いていけばお台場は近い, etc... »
コメント