Class: SvnWc::RepoAccess
- Inherits:
-
Object
- Object
- SvnWc::RepoAccess
- Defined in:
- lib/svn_wc.rb
Overview
class that provides API to (common) svn operations (working copy of a repo) also exposes the svn ruby bindings directly
It aims to provide (simple) client CLI type behavior, for working directory repository management. in an API
Constant Summary collapse
- VERSION =
'0.0.3'
Instance Attribute Summary collapse
-
#ctx ⇒ Object
readonly
Returns the value of attribute ctx.
-
#cur_file ⇒ Object
– TODO revist these ++.
-
#repos ⇒ Object
readonly
Returns the value of attribute repos.
-
#svn_pass ⇒ Object
– TODO revist these ++.
-
#svn_repo_config_file ⇒ Object
– TODO revist these ++.
-
#svn_repo_config_path ⇒ Object
– TODO revist these ++.
-
#svn_repo_master ⇒ Object
– TODO revist these ++.
-
#svn_repo_working_copy ⇒ Object
– TODO revist these ++.
-
#svn_user ⇒ Object
– TODO revist these ++.
Instance Method Summary collapse
-
#add(files = [], recurse = true, force = false, no_ignore = false) ⇒ Object
add entities to the repo.
-
#checkout ⇒ Object
(also: #co)
checkout.
-
#commit(files = [], msg = '') ⇒ Object
(also: #ci)
commit entities to the repository.
-
#delete(files = [], recurs = false) ⇒ Object
(also: #rm)
delete entities from the repository.
-
#diff(file = '', rev1 = '', rev2 = '') ⇒ Object
By Default compares current working directory file with ‘HEAD’ in repository (NOTE: does not yet support diff to previous revisions) – TODO support diffing previous revisions ++.
- #do_checkout(force = false) ⇒ Object
-
#info(file = '') ⇒ Object
get detailed repository info about a specific file or (by default) the entire repository – TODO - document all the params available from this command ++.
-
#initialize(conf = nil, checkout = false, force = false) ⇒ RepoAccess
constructor
initialization three optional parameters 1.
-
#list(wc_path = self.svn_repo_working_copy, rev = 'head', verbose = nil, depth = 'infinity') ⇒ Object
(also: #ls)
list (ls).
-
#list_entries(dir = self.svn_repo_working_copy, file = nil, verbose = false) ⇒ Object
Get list of all entries at (passed) dir level in repo use repo root if nothing passed .
-
#method_missing(sym, *args, &block) ⇒ Object
‘expose the abstraction’ introduce Delegation, if we don’t define the method pass it on to the ruby bindings.
-
#propset(type, files, dir_path = self.svn_repo_working_copy) ⇒ Object
currently supports type=‘ignore’ only – TODO support other propset’s ; also propget ++.
-
#revert(file_path = '') ⇒ Object
discard working copy changes, get current repository entry.
-
#set_conf(conf) ⇒ Object
set config file with abs path.
-
#setup_auth_baton(auth_baton) ⇒ Object
:nodoc:.
-
#status(path = '') ⇒ Object
(also: #stat)
get status on dir/file path.
-
#svn_session(commit_msg = String.new) ⇒ Object
svn session set up – from svn.collab.net/repos/svn/trunk/subversion/bindings/swig/ruby/test/util.rb ++.
-
#update(paths = []) ⇒ Object
(also: #up)
update local working copy with most recent (remote) repo version (does not resolve conflict - or alert or anything at the moment).
Constructor Details
#initialize(conf = nil, checkout = false, force = false) ⇒ RepoAccess
initialization three optional parameters
-
Path to yaml conf file (default used, if none specified)
-
Do a checkout from remote svn repo (usually, necessary with first time set up only)
-
Force. Overwrite anything that may be preventing a checkout
144 145 146 147 148 149 150 |
# File 'lib/svn_wc.rb', line 144 def initialize(conf=nil, checkout=false, force=false) set_conf(conf) if conf do_checkout(force) if checkout == true # instance var of out open repo session @ctx = svn_session end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(sym, *args, &block) ⇒ Object
‘expose the abstraction’ introduce Delegation, if we don’t define the method pass it on to the ruby bindings.
(yup, this is probably asking for trouble)
159 160 161 |
# File 'lib/svn_wc.rb', line 159 def method_missing(sym, *args, &block) @ctx.send sym, *args, &block end |
Instance Attribute Details
#ctx ⇒ Object (readonly)
Returns the value of attribute ctx.
169 170 171 |
# File 'lib/svn_wc.rb', line 169 def ctx @ctx end |
#cur_file ⇒ Object
– TODO revist these ++
166 167 168 |
# File 'lib/svn_wc.rb', line 166 def cur_file @cur_file end |
#repos ⇒ Object (readonly)
Returns the value of attribute repos.
169 170 171 |
# File 'lib/svn_wc.rb', line 169 def repos @repos end |
#svn_pass ⇒ Object
– TODO revist these ++
166 167 168 |
# File 'lib/svn_wc.rb', line 166 def svn_pass @svn_pass end |
#svn_repo_config_file ⇒ Object
– TODO revist these ++
166 167 168 |
# File 'lib/svn_wc.rb', line 166 def svn_repo_config_file @svn_repo_config_file end |
#svn_repo_config_path ⇒ Object
– TODO revist these ++
166 167 168 |
# File 'lib/svn_wc.rb', line 166 def svn_repo_config_path @svn_repo_config_path end |
#svn_repo_master ⇒ Object
– TODO revist these ++
166 167 168 |
# File 'lib/svn_wc.rb', line 166 def svn_repo_master @svn_repo_master end |
#svn_repo_working_copy ⇒ Object
– TODO revist these ++
166 167 168 |
# File 'lib/svn_wc.rb', line 166 def svn_repo_working_copy @svn_repo_working_copy end |
#svn_user ⇒ Object
– TODO revist these ++
166 167 168 |
# File 'lib/svn_wc.rb', line 166 def svn_user @svn_user end |
Instance Method Details
#add(files = [], recurse = true, force = false, no_ignore = false) ⇒ Object
add entities to the repo
pass a single entry or list of file(s) with fully qualified path, which must exist,
raises RepoAccessError if something goes wrong
– “svn/client.rb” Svn::Client
def add(path, recurse=true, force=false, no_ignore=false)
Client.add3(path, recurse, force, no_ignore, self)
end
++
279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 |
# File 'lib/svn_wc.rb', line 279 def add(files=[], recurse=true, force=false, no_ignore=false) # TODO make sure args are what is expected for all methods raise ArgumentError, 'files is empty' unless files svn_session() do |svn| begin files.each do |ef| svn.add(ef, recurse, force, no_ignore) end #rescue Svn::Error::ENTRY_EXISTS, # Svn::Error::AuthnNoProvider, # #Svn::Error::WcNotDirectory, # Svn::Error::SvnError => e rescue Exception => excp raise RepoAccessError, "Add Failed: #{excp.}" end end end |
#checkout ⇒ Object Also known as: co
checkout
create a local working copy of a remote svn repo (creates dir if not exist) raises RepoAccessError if something goes wrong
224 225 226 227 228 229 230 231 232 233 234 235 |
# File 'lib/svn_wc.rb', line 224 def checkout begin svn_session() do |ctx| ctx.checkout(@svn_repo_master, @svn_repo_working_copy) end #rescue Svn::Error::RaLocalReposOpenFailed, # Svn::Error::FsAlreadyExists, #rescue Errno::EACCES => e rescue Exception => err raise RepoAccessError, err. end end |
#commit(files = [], msg = '') ⇒ Object Also known as: ci
commit entities to the repository
params single or list of files (full relative path (to repo root) needed)
optional message
raises RepoAccessError if something goes wrong returns the revision of the commmit
335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 |
# File 'lib/svn_wc.rb', line 335 def commit(files=[], msg='') if files and files.empty? or files.nil? then files = self.svn_repo_working_copy end rev = '' svn_session(msg) do |svn| begin rev = svn.commit(files).revision #rescue Svn::Error::AuthnNoProvider, # #Svn::Error::WcNotDirectory, # Svn::Error::IllegalTarget, # #Svn::Error::EntryNotFound => e # Exception => e rescue Exception => err raise RepoAccessError, "Commit Failed: #{err.}" end end rev end |
#delete(files = [], recurs = false) ⇒ Object Also known as: rm
delete entities from the repository
pass single entity or list of files with fully qualified path, which must exist,
raises RepoAccessError if something goes wrong
308 309 310 311 312 313 314 315 316 317 318 319 320 |
# File 'lib/svn_wc.rb', line 308 def delete(files=[], recurs=false) svn_session() do |svn| begin svn.delete(files) #rescue Svn::Error::AuthnNoProvider, # #Svn::Error::WcNotDirectory, # Svn::Error::ClientModified, # Svn::Error::SvnError => e rescue Exception => err raise RepoAccessError, "Delete Failed: #{err.}" end end end |
#diff(file = '', rev1 = '', rev2 = '') ⇒ Object
By Default compares current working directory file with ‘HEAD’ in repository (NOTE: does not yet support diff to previous revisions) – TODO support diffing previous revisions ++
846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 |
# File 'lib/svn_wc.rb', line 846 def diff(file='', rev1='', rev2='') raise ArgumentError, 'file list empty or nil' unless file and file.size raise RepoAccessError, "Diff requires an absolute path to a file" \ unless File.exists? file # can also use new (updated) svn.status(f)[0][:repo_rev] rev = info(file)[:rev] out_file = Tempfile.new("svn_diff") err_file = Tempfile.new("svn_diff") svn_session() do |svn| begin svn.diff([], file, rev, file, "WORKING", out_file.path, err_file.path) rescue Exception => e #Svn::Error::EntryNotFound => e raise RepoAccessError, "Diff Failed: #{e.}" end end out_file.readlines end |
#do_checkout(force = false) ⇒ Object
189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 |
# File 'lib/svn_wc.rb', line 189 def do_checkout(force=false) if @svn_repo_working_copy.nil? raise RepoAccessError, 'conf file not loaded! - Fatal Error' end ## do checkout if not exists at specified local path if force begin #FileUtils.rm_rf @svn_repo_working_copy FileUtils.mkdir_p @svn_repo_working_copy, :force => true rescue end else if File.directory? @svn_repo_working_copy raise RepoAccessError, 'target local directory ' << \ "[#{@svn_repo_working_copy}] exists, please remove" << \ 'or specify another directory' end begin FileUtils.mkdir_p @svn_repo_working_copy rescue Errno::EACCES => err raise RepoAccessError, err. end end checkout end |
#info(file = '') ⇒ Object
get detailed repository info about a specific file or (by default) the entire repository – TODO - document all the params available from this command ++
753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 |
# File 'lib/svn_wc.rb', line 753 def info(file='') if file and not (file.empty? or file.nil? or file.class != String) wc_path = file else wc_path = self.svn_repo_working_copy end r_info = Hash.new begin @ctx.info(wc_path) do |path, type| r_info[:last_changed_author] = type. r_info[:last_changed_rev] = type.last_changed_rev r_info[:last_changed_date] = type.last_changed_date r_info[:conflict_old] = type.conflict_old #r_info[:tree_conflict] = type.tree_conflict r_info[:repos_root_url] = type.repos_root_url r_info[:repos_root_URL] = type.repos_root_URL r_info[:copyfrom_rev] = type.copyfrom_rev r_info[:copyfrom_url] = type.copyfrom_url #r_info[:working_size] = type.working_size r_info[:conflict_wrk] = type.conflict_wrk r_info[:conflict_new] = type.conflict_new r_info[:has_wc_info] = type.has_wc_info r_info[:repos_UUID] = type.repos_UUID r_info[:checksum] = type.checksum r_info[:prop_time], r_info[:text_time] = type.prop_time, type.text_time r_info[:prejfile], r_info[:schedule] = type.prejfile, type.schedule r_info[:taguri], r_info[:lock] = type.taguri, type.lock r_info[:rev], r_info[:dup] = type.rev, type.dup r_info[:url], r_info[:URL] = type.url, type.URL #r_info[:changelist] = type.changelist #r_info[:depth], r_info[:size] = type.depth, type.size end #rescue Svn::Error::WcNotDirectory => e # #Svn::Error::RaIllegalUrl, # #Svn::Error::EntryNotFound, # #Svn::Error::RaIllegalUrl, # #Svn::Error::WC_NOT_DIRECTORY # #Svn::Error::WcNotDirectory => e rescue Exception => e raise RepoAccessError, "cant get info: #{e.}" end r_info end |
#list(wc_path = self.svn_repo_working_copy, rev = 'head', verbose = nil, depth = 'infinity') ⇒ Object Also known as: ls
list (ls)
list all entries at (passed) dir level in repo use repo root if not specified
no repo/file info is returned, just a list of files, with abs_path
optional
564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 |
# File 'lib/svn_wc.rb', line 564 def list(wc_path=self.svn_repo_working_copy, rev='head', verbose=nil, depth='infinity') paths = [] svn_session() do |svn| begin svn.list(wc_path, rev, verbose, depth) do |path, dirent, lock, abs_path| #paths.push(path.empty? ? abs_path : File.join(abs_path, path)) f_rec = Hash.new f_rec[:entry] = (path.empty? ? abs_path : File.join(abs_path, path)) f_rec[:last_changed_rev] = dirent.created_rev paths.push f_rec end #rescue Svn::Error::AuthnNoProvider, # #Svn::Error::WcNotDirectory, # Svn::Error::FS_NO_SUCH_REVISION, # #Svn::Error::EntryNotFound => e # Exception => e rescue Exception => e raise RepoAccessError, "List Failed: #{e.}" end end paths end |
#list_entries(dir = self.svn_repo_working_copy, file = nil, verbose = false) ⇒ Object
Get list of all entries at (passed) dir level in repo use repo root if nothing passed
params [String, String, String] optional params, defaults to repo root
if file passed, get specifics on file, else get
into on all in dir path passed
3rd arg is verbose flag, if set to true, lot's
more info is returned about the object
returns [Array] list of entries in svn repository
616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 |
# File 'lib/svn_wc.rb', line 616 def list_entries(dir=self.svn_repo_working_copy, file=nil, verbose=false) @entry_list, @show, @verbose = [], true, verbose Svn::Wc::AdmAccess.open(nil, dir, false, 5) do |adm| @adm = adm if file.nil? #also see walk_entries (in svn bindings) has callback adm.read_entries.keys.sort.each { |ef| next unless ef.length >= 1 # why this check and not file.exists? f_path = File.join(dir, ef) if File.file? f_path _collect_get_entry_info(f_path) elsif File.directory? f_path _walk_entries(f_path) end } else _collect_get_entry_info(file) end end #XXX do we want nil or empty on no entries, choosing empty for now #@entry_list unless @entry_list.empty? @entry_list end |
#propset(type, files, dir_path = self.svn_repo_working_copy) ⇒ Object
currently supports type=‘ignore’ only – TODO support other propset’s ; also propget ++
871 872 873 874 875 876 877 878 879 880 881 882 883 884 |
# File 'lib/svn_wc.rb', line 871 def propset(type, files, dir_path=self.svn_repo_working_copy) raise RepoAccessError, '"ignore" is only supported propset' \ unless type == 'ignore' svn_session() do |svn| files.each do |ef| begin svn.propset(Svn::Core::PROP_IGNORE, ef, dir_path) rescue Exception => e #Svn::Error::EntryNotFound => e raise RepoAccessError, "Propset (Ignore) Failed: #{e.}" end end end end |
#revert(file_path = '') ⇒ Object
discard working copy changes, get current repository entry
836 837 838 839 |
# File 'lib/svn_wc.rb', line 836 def revert(file_path='') if file_path.empty? then file_path = self.svn_repo_working_copy end svn_session() { |svn| svn.revert(file_path) } end |
#set_conf(conf) ⇒ Object
set config file with abs path
174 175 176 177 178 179 180 181 182 183 184 185 186 |
# File 'lib/svn_wc.rb', line 174 def set_conf(conf) begin conf = load_conf(conf) @svn_user = conf['svn_user'] @svn_pass = conf['svn_pass'] @svn_repo_master = conf['svn_repo_master'] @svn_repo_working_copy = conf['svn_repo_working_copy'] @svn_repo_config_path = conf['svn_repo_config_path'] Svn::Core::Config.ensure(@svn_repo_config_path) rescue Exception => e raise RepoAccessError, 'errors loading conf file' end end |
#setup_auth_baton(auth_baton) ⇒ Object
:nodoc:
922 923 924 925 |
# File 'lib/svn_wc.rb', line 922 def setup_auth_baton(auth_baton) # :nodoc: auth_baton[Svn::Core::AUTH_PARAM_CONFIG_DIR] = @svn_repo_config_path auth_baton[Svn::Core::AUTH_PARAM_DEFAULT_USERNAME] = @svn_user end |
#status(path = '') ⇒ Object Also known as: stat
get status on dir/file path.
if nothing passed, does repo root
– TODO/XXX add optional param to return results as a data structure (current behavior) or as a puts ‘M’ File (like the CLI version, have the latter as the default, this avoids the awkward s.status(file)[:status] notation one could just say: s.status file and get the list displayed on stdout ++
455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 |
# File 'lib/svn_wc.rb', line 455 def status(path='') raise ArgumentError, 'path not a String' if ! (path or path.class == String) if path and path.empty? then path = self.svn_repo_working_copy end status_info = Hash.new if File.file?(path) # is single file path file = path status_info = do_status(File.dirname(path), file) elsif File.directory?(path) status_info = do_status(path) else raise RepoAccessError, "Arg is not a file or directory" end status_info end |
#svn_session(commit_msg = String.new) ⇒ Object
svn session set up – from svn.collab.net/repos/svn/trunk/subversion/bindings/swig/ruby/test/util.rb ++
891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 |
# File 'lib/svn_wc.rb', line 891 def svn_session(commit_msg = String.new) # :nodoc: ctx = Svn::Client::Context.new # Function for commit messages ctx.set_log_msg_func do |items| [true, commit_msg] end # don't fail on non CA signed ssl server ctx.add_ssl_server_trust_file_provider setup_auth_baton(ctx.auth_baton) ctx.add_username_provider # username and password ctx.add_simple_prompt_provider(0) do |cred, realm, username, may_save| cred.username = @svn_user cred.password = @svn_pass cred.may_save = false end return ctx unless block_given? begin yield ctx #ensure # warning!? # ctx.destroy end end |
#update(paths = []) ⇒ Object Also known as: up
update local working copy with most recent (remote) repo version (does not resolve conflict - or alert or anything at the moment)
if nothing passed, does repo root
params optional: single or list of files (full relative path (to repo root) needed)
raises RepoAccessError if something goes wrong
alias up
367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 |
# File 'lib/svn_wc.rb', line 367 def update(paths=[]) if paths.empty? then paths = self.svn_repo_working_copy end #XXX update is a bummer, just returns the rev num, not affected files #(svn command line up, also returns altered/new files - mimic that) # hence our inplace hack (_pre/_post update_entries) # # unfortunetly, we cant use 'Repos', only works on local filesystem repo # (NOT remote) #p Svn::Repos.open(@svn_repo_master) # Svn::Repos.open('/tmp/svnrepo') _pre_update_entries rev = String.new svn_session() do |svn| begin #p svn.status paths rev = svn.update(paths, nil, 'infinity') #rescue Svn::Error::AuthnNoProvider, # #Svn::Error::FS_NO_SUCH_REVISION, # #Svn::Error::WcNotDirectory, # #Svn::Error::EntryNotFound => e # Exception => e rescue Exception => err raise RepoAccessError, "Update Failed: #{err.}" end end _post_update_entries return rev, @modified_entries end |