1# ==================================================================== 2# Licensed to the Apache Software Foundation (ASF) under one 3# or more contributor license agreements. See the NOTICE file 4# distributed with this work for additional information 5# regarding copyright ownership. The ASF licenses this file 6# to you under the Apache License, Version 2.0 (the 7# "License"); you may not use this file except in compliance 8# with the License. You may obtain a copy of the License at 9# 10# http://www.apache.org/licenses/LICENSE-2.0 11# 12# Unless required by applicable law or agreed to in writing, 13# software distributed under the License is distributed on an 14# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15# KIND, either express or implied. See the License for the 16# specific language governing permissions and limitations 17# under the License. 18# ==================================================================== 19 20require "English" 21require "tempfile" 22require "svn/error" 23require "svn/util" 24require "svn/core" 25require "svn/repos" 26require "svn/ext/ra" 27 28module Svn 29 module Ra 30 Util.set_constants(Ext::Ra, self) 31 Util.set_methods(Ext::Ra, self) 32 33 @@ra_pool = Svn::Core::Pool.new 34 Ra.initialize(@@ra_pool) 35 36 class << self 37 def modules 38 print_modules("") 39 end 40 end 41 42 Session = SWIG::TYPE_p_svn_ra_session_t 43 44 class Session 45 class << self 46 def open(url, config=nil, callbacks=nil) 47 pool = Core::Pool.new 48 session = Ra.open2(url, callbacks, config || Svn::Core::Config.get, pool) 49 session.instance_variable_set(:@pool, pool) 50 return session unless block_given? 51 begin 52 yield session 53 ensure 54 session.close 55 end 56 end 57 end 58 59 def close 60 @pool.destroy 61 end 62 63 def latest_revnum 64 Ra.get_latest_revnum(self) 65 end 66 alias latest_revision latest_revnum 67 68 def dated_revision(time) 69 Ra.get_dated_revision(self, time.to_apr_time) 70 end 71 72 def set_prop(name, value, rev=nil) 73 Ra.change_rev_prop(self, rev || latest_revnum, name, value) 74 end 75 76 def []=(name, *args) 77 value = args.pop 78 set_prop(name, value, *args) 79 value 80 end 81 82 def proplist(rev=nil) 83 Ra.rev_proplist(self, rev || latest_revnum) 84 end 85 alias properties proplist 86 87 def prop(name, rev=nil) 88 Ra.rev_prop(self, rev || latest_revnum, name) 89 end 90 alias [] prop 91 92 def commit_editor(log_msg, lock_tokens={}, keep_lock=false) 93 callback = Proc.new do |new_revision, date, author| 94 yield(new_revision, date, author) 95 end 96 editor, editor_baton = Ra.get_commit_editor(self, log_msg, callback, 97 lock_tokens, keep_lock) 98 editor.baton = editor_baton 99 [editor, editor_baton] 100 end 101 102 def commit_editor2(log_msg_or_rev_props, lock_tokens={}, 103 keep_lock=false, &callback) 104 if log_msg_or_rev_props.is_a?(Hash) 105 rev_props = log_msg_or_rev_props 106 else 107 rev_props = {Svn::Core::PROP_REVISION_LOG => log_msg_or_rev_props} 108 end 109 editor, editor_baton = Ra.get_commit_editor3(self, rev_props, callback, 110 lock_tokens, keep_lock) 111 editor.baton = editor_baton 112 editor 113 end 114 115 def file(path, rev=nil) 116 output = StringIO.new 117 rev ||= latest_revnum 118 fetched_rev, props = Ra.get_file(self, path, rev, output) 119 output.rewind 120 props_filter(props) 121 [output.read, props] 122 end 123 124 def dir(path, rev=nil, fields=nil) 125 rev ||= latest_revnum 126 fields ||= Core::DIRENT_ALL 127 entries, fetched_rev, props = Ra.get_dir2(self, path, rev, fields) 128 props_filter(props) 129 [entries, props] 130 end 131 132 def update(revision_to_update_to, update_target, 133 editor, editor_baton, depth=nil, &block) 134 editor.baton = editor_baton 135 update2(revision_to_update_to, update_target, 136 editor, depth, &block) 137 end 138 139 def update2(revision_to_update_to, update_target, editor, depth=nil, 140 send_copyfrom_args=nil) 141 reporter, reporter_baton = Ra.do_update2(self, revision_to_update_to, 142 update_target, depth, 143 send_copyfrom_args, editor) 144 reporter.baton = reporter_baton 145 if block_given? 146 yield(reporter) 147 reporter.finish_report 148 nil 149 else 150 reporter 151 end 152 end 153 154 def switch(revision_to_switch_to, switch_target, switch_url, 155 editor, editor_baton, depth=nil, &block) 156 editor.baton = editor_baton 157 switch2(revision_to_switch_to, switch_target, switch_url, 158 editor, depth, &block) 159 end 160 161 def switch2(revision_to_switch_to, switch_target, switch_url, 162 editor, depth=nil) 163 reporter, reporter_baton = Ra.do_switch2(self, revision_to_switch_to, 164 switch_target, depth, 165 switch_url, editor) 166 reporter.baton = reporter_baton 167 if block_given? 168 yield(reporter) 169 reporter.finish_report 170 nil 171 else 172 reporter 173 end 174 end 175 176 def status(revision, status_target, editor, editor_baton, 177 recurse=true, &block) 178 editor.baton = editor_baton 179 status2(revision, status_target, editor, recurse, &block) 180 end 181 182 def status2(revision, status_target, editor, recurse=true) 183 reporter, reporter_baton = Ra.do_status2(self, status_target, 184 revision, recurse, editor) 185 reporter.baton = reporter_baton 186 if block_given? 187 yield(reporter) 188 reporter.finish_report 189 nil 190 else 191 reporter 192 end 193 end 194 195 def diff(rev, target, versus_url, editor, 196 depth=nil, ignore_ancestry=true, text_deltas=true) 197 args = [self, rev, target, depth, ignore_ancestry, 198 text_deltas, versus_url, editor] 199 reporter, baton = Ra.do_diff3(*args) 200 reporter.baton = baton 201 reporter 202 end 203 204 def log(paths, start_rev, end_rev, limit, 205 discover_changed_paths=true, 206 strict_node_history=false) 207 paths = [paths] unless paths.is_a?(Array) 208 receiver = Proc.new do |changed_paths, revision, author, date, message| 209 yield(changed_paths, revision, author, date, message) 210 end 211 Ra.get_log(self, paths, start_rev, end_rev, limit, 212 discover_changed_paths, strict_node_history, 213 receiver) 214 end 215 216 def check_path(path, rev=nil) 217 Ra.check_path(self, path, rev || latest_revnum) 218 end 219 220 def stat(path, rev=nil) 221 Ra.stat(self, path, rev || latest_revnum) 222 end 223 224 def uuid 225 Ra.get_uuid(self) 226 end 227 228 def repos_root 229 Ra.get_repos_root(self) 230 end 231 232 def locations(path, location_revisions, peg_revision=nil) 233 peg_revision ||= latest_revnum 234 Ra.get_locations(self, path, peg_revision, location_revisions) 235 end 236 237 def file_revs(path, start_rev, end_rev=nil) 238 args = [path, start_rev, end_rev] 239 if block_given? 240 revs = file_revs2(*args) do |path, rev, rev_props, prop_diffs| 241 yield(path, rev, rev_props, Util.hash_to_prop_array(prop_diffs)) 242 end 243 else 244 revs = file_revs2(*args) 245 end 246 revs.collect do |path, rev, rev_props, prop_diffs| 247 [path, rev, rev_props, Util.hash_to_prop_array(prop_diffs)] 248 end 249 end 250 251 def file_revs2(path, start_rev, end_rev=nil) 252 end_rev ||= latest_revnum 253 revs = [] 254 handler = Proc.new do |path, rev, rev_props, prop_diffs| 255 revs << [path, rev, rev_props, prop_diffs] 256 yield(path, rev, rev_props, prop_diffs) if block_given? 257 end 258 Ra.get_file_revs(self, path, start_rev, end_rev, handler) 259 revs 260 end 261 262 def lock(path_revs, comment=nil, steal_lock=false) 263 lock_func = Proc.new do |path, do_lock, lock, ra_err| 264 yield(path, do_lock, lock, ra_err) 265 end 266 Ra.lock(self, path_revs, comment, steal_lock, lock_func) 267 end 268 269 def unlock(path_tokens, break_lock=false, &lock_func) 270 Ra.unlock(self, path_tokens, break_lock, lock_func) 271 end 272 273 def get_lock(path) 274 Ra.get_lock(self, path) 275 end 276 277 def get_locks(path) 278 Ra.get_locks(self, path) 279 end 280 281 def replay(rev, low_water_mark, editor, send_deltas=true) 282 Ra.replay(self, rev, low_water_mark, send_deltas, editor) 283 end 284 285 def reparent(url) 286 Ra.reparent(self, url) 287 end 288 289 def mergeinfo(paths, revision=nil, inherit=nil, include_descendants=false) 290 paths = [paths] unless paths.is_a?(Array) 291 revision ||= Svn::Core::INVALID_REVNUM 292 info = Ra.get_mergeinfo(self, paths, revision, inherit, 293 include_descendants) 294 unless info.nil? 295 info.each_key do |key| 296 info[key] = Core::MergeInfo.new(info[key]) 297 end 298 end 299 info 300 end 301 302 private 303 def props_filter(props) 304 date_str = props[Svn::Core::PROP_ENTRY_COMMITTED_DATE] 305 if date_str 306 date = Time.parse_svn_format(date_str) 307 props[Svn::Core::PROP_ENTRY_COMMITTED_DATE] = date 308 end 309 props 310 end 311 end 312 313 class Reporter3 314 attr_accessor :baton 315 def set_path(path, revision, depth=nil, start_empty=true, 316 lock_token=nil) 317 Ra.reporter3_invoke_set_path(self, @baton, path, revision, 318 depth, start_empty, lock_token) 319 end 320 321 def delete_path(path) 322 Ra.reporter3_invoke_delete_path(self, @baton, path) 323 end 324 325 def link_path(path, url, revision, depth=nil, 326 start_empty=true, lock_token=nil) 327 Ra.reporter3_invoke_link_path(self, @baton, path, url, 328 revision, depth, start_empty, lock_token) 329 end 330 331 def finish_report 332 Ra.reporter3_invoke_finish_report(self, @baton) 333 end 334 335 def abort_report 336 Ra.reporter3_invoke_abort_report(self, @baton) 337 end 338 end 339 340 remove_const(:Callbacks) 341 class Callbacks 342 include Core::Authenticatable 343 344 def initialize(auth_baton=nil) 345 self.auth_baton = auth_baton || Core::AuthBaton.new 346 end 347 348 def open_tmp_file 349 tmp = Tempfile.new("Svn::Ra") 350 path = tmp.path 351 tmp.close(true) 352 path 353 end 354 355 def get_wc_prop(relpath, name) 356 nil 357 end 358 359 def set_wc_prop(path, name, value) 360 end 361 362 def push_wc_prop(path, name, value) 363 end 364 365 def invalidate_wc_props(path, name) 366 end 367 368 def progress_func(progress, total) 369 end 370 end 371 end 372end 373